@dudousxd/nestjs-durable-core 0.70.1 → 0.70.2
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.d.cts
CHANGED
|
@@ -4004,6 +4004,24 @@ declare class WorkflowEngine {
|
|
|
4004
4004
|
* — the caller has already ensured this is the decision for the currently-awaited turn.
|
|
4005
4005
|
*/
|
|
4006
4006
|
private applyDecision;
|
|
4007
|
+
/**
|
|
4008
|
+
* Re-drive a run whose turn was computed from a history OLDER than the store's.
|
|
4009
|
+
*
|
|
4010
|
+
* A turn replays against a SNAPSHOT, and an op can settle while its decision is in flight. The
|
|
4011
|
+
* canonical case is a remote `gather_calls` fan-out whose last call lands during the decision's
|
|
4012
|
+
* lease window: `completeRemoteResult` -> `resume` -> `execute` finds the lease held and returns
|
|
4013
|
+
* silently, so that call's wake is spent with nothing to show for it, and the decision then parks
|
|
4014
|
+
* the run on a `call` that is already complete. Nothing would ever wake it again — only the
|
|
4015
|
+
* `reconcileMs` orphan sweep, minutes later.
|
|
4016
|
+
*
|
|
4017
|
+
* The tell is precise: the turn (re)declared a blocking op whose checkpoint is already settled. A
|
|
4018
|
+
* turn with an up-to-date history never does that, because a settled op is in its history and the
|
|
4019
|
+
* replay skips it. That also makes this convergent — the re-driven turn sees the op resolved and
|
|
4020
|
+
* cannot re-declare it, so one lost wake costs exactly one extra turn, never a loop.
|
|
4021
|
+
*
|
|
4022
|
+
* Scheduled off the current stack so it runs after the caller released the run lease.
|
|
4023
|
+
*/
|
|
4024
|
+
private redriveIfTurnSawStaleHistory;
|
|
4007
4025
|
/** The run's resolved durable ops as replay inputs: completed/failed steps + elapsed timers. */
|
|
4008
4026
|
private remoteHistory;
|
|
4009
4027
|
/** Apply a turn's commands: persist recorded local steps, dispatch remote calls, schedule timers.
|
package/dist/index.d.ts
CHANGED
|
@@ -4004,6 +4004,24 @@ declare class WorkflowEngine {
|
|
|
4004
4004
|
* — the caller has already ensured this is the decision for the currently-awaited turn.
|
|
4005
4005
|
*/
|
|
4006
4006
|
private applyDecision;
|
|
4007
|
+
/**
|
|
4008
|
+
* Re-drive a run whose turn was computed from a history OLDER than the store's.
|
|
4009
|
+
*
|
|
4010
|
+
* A turn replays against a SNAPSHOT, and an op can settle while its decision is in flight. The
|
|
4011
|
+
* canonical case is a remote `gather_calls` fan-out whose last call lands during the decision's
|
|
4012
|
+
* lease window: `completeRemoteResult` -> `resume` -> `execute` finds the lease held and returns
|
|
4013
|
+
* silently, so that call's wake is spent with nothing to show for it, and the decision then parks
|
|
4014
|
+
* the run on a `call` that is already complete. Nothing would ever wake it again — only the
|
|
4015
|
+
* `reconcileMs` orphan sweep, minutes later.
|
|
4016
|
+
*
|
|
4017
|
+
* The tell is precise: the turn (re)declared a blocking op whose checkpoint is already settled. A
|
|
4018
|
+
* turn with an up-to-date history never does that, because a settled op is in its history and the
|
|
4019
|
+
* replay skips it. That also makes this convergent — the re-driven turn sees the op resolved and
|
|
4020
|
+
* cannot re-declare it, so one lost wake costs exactly one extra turn, never a loop.
|
|
4021
|
+
*
|
|
4022
|
+
* Scheduled off the current stack so it runs after the caller released the run lease.
|
|
4023
|
+
*/
|
|
4024
|
+
private redriveIfTurnSawStaleHistory;
|
|
4007
4025
|
/** The run's resolved durable ops as replay inputs: completed/failed steps + elapsed timers. */
|
|
4008
4026
|
private remoteHistory;
|
|
4009
4027
|
/** Apply a turn's commands: persist recorded local steps, dispatch remote calls, schedule timers.
|
package/dist/index.js
CHANGED
|
@@ -4836,10 +4836,42 @@ var WorkflowEngine = class {
|
|
|
4836
4836
|
};
|
|
4837
4837
|
}
|
|
4838
4838
|
const wakeAt = await this.applyCommands(run, decision.commands);
|
|
4839
|
-
|
|
4839
|
+
const suspended = await this.settleRun(run, {
|
|
4840
4840
|
kind: "suspended",
|
|
4841
4841
|
wakeAt
|
|
4842
4842
|
});
|
|
4843
|
+
await this.redriveIfTurnSawStaleHistory(run.id, decision.commands);
|
|
4844
|
+
return suspended;
|
|
4845
|
+
}
|
|
4846
|
+
/**
|
|
4847
|
+
* Re-drive a run whose turn was computed from a history OLDER than the store's.
|
|
4848
|
+
*
|
|
4849
|
+
* A turn replays against a SNAPSHOT, and an op can settle while its decision is in flight. The
|
|
4850
|
+
* canonical case is a remote `gather_calls` fan-out whose last call lands during the decision's
|
|
4851
|
+
* lease window: `completeRemoteResult` -> `resume` -> `execute` finds the lease held and returns
|
|
4852
|
+
* silently, so that call's wake is spent with nothing to show for it, and the decision then parks
|
|
4853
|
+
* the run on a `call` that is already complete. Nothing would ever wake it again — only the
|
|
4854
|
+
* `reconcileMs` orphan sweep, minutes later.
|
|
4855
|
+
*
|
|
4856
|
+
* The tell is precise: the turn (re)declared a blocking op whose checkpoint is already settled. A
|
|
4857
|
+
* turn with an up-to-date history never does that, because a settled op is in its history and the
|
|
4858
|
+
* replay skips it. That also makes this convergent — the re-driven turn sees the op resolved and
|
|
4859
|
+
* cannot re-declare it, so one lost wake costs exactly one extra turn, never a loop.
|
|
4860
|
+
*
|
|
4861
|
+
* Scheduled off the current stack so it runs after the caller released the run lease.
|
|
4862
|
+
*/
|
|
4863
|
+
async redriveIfTurnSawStaleHistory(runId, commands) {
|
|
4864
|
+
const blocking = commands.filter((cmd) => cmd.kind === "call" || cmd.kind === "startChild" || cmd.kind === "waitSignal");
|
|
4865
|
+
if (blocking.length === 0) return;
|
|
4866
|
+
for (const cmd of blocking) {
|
|
4867
|
+
const checkpoint = await this.store.getCheckpoint(runId, cmd.seq);
|
|
4868
|
+
if (checkpoint && checkpoint.status !== "pending") {
|
|
4869
|
+
setTimeout(() => {
|
|
4870
|
+
void this.resume(runId).catch(() => void 0);
|
|
4871
|
+
}, 0).unref?.();
|
|
4872
|
+
return;
|
|
4873
|
+
}
|
|
4874
|
+
}
|
|
4843
4875
|
}
|
|
4844
4876
|
/** The run's resolved durable ops as replay inputs: completed/failed steps + elapsed timers. */
|
|
4845
4877
|
async remoteHistory(runId) {
|