@russ-b/nestjs-common-tools 2.2.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -3
- package/dist/modules/outbox/entities/outbox-event.entity.d.ts +2 -0
- package/dist/modules/outbox/entities/outbox-event.entity.js +9 -0
- package/dist/modules/outbox/entities/outbox-event.entity.js.map +1 -1
- package/dist/modules/outbox/services/base-worker.d.ts +1 -0
- package/dist/modules/outbox/services/base-worker.js +9 -1
- package/dist/modules/outbox/services/base-worker.js.map +1 -1
- package/dist/modules/outbox/services/outbox.service.d.ts +13 -2
- package/dist/modules/outbox/services/outbox.service.js +65 -11
- package/dist/modules/outbox/services/outbox.service.js.map +1 -1
- package/package.json +8 -10
package/README.md
CHANGED
|
@@ -612,11 +612,24 @@ await dataSource.transaction(async (manager) => {
|
|
|
612
612
|
await outboxService.createEvent(
|
|
613
613
|
'order.created',
|
|
614
614
|
{ orderId: order.id },
|
|
615
|
-
manager,
|
|
615
|
+
{ manager },
|
|
616
616
|
);
|
|
617
617
|
});
|
|
618
618
|
```
|
|
619
619
|
|
|
620
|
+
Create delayed events with `nextTryAt` when processing must not start before a known time. Pass `maxRetries` to override the global retry limit for a specific event:
|
|
621
|
+
|
|
622
|
+
```typescript
|
|
623
|
+
await outboxService.createEvent(
|
|
624
|
+
'order.reminder',
|
|
625
|
+
{ orderId: order.id },
|
|
626
|
+
{
|
|
627
|
+
nextTryAt: new Date(Date.now() + 5_000),
|
|
628
|
+
maxRetries: 3,
|
|
629
|
+
},
|
|
630
|
+
);
|
|
631
|
+
```
|
|
632
|
+
|
|
620
633
|
### Process events
|
|
621
634
|
|
|
622
635
|
Extend `BaseWorker` and implement event selection plus handling.
|
|
@@ -647,6 +660,35 @@ export class OrderCreatedWorker extends BaseWorker {
|
|
|
647
660
|
|
|
648
661
|
Outbox delivery is at-least-once. Handlers must be idempotent, especially when they call external services or publish messages.
|
|
649
662
|
|
|
663
|
+
### Delay retries
|
|
664
|
+
|
|
665
|
+
Failed events are retried immediately by default. Override `getNextTryAt()` in a worker to delay the next attempt. While `nextTryAt` is in the future, `claimById()`, `claimPendingEvents()`, and `claimPendingEventsByTypes()` skip the pending event.
|
|
666
|
+
|
|
667
|
+
```typescript
|
|
668
|
+
@Injectable()
|
|
669
|
+
export class OrderCreatedWorker extends BaseWorker {
|
|
670
|
+
constructor(outboxService: OutboxService) {
|
|
671
|
+
super(outboxService);
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
getEvents(): Promise<OutboxEvent[]> {
|
|
675
|
+
return this.outboxService.claimPendingEvents('order.created');
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
async handle(event: OutboxEvent): Promise<void> {
|
|
679
|
+
// Send email, publish message, call another service, etc.
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
protected getNextTryAt(
|
|
683
|
+
event: OutboxEvent,
|
|
684
|
+
error: unknown,
|
|
685
|
+
nextRetryCount: number,
|
|
686
|
+
): Date | null {
|
|
687
|
+
return new Date(Date.now() + nextRetryCount * 60_000);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
```
|
|
691
|
+
|
|
650
692
|
### Cleanup processed events
|
|
651
693
|
|
|
652
694
|
`OutboxCleanupWorker` deletes processed events older than the configured `processedEventRetentionHours`. The library does not schedule it by itself, so wire it to your app scheduler. If retention should come from environment or config, pass it through `OutboxModule.forRootAsync`.
|
|
@@ -674,13 +716,13 @@ export class OutboxCleanupCron {
|
|
|
674
716
|
| Option | Default | Description |
|
|
675
717
|
| ------------------------------ | --------- | -------------------------------------------------------------- |
|
|
676
718
|
| `claimBatchSize` | `100` | Default number of events claimed per poll |
|
|
677
|
-
| `maxRetries` | `5` |
|
|
719
|
+
| `maxRetries` | `5` | Default retry limit when an event does not define its own `maxRetries` |
|
|
678
720
|
| `staleProcessingMinutes` | `5` | Processing events older than this are reset to pending |
|
|
679
721
|
| `resetStaleProcessingEvents` | `true` | Enables stale processing reset in `BaseWorker` |
|
|
680
722
|
| `maxConcurrentEvents` | unlimited | Limits parallel handler execution inside one worker cycle |
|
|
681
723
|
| `processedEventRetentionHours` | `24` | Default age used by `deleteProcessed()` |
|
|
682
724
|
|
|
683
|
-
The outbox entity uses PostgreSQL-specific column types and requires
|
|
725
|
+
The outbox entity uses PostgreSQL-specific column types and requires nullable `processing_started_at`, `next_try_at`, and `max_retries` columns for stale processing detection, delayed retries, and per-event retry limits.
|
|
684
726
|
|
|
685
727
|
## Entity Validator
|
|
686
728
|
|
|
@@ -5,8 +5,10 @@ export declare class OutboxEvent {
|
|
|
5
5
|
payload: Record<string, any>;
|
|
6
6
|
status: OutboxEventStatus;
|
|
7
7
|
retryCount: number;
|
|
8
|
+
maxRetries: number | null;
|
|
8
9
|
lastError: string | null;
|
|
9
10
|
createdAt: Date;
|
|
10
11
|
processingStartedAt: Date | null;
|
|
12
|
+
nextTryAt: Date | null;
|
|
11
13
|
processedAt: Date | null;
|
|
12
14
|
}
|
|
@@ -40,6 +40,10 @@ __decorate([
|
|
|
40
40
|
(0, typeorm_1.Column)({ name: 'retry_count', type: 'int', default: 0 }),
|
|
41
41
|
__metadata("design:type", Number)
|
|
42
42
|
], OutboxEvent.prototype, "retryCount", void 0);
|
|
43
|
+
__decorate([
|
|
44
|
+
(0, typeorm_1.Column)({ name: 'max_retries', type: 'int', nullable: true }),
|
|
45
|
+
__metadata("design:type", Object)
|
|
46
|
+
], OutboxEvent.prototype, "maxRetries", void 0);
|
|
43
47
|
__decorate([
|
|
44
48
|
(0, typeorm_1.Column)({ name: 'last_error', type: 'text', nullable: true }),
|
|
45
49
|
__metadata("design:type", Object)
|
|
@@ -57,6 +61,11 @@ __decorate([
|
|
|
57
61
|
}),
|
|
58
62
|
__metadata("design:type", Object)
|
|
59
63
|
], OutboxEvent.prototype, "processingStartedAt", void 0);
|
|
64
|
+
__decorate([
|
|
65
|
+
(0, typeorm_1.Index)(),
|
|
66
|
+
(0, typeorm_1.Column)({ type: 'timestamptz', name: 'next_try_at', nullable: true }),
|
|
67
|
+
__metadata("design:type", Object)
|
|
68
|
+
], OutboxEvent.prototype, "nextTryAt", void 0);
|
|
60
69
|
__decorate([
|
|
61
70
|
(0, typeorm_1.Column)({ type: 'timestamptz', name: 'processed_at', nullable: true }),
|
|
62
71
|
__metadata("design:type", Object)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outbox-event.entity.js","sourceRoot":"","sources":["../../../../src/modules/outbox/entities/outbox-event.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qCAMiB;AACjB,oCAA6C;AAGtC,IAAM,WAAW,GAAjB,MAAM,WAAW;
|
|
1
|
+
{"version":3,"file":"outbox-event.entity.js","sourceRoot":"","sources":["../../../../src/modules/outbox/entities/outbox-event.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qCAMiB;AACjB,oCAA6C;AAGtC,IAAM,WAAW,GAAjB,MAAM,WAAW;CA4CvB,CAAA;AA5CY,kCAAW;AAEtB;IADC,IAAA,uBAAa,EAAC,MAAM,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC;;uCAC1C;AAIX;IAFC,IAAA,eAAK,GAAE;IACP,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;;8CAC5D;AAGlB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;;4CACd;AAO7B;IALC,IAAA,gBAAM,EAAC;QACN,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,yBAAiB;QACvB,OAAO,EAAE,yBAAiB,CAAC,OAAO;KACnC,CAAC;;2CACwB;AAG1B;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;;+CACtC;AAGnB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;+CACnC;AAG1B;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;8CACpC;AAGzB;IADC,IAAA,0BAAgB,EAAC,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;8BACnD,IAAI;8CAAC;AAQhB;IANC,IAAA,eAAK,GAAE;IACP,IAAA,gBAAM,EAAC;QACN,IAAI,EAAE,aAAa;QACnB,IAAI,EAAE,uBAAuB;QAC7B,QAAQ,EAAE,IAAI;KACf,CAAC;;wDAC+B;AAIjC;IAFC,IAAA,eAAK,GAAE;IACP,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;8CAC9C;AAGvB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;gDAC7C;sBA3Cd,WAAW;IADvB,IAAA,gBAAM,GAAE;GACI,WAAW,CA4CvB"}
|
|
@@ -10,5 +10,6 @@ export declare abstract class BaseWorker {
|
|
|
10
10
|
private processEvents;
|
|
11
11
|
private processEvent;
|
|
12
12
|
private getErrorMessage;
|
|
13
|
+
protected getNextTryAt(event: OutboxEvent, error: unknown, nextRetryCount: number): Date | null;
|
|
13
14
|
abstract handle(event: OutboxEvent): Promise<void>;
|
|
14
15
|
}
|
|
@@ -70,7 +70,9 @@ let BaseWorker = BaseWorker_1 = class BaseWorker {
|
|
|
70
70
|
catch (e) {
|
|
71
71
|
this.logger.error(`Failed to process event ${event.id}`, e);
|
|
72
72
|
const errorMessage = this.getErrorMessage(e);
|
|
73
|
-
const
|
|
73
|
+
const nextRetryCount = event.retryCount + 1;
|
|
74
|
+
const nextTryAt = this.getNextTryAt(event, e, nextRetryCount);
|
|
75
|
+
const retryUpdated = await this.outboxService.incrementRetry(event.id, errorMessage, maxRetries, event.processingStartedAt, nextTryAt);
|
|
74
76
|
if (!retryUpdated) {
|
|
75
77
|
this.logger.warn(`Event ${event.id} retry was not updated because the claim expired`);
|
|
76
78
|
}
|
|
@@ -82,6 +84,12 @@ let BaseWorker = BaseWorker_1 = class BaseWorker {
|
|
|
82
84
|
}
|
|
83
85
|
return String(e);
|
|
84
86
|
}
|
|
87
|
+
getNextTryAt(event, error, nextRetryCount) {
|
|
88
|
+
void event;
|
|
89
|
+
void error;
|
|
90
|
+
void nextRetryCount;
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
85
93
|
};
|
|
86
94
|
exports.BaseWorker = BaseWorker;
|
|
87
95
|
exports.BaseWorker = BaseWorker = BaseWorker_1 = __decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-worker.js","sourceRoot":"","sources":["../../../../src/modules/outbox/services/base-worker.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAAoD;AACpD,0CAA4C;AAKrC,IAAe,UAAU,kBAAzB,MAAe,UAAU;IAI9B,YAAyC,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;QAHpD,WAAM,GAAG,IAAI,eAAM,CAAC,YAAU,CAAC,IAAI,CAAC,CAAC;IAGkB,CAAC;IAIzE,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAC;YAE1E,OAAO;QACT,CAAC;QAED,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QAEnB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,oBAAoB,EAAE,CAAC;YAEzD,IAAI,MAAM,CAAC,0BAA0B,EAAE,CAAC;gBACtC,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,0BAA0B,CACpE,MAAM,CAAC,sBAAsB,CAC9B,CAAC;gBACF,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;oBACnB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,UAAU,0BAA0B,CAAC,CAAC;gBAClE,CAAC;YACH,CAAC;YAED,kEAAkE;YAClE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;YAEtC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,MAAM,iBAAiB,CAAC,CAAC;YAC3D,CAAC;YAED,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC3C,CAAC;QAAC,OAAO,CAAU,EAAE,CAAC;YACpB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,EAAE,CAAC,CAAC,CAAC;QAC9C,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACtB,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,aAAa,CACzB,MAAqB,EACrB,MAAuC;QAEvC,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;YAChC,MAAM,OAAO,CAAC,UAAU,CACtB,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CACnE,CAAC;YAEF,OAAO;QACT,CAAC;QAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,MAAM,CAAC,mBAAmB,EAAE,CAAC;YACnE,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAC;YAC9D,MAAM,OAAO,CAAC,UAAU,CACtB,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAClE,CAAC;QACJ,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,YAAY,CACxB,KAAkB,EAClB,UAAkB;QAElB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAEzB,MAAM,iBAAiB,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,eAAe,CAChE,KAAK,CAAC,EAAE,EACR,KAAK,CAAC,mBAAmB,CAC1B,CAAC;YAEF,IAAI,iBAAiB,EAAE,CAAC;gBACtB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,gCAAgC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;YAC9D,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,SAAS,KAAK,CAAC,EAAE,sEAAsE,CACxF,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,CAAU,EAAE,CAAC;YACpB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;YAC5D,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"base-worker.js","sourceRoot":"","sources":["../../../../src/modules/outbox/services/base-worker.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,22 +1,33 @@
|
|
|
1
1
|
import { EntityManager, Repository } from 'typeorm';
|
|
2
2
|
import { OutboxEvent } from '../entities';
|
|
3
3
|
import { OutboxResolvedModuleOptions } from '../types';
|
|
4
|
+
export interface CreateOutboxEventOptions {
|
|
5
|
+
manager?: EntityManager;
|
|
6
|
+
maxRetries?: number | null;
|
|
7
|
+
nextTryAt?: Date | null;
|
|
8
|
+
}
|
|
4
9
|
export declare class OutboxService {
|
|
5
10
|
private readonly outboxRepository;
|
|
6
11
|
private readonly options;
|
|
7
12
|
constructor(outboxRepository: Repository<OutboxEvent>, options: OutboxResolvedModuleOptions);
|
|
8
13
|
getOperationalPolicy(): OutboxResolvedModuleOptions['operationalPolicy'];
|
|
9
|
-
createEvent(eventType: string, payload: Record<string, any>,
|
|
14
|
+
createEvent(eventType: string, payload: Record<string, any>, optionsOrManager?: CreateOutboxEventOptions | EntityManager): Promise<OutboxEvent>;
|
|
10
15
|
claimById(eventId: string): Promise<OutboxEvent | null>;
|
|
11
16
|
claimPendingEventsByTypes(eventTypes: string[], limit?: number): Promise<OutboxEvent[]>;
|
|
12
17
|
claimPendingEvents(eventType: string, limit?: number): Promise<OutboxEvent[]>;
|
|
13
18
|
markAsProcessing(eventId: string): Promise<void>;
|
|
14
19
|
markAsProcessed(eventId: string, expectedProcessingStartedAt?: Date | null): Promise<boolean>;
|
|
15
|
-
incrementRetry(eventId: string, error: string,
|
|
20
|
+
incrementRetry(eventId: string, error: string, fallbackMaxRetries?: number, expectedProcessingStartedAt?: Date | null, nextTryAt?: Date | null): Promise<boolean>;
|
|
16
21
|
markAsFailed(eventId: string, error: string, expectedProcessingStartedAt?: Date | null): Promise<boolean>;
|
|
17
22
|
deleteProcessed(olderThanHours?: number): Promise<number>;
|
|
18
23
|
resetStaleProcessingEvents(staleMinutes?: number): Promise<number>;
|
|
19
24
|
private findEventForProcessingUpdate;
|
|
20
25
|
private updateEvent;
|
|
21
26
|
private addProcessingOwnershipCondition;
|
|
27
|
+
private addReadyToProcessCondition;
|
|
28
|
+
private resolveCreateEventOptions;
|
|
29
|
+
private isEntityManager;
|
|
30
|
+
private resolveEventMaxRetries;
|
|
31
|
+
private resolveEffectiveMaxRetries;
|
|
32
|
+
private requirePositiveInteger;
|
|
22
33
|
}
|
|
@@ -26,30 +26,35 @@ let OutboxService = class OutboxService {
|
|
|
26
26
|
getOperationalPolicy() {
|
|
27
27
|
return this.options.operationalPolicy;
|
|
28
28
|
}
|
|
29
|
-
async createEvent(eventType, payload,
|
|
30
|
-
const
|
|
31
|
-
|
|
29
|
+
async createEvent(eventType, payload, optionsOrManager) {
|
|
30
|
+
const options = this.resolveCreateEventOptions(optionsOrManager);
|
|
31
|
+
const repo = options.manager
|
|
32
|
+
? options.manager.getRepository(entities_1.OutboxEvent)
|
|
32
33
|
: this.outboxRepository;
|
|
33
34
|
const event = repo.create({
|
|
34
35
|
eventType,
|
|
35
36
|
payload,
|
|
36
37
|
status: enums_1.OutboxEventStatus.PENDING,
|
|
38
|
+
maxRetries: this.resolveEventMaxRetries(options.maxRetries),
|
|
39
|
+
nextTryAt: options.nextTryAt ?? null,
|
|
37
40
|
});
|
|
38
41
|
return repo.save(event);
|
|
39
42
|
}
|
|
40
43
|
async claimById(eventId) {
|
|
41
44
|
return this.outboxRepository.manager.transaction(async (manager) => {
|
|
42
45
|
const processingStartedAt = new Date();
|
|
43
|
-
const
|
|
46
|
+
const query = manager
|
|
44
47
|
.createQueryBuilder()
|
|
45
48
|
.update(entities_1.OutboxEvent)
|
|
46
49
|
.set({
|
|
47
50
|
status: enums_1.OutboxEventStatus.PROCESSING,
|
|
48
51
|
processingStartedAt,
|
|
52
|
+
nextTryAt: null,
|
|
49
53
|
})
|
|
50
54
|
.where('id = :id', { id: eventId })
|
|
51
|
-
.andWhere('status = :status', { status: enums_1.OutboxEventStatus.PENDING })
|
|
52
|
-
|
|
55
|
+
.andWhere('status = :status', { status: enums_1.OutboxEventStatus.PENDING });
|
|
56
|
+
this.addReadyToProcessCondition(query, processingStartedAt);
|
|
57
|
+
const result = await query.execute();
|
|
53
58
|
if (!result.affected) {
|
|
54
59
|
return null;
|
|
55
60
|
}
|
|
@@ -61,10 +66,12 @@ let OutboxService = class OutboxService {
|
|
|
61
66
|
return [];
|
|
62
67
|
}
|
|
63
68
|
return this.outboxRepository.manager.transaction(async (manager) => {
|
|
64
|
-
const
|
|
69
|
+
const query = manager
|
|
65
70
|
.createQueryBuilder(entities_1.OutboxEvent, 'outbox')
|
|
66
71
|
.where('outbox.status = :status', { status: enums_1.OutboxEventStatus.PENDING })
|
|
67
|
-
.andWhere('outbox.eventType IN (:...eventTypes)', { eventTypes })
|
|
72
|
+
.andWhere('outbox.eventType IN (:...eventTypes)', { eventTypes });
|
|
73
|
+
this.addReadyToProcessCondition(query, new Date(), 'outbox');
|
|
74
|
+
const events = await query
|
|
68
75
|
.orderBy('outbox.createdAt', 'ASC')
|
|
69
76
|
.limit(limit)
|
|
70
77
|
.setLock('pessimistic_write')
|
|
@@ -79,12 +86,14 @@ let OutboxService = class OutboxService {
|
|
|
79
86
|
.set({
|
|
80
87
|
status: enums_1.OutboxEventStatus.PROCESSING,
|
|
81
88
|
processingStartedAt,
|
|
89
|
+
nextTryAt: null,
|
|
82
90
|
})
|
|
83
91
|
.whereInIds(eventIds)
|
|
84
92
|
.execute();
|
|
85
93
|
events.forEach((e) => {
|
|
86
94
|
e.status = enums_1.OutboxEventStatus.PROCESSING;
|
|
87
95
|
e.processingStartedAt = processingStartedAt;
|
|
96
|
+
e.nextTryAt = null;
|
|
88
97
|
});
|
|
89
98
|
}
|
|
90
99
|
return events;
|
|
@@ -93,10 +102,12 @@ let OutboxService = class OutboxService {
|
|
|
93
102
|
async claimPendingEvents(eventType, limit = this.options.operationalPolicy.claimBatchSize) {
|
|
94
103
|
return this.outboxRepository.manager.transaction(async (manager) => {
|
|
95
104
|
// Fetch pending events with pessimistic lock
|
|
96
|
-
const
|
|
105
|
+
const query = manager
|
|
97
106
|
.createQueryBuilder(entities_1.OutboxEvent, 'outbox')
|
|
98
107
|
.where('outbox.status = :status', { status: enums_1.OutboxEventStatus.PENDING })
|
|
99
|
-
.andWhere('outbox.eventType = :eventType', { eventType })
|
|
108
|
+
.andWhere('outbox.eventType = :eventType', { eventType });
|
|
109
|
+
this.addReadyToProcessCondition(query, new Date(), 'outbox');
|
|
110
|
+
const events = await query
|
|
100
111
|
.orderBy('outbox.createdAt', 'ASC')
|
|
101
112
|
.limit(limit)
|
|
102
113
|
.setLock('pessimistic_write')
|
|
@@ -112,6 +123,7 @@ let OutboxService = class OutboxService {
|
|
|
112
123
|
.set({
|
|
113
124
|
status: enums_1.OutboxEventStatus.PROCESSING,
|
|
114
125
|
processingStartedAt,
|
|
126
|
+
nextTryAt: null,
|
|
115
127
|
})
|
|
116
128
|
.whereInIds(eventIds)
|
|
117
129
|
.execute();
|
|
@@ -119,6 +131,7 @@ let OutboxService = class OutboxService {
|
|
|
119
131
|
events.forEach((e) => {
|
|
120
132
|
e.status = enums_1.OutboxEventStatus.PROCESSING;
|
|
121
133
|
e.processingStartedAt = processingStartedAt;
|
|
134
|
+
e.nextTryAt = null;
|
|
122
135
|
});
|
|
123
136
|
}
|
|
124
137
|
return events;
|
|
@@ -128,27 +141,31 @@ let OutboxService = class OutboxService {
|
|
|
128
141
|
await this.outboxRepository.update(eventId, {
|
|
129
142
|
status: enums_1.OutboxEventStatus.PROCESSING,
|
|
130
143
|
processingStartedAt: new Date(),
|
|
144
|
+
nextTryAt: null,
|
|
131
145
|
});
|
|
132
146
|
}
|
|
133
147
|
async markAsProcessed(eventId, expectedProcessingStartedAt) {
|
|
134
148
|
return this.updateEvent(eventId, {
|
|
135
149
|
status: enums_1.OutboxEventStatus.PROCESSED,
|
|
136
150
|
processingStartedAt: null,
|
|
151
|
+
nextTryAt: null,
|
|
137
152
|
processedAt: new Date(),
|
|
138
153
|
}, expectedProcessingStartedAt);
|
|
139
154
|
}
|
|
140
|
-
async incrementRetry(eventId, error,
|
|
155
|
+
async incrementRetry(eventId, error, fallbackMaxRetries = this.options.operationalPolicy.maxRetries, expectedProcessingStartedAt, nextTryAt) {
|
|
141
156
|
const event = await this.findEventForProcessingUpdate(eventId, expectedProcessingStartedAt);
|
|
142
157
|
if (!event) {
|
|
143
158
|
return false;
|
|
144
159
|
}
|
|
145
160
|
const newRetryCount = event.retryCount + 1;
|
|
161
|
+
const maxRetries = this.resolveEffectiveMaxRetries(event.maxRetries, fallbackMaxRetries);
|
|
146
162
|
if (newRetryCount >= maxRetries) {
|
|
147
163
|
return this.updateEvent(eventId, {
|
|
148
164
|
status: enums_1.OutboxEventStatus.FAILED,
|
|
149
165
|
lastError: error,
|
|
150
166
|
retryCount: newRetryCount,
|
|
151
167
|
processingStartedAt: null,
|
|
168
|
+
nextTryAt: null,
|
|
152
169
|
}, expectedProcessingStartedAt);
|
|
153
170
|
}
|
|
154
171
|
return this.updateEvent(eventId, {
|
|
@@ -156,6 +173,7 @@ let OutboxService = class OutboxService {
|
|
|
156
173
|
lastError: error,
|
|
157
174
|
retryCount: newRetryCount,
|
|
158
175
|
processingStartedAt: null,
|
|
176
|
+
nextTryAt: nextTryAt ?? null,
|
|
159
177
|
}, expectedProcessingStartedAt);
|
|
160
178
|
}
|
|
161
179
|
async markAsFailed(eventId, error, expectedProcessingStartedAt) {
|
|
@@ -165,6 +183,7 @@ let OutboxService = class OutboxService {
|
|
|
165
183
|
lastError: error,
|
|
166
184
|
retryCount: event?.retryCount || 0,
|
|
167
185
|
processingStartedAt: null,
|
|
186
|
+
nextTryAt: null,
|
|
168
187
|
}, expectedProcessingStartedAt);
|
|
169
188
|
}
|
|
170
189
|
async deleteProcessed(olderThanHours = this.options.operationalPolicy
|
|
@@ -186,6 +205,7 @@ let OutboxService = class OutboxService {
|
|
|
186
205
|
.set({
|
|
187
206
|
status: enums_1.OutboxEventStatus.PENDING,
|
|
188
207
|
processingStartedAt: null,
|
|
208
|
+
nextTryAt: null,
|
|
189
209
|
})
|
|
190
210
|
.where('status = :status', { status: enums_1.OutboxEventStatus.PROCESSING })
|
|
191
211
|
.andWhere('processing_started_at < :staleThreshold', { staleThreshold })
|
|
@@ -224,6 +244,40 @@ let OutboxService = class OutboxService {
|
|
|
224
244
|
expectedProcessingStartedAt,
|
|
225
245
|
});
|
|
226
246
|
}
|
|
247
|
+
addReadyToProcessCondition(query, now, alias) {
|
|
248
|
+
const prefix = alias ? `${alias}.` : '';
|
|
249
|
+
query.andWhere(`(${prefix}next_try_at IS NULL OR ${prefix}next_try_at <= :now)`, { now });
|
|
250
|
+
}
|
|
251
|
+
resolveCreateEventOptions(optionsOrManager) {
|
|
252
|
+
if (!optionsOrManager) {
|
|
253
|
+
return {};
|
|
254
|
+
}
|
|
255
|
+
if (this.isEntityManager(optionsOrManager)) {
|
|
256
|
+
return { manager: optionsOrManager };
|
|
257
|
+
}
|
|
258
|
+
return optionsOrManager;
|
|
259
|
+
}
|
|
260
|
+
isEntityManager(value) {
|
|
261
|
+
return typeof value.getRepository === 'function';
|
|
262
|
+
}
|
|
263
|
+
resolveEventMaxRetries(maxRetries) {
|
|
264
|
+
if (maxRetries === undefined || maxRetries === null) {
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
return this.requirePositiveInteger(maxRetries, 'maxRetries');
|
|
268
|
+
}
|
|
269
|
+
resolveEffectiveMaxRetries(eventMaxRetries, fallbackMaxRetries) {
|
|
270
|
+
if (eventMaxRetries !== null) {
|
|
271
|
+
return this.requirePositiveInteger(eventMaxRetries, 'event.maxRetries');
|
|
272
|
+
}
|
|
273
|
+
return this.requirePositiveInteger(fallbackMaxRetries, 'fallbackMaxRetries');
|
|
274
|
+
}
|
|
275
|
+
requirePositiveInteger(value, optionName) {
|
|
276
|
+
if (Number.isInteger(value) && value > 0) {
|
|
277
|
+
return value;
|
|
278
|
+
}
|
|
279
|
+
throw new TypeError(`${optionName} must be a positive integer.`);
|
|
280
|
+
}
|
|
227
281
|
};
|
|
228
282
|
exports.OutboxService = OutboxService;
|
|
229
283
|
exports.OutboxService = OutboxService = __decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outbox.service.js","sourceRoot":"","sources":["../../../../src/modules/outbox/services/outbox.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAoD;AACpD,qCAAoD;AACpD,0CAA0C;AAC1C,oCAA6C;AAE7C,0DAG6B;
|
|
1
|
+
{"version":3,"file":"outbox.service.js","sourceRoot":"","sources":["../../../../src/modules/outbox/services/outbox.service.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@russ-b/nestjs-common-tools",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "NestJS utility tools",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -8,14 +8,6 @@
|
|
|
8
8
|
"dist",
|
|
9
9
|
"README.md"
|
|
10
10
|
],
|
|
11
|
-
"scripts": {
|
|
12
|
-
"build": "node -e \"const fs = require('fs'); fs.rmSync('dist', { recursive: true, force: true }); fs.rmSync('tsconfig.tsbuildinfo', { force: true });\" && tsc",
|
|
13
|
-
"test": "jest",
|
|
14
|
-
"prepublishOnly": "npm test",
|
|
15
|
-
"prepare": "npm run build",
|
|
16
|
-
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\"",
|
|
17
|
-
"format": "prettier --write \"src/**/*.ts\""
|
|
18
|
-
},
|
|
19
11
|
"keywords": [
|
|
20
12
|
"nestjs",
|
|
21
13
|
"typeorm",
|
|
@@ -212,5 +204,11 @@
|
|
|
212
204
|
],
|
|
213
205
|
"coverageDirectory": "../coverage",
|
|
214
206
|
"testEnvironment": "node"
|
|
207
|
+
},
|
|
208
|
+
"scripts": {
|
|
209
|
+
"build": "node -e \"const fs = require('fs'); fs.rmSync('dist', { recursive: true, force: true }); fs.rmSync('tsconfig.tsbuildinfo', { force: true });\" && tsc",
|
|
210
|
+
"test": "jest",
|
|
211
|
+
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\"",
|
|
212
|
+
"format": "prettier --write \"src/**/*.ts\""
|
|
215
213
|
}
|
|
216
|
-
}
|
|
214
|
+
}
|