Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 2x 2x 2x 10x 15x 10008x 1x 1x 1x 10008x | import { Injectable } from '@nestjs/common';
const MAX_ENTRIES = 10_000;
/**
* Consumer-side idempotency: remembers which eventIds were fully processed so
* an at-least-once redelivery doesn't send the same notification twice.
*
* In-memory on purpose — one instance, bounded, zero infrastructure. The
* documented production upgrade is a shared store (Redis SETNX or a DB unique
* insert, as the audit projection already does); the seam stays the same.
*/
@Injectable()
export class ProcessedEventsStore {
private readonly seen = new Set<string>();
has(eventId: string): boolean {
return this.seen.has(eventId);
}
/** Call only after the side effect succeeded — marking first would turn a
* crash between mark and send into a silently lost notification. */
mark(eventId: string): void {
if (this.seen.size >= MAX_ENTRIES) {
// Sets iterate in insertion order, so the first entry is the oldest.
for (const oldest of this.seen) {
this.seen.delete(oldest);
break;
}
}
this.seen.add(eventId);
}
}
|