@dudousxd/nestjs-durable 0.43.0 → 0.43.1
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/dist/index.cjs +44 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +44 -6
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1169,6 +1169,15 @@ var RetentionPoller = class {
|
|
|
1169
1169
|
onModuleDestroy() {
|
|
1170
1170
|
if (this.timer) clearInterval(this.timer);
|
|
1171
1171
|
}
|
|
1172
|
+
/**
|
|
1173
|
+
* Prune one round.
|
|
1174
|
+
*
|
|
1175
|
+
* Never rejects, for the same reason {@link TimerPoller.poll} does not: it is awaited inside
|
|
1176
|
+
* `onApplicationBootstrap` (so a rejection propagates into the host's `bootstrap()` and kills the
|
|
1177
|
+
* process) and fired as `void` on the interval (so a rejection is an unhandled one, also fatal).
|
|
1178
|
+
* Pruning history is the least urgent thing this package does — a `pruneTerminalRuns` that fails
|
|
1179
|
+
* on a locked table must cost this sweep and nothing more.
|
|
1180
|
+
*/
|
|
1172
1181
|
async sweep() {
|
|
1173
1182
|
if (this.sweeping) return;
|
|
1174
1183
|
const retention = this.options.retention;
|
|
@@ -1185,6 +1194,8 @@ var RetentionPoller = class {
|
|
|
1185
1194
|
if (deleted < batchSize) break;
|
|
1186
1195
|
}
|
|
1187
1196
|
}
|
|
1197
|
+
} catch (error) {
|
|
1198
|
+
console.error("[nestjs-durable] retention sweep failed; retrying next interval:", error);
|
|
1188
1199
|
} finally {
|
|
1189
1200
|
this.sweeping = false;
|
|
1190
1201
|
}
|
|
@@ -1579,7 +1590,11 @@ var TimerPoller = class {
|
|
|
1579
1590
|
}
|
|
1580
1591
|
async onApplicationBootstrap() {
|
|
1581
1592
|
if (!isDrivingOperator(this.options)) return;
|
|
1582
|
-
this.unsubscribeEnqueued = this.engine.onEnqueued((runId) =>
|
|
1593
|
+
this.unsubscribeEnqueued = this.engine.onEnqueued((runId) => {
|
|
1594
|
+
void this.engine.runOne(runId).catch((error) => {
|
|
1595
|
+
console.error(`[nestjs-durable] could not run enqueued run ${runId}:`, error);
|
|
1596
|
+
});
|
|
1597
|
+
});
|
|
1583
1598
|
await this.poll();
|
|
1584
1599
|
const intervalMs = this.options.timerPollMs ?? 1e3;
|
|
1585
1600
|
if (intervalMs > 0) {
|
|
@@ -1591,22 +1606,45 @@ var TimerPoller = class {
|
|
|
1591
1606
|
if (this.timer) clearInterval(this.timer);
|
|
1592
1607
|
this.unsubscribeEnqueued?.();
|
|
1593
1608
|
}
|
|
1609
|
+
/**
|
|
1610
|
+
* One sweep of the engine's recovery work.
|
|
1611
|
+
*
|
|
1612
|
+
* **This method never rejects, and that is a hard requirement rather than defensiveness.** It has
|
|
1613
|
+
* exactly two callers and a rejection out of either one kills the process: on boot it is awaited
|
|
1614
|
+
* inside `onApplicationBootstrap`, so the rejection propagates through `NestApplication.init()`
|
|
1615
|
+
* into the host's `bootstrap()`; on the interval it is a fire-and-forget `void`, so it surfaces as
|
|
1616
|
+
* an unhandled rejection. Both are fatal, and both re-occur on the next boot with the same state,
|
|
1617
|
+
* so a single unrecoverable run crash-loops every worker in the deployment — taking down every
|
|
1618
|
+
* other workflow with it. A poll that goes wrong must cost this tick, not the pod.
|
|
1619
|
+
*
|
|
1620
|
+
* Each sweep is isolated separately because they are independent: a store that fails
|
|
1621
|
+
* `recoverIncomplete` says nothing about whether durable timers should still fire, and skipping
|
|
1622
|
+
* the rest of the tick would silently widen one subsystem's outage into all of them.
|
|
1623
|
+
*/
|
|
1594
1624
|
async poll() {
|
|
1595
1625
|
if (this.polling) return;
|
|
1596
1626
|
this.polling = true;
|
|
1597
1627
|
try {
|
|
1598
|
-
await this.engine.runPending();
|
|
1599
|
-
await this.engine.recoverIncomplete();
|
|
1600
|
-
await this.engine.resumeDueTimers();
|
|
1601
|
-
await this.engine.sweepTimeouts();
|
|
1628
|
+
await this.sweep("runPending", () => this.engine.runPending());
|
|
1629
|
+
await this.sweep("recoverIncomplete", () => this.engine.recoverIncomplete());
|
|
1630
|
+
await this.sweep("resumeDueTimers", () => this.engine.resumeDueTimers());
|
|
1631
|
+
await this.sweep("sweepTimeouts", () => this.engine.sweepTimeouts());
|
|
1602
1632
|
const schedules = this.options.schedules;
|
|
1603
1633
|
if (schedules && schedules.length > 0) {
|
|
1604
|
-
await runSchedules(this.engine, schedules, Date.now());
|
|
1634
|
+
await this.sweep("schedules", () => runSchedules(this.engine, schedules, Date.now()));
|
|
1605
1635
|
}
|
|
1606
1636
|
} finally {
|
|
1607
1637
|
this.polling = false;
|
|
1608
1638
|
}
|
|
1609
1639
|
}
|
|
1640
|
+
/** Run one sweep, absorbing and reporting its failure — see {@link poll}. */
|
|
1641
|
+
async sweep(name, run) {
|
|
1642
|
+
try {
|
|
1643
|
+
await run();
|
|
1644
|
+
} catch (error) {
|
|
1645
|
+
console.error(`[nestjs-durable] timer poll: ${name} failed; continuing:`, error);
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1610
1648
|
};
|
|
1611
1649
|
TimerPoller = _ts_decorate9([
|
|
1612
1650
|
Injectable9(),
|