@dudousxd/nestjs-durable-core 0.70.1 → 0.70.3
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 +33 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +33 -1
- package/dist/index.js.map +1 -1
- package/package.json +10 -1
package/dist/index.cjs
CHANGED
|
@@ -4977,10 +4977,42 @@ var WorkflowEngine = class {
|
|
|
4977
4977
|
};
|
|
4978
4978
|
}
|
|
4979
4979
|
const wakeAt = await this.applyCommands(run, decision.commands);
|
|
4980
|
-
|
|
4980
|
+
const suspended = await this.settleRun(run, {
|
|
4981
4981
|
kind: "suspended",
|
|
4982
4982
|
wakeAt
|
|
4983
4983
|
});
|
|
4984
|
+
await this.redriveIfTurnSawStaleHistory(run.id, decision.commands);
|
|
4985
|
+
return suspended;
|
|
4986
|
+
}
|
|
4987
|
+
/**
|
|
4988
|
+
* Re-drive a run whose turn was computed from a history OLDER than the store's.
|
|
4989
|
+
*
|
|
4990
|
+
* A turn replays against a SNAPSHOT, and an op can settle while its decision is in flight. The
|
|
4991
|
+
* canonical case is a remote `gather_calls` fan-out whose last call lands during the decision's
|
|
4992
|
+
* lease window: `completeRemoteResult` -> `resume` -> `execute` finds the lease held and returns
|
|
4993
|
+
* silently, so that call's wake is spent with nothing to show for it, and the decision then parks
|
|
4994
|
+
* the run on a `call` that is already complete. Nothing would ever wake it again — only the
|
|
4995
|
+
* `reconcileMs` orphan sweep, minutes later.
|
|
4996
|
+
*
|
|
4997
|
+
* The tell is precise: the turn (re)declared a blocking op whose checkpoint is already settled. A
|
|
4998
|
+
* turn with an up-to-date history never does that, because a settled op is in its history and the
|
|
4999
|
+
* replay skips it. That also makes this convergent — the re-driven turn sees the op resolved and
|
|
5000
|
+
* cannot re-declare it, so one lost wake costs exactly one extra turn, never a loop.
|
|
5001
|
+
*
|
|
5002
|
+
* Scheduled off the current stack so it runs after the caller released the run lease.
|
|
5003
|
+
*/
|
|
5004
|
+
async redriveIfTurnSawStaleHistory(runId, commands) {
|
|
5005
|
+
const blocking = commands.filter((cmd) => cmd.kind === "call" || cmd.kind === "startChild" || cmd.kind === "waitSignal");
|
|
5006
|
+
if (blocking.length === 0) return;
|
|
5007
|
+
for (const cmd of blocking) {
|
|
5008
|
+
const checkpoint = await this.store.getCheckpoint(runId, cmd.seq);
|
|
5009
|
+
if (checkpoint && checkpoint.status !== "pending") {
|
|
5010
|
+
setTimeout(() => {
|
|
5011
|
+
void this.resume(runId).catch(() => void 0);
|
|
5012
|
+
}, 0).unref?.();
|
|
5013
|
+
return;
|
|
5014
|
+
}
|
|
5015
|
+
}
|
|
4984
5016
|
}
|
|
4985
5017
|
/** The run's resolved durable ops as replay inputs: completed/failed steps + elapsed timers. */
|
|
4986
5018
|
async remoteHistory(runId) {
|