@dudousxd/nestjs-durable-core 0.34.0 → 0.35.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/dist/index.cjs +102 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.js +102 -37
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -804,7 +804,8 @@ var SingletonGate = class {
|
|
|
804
804
|
statuses: [
|
|
805
805
|
"pending",
|
|
806
806
|
"running",
|
|
807
|
-
"suspended"
|
|
807
|
+
"suspended",
|
|
808
|
+
"cancelling"
|
|
808
809
|
]
|
|
809
810
|
});
|
|
810
811
|
if (queued.length >= cap) {
|
|
@@ -822,7 +823,8 @@ var SingletonGate = class {
|
|
|
822
823
|
workflow: run.workflow,
|
|
823
824
|
statuses: [
|
|
824
825
|
"running",
|
|
825
|
-
"suspended"
|
|
826
|
+
"suspended",
|
|
827
|
+
"cancelling"
|
|
826
828
|
]
|
|
827
829
|
})).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime() || a.id.localeCompare(b.id));
|
|
828
830
|
const idx = inflight.findIndex((r) => r.id === run.id);
|
|
@@ -1971,14 +1973,16 @@ var WorkflowEngine = class {
|
|
|
1971
1973
|
continue;
|
|
1972
1974
|
}
|
|
1973
1975
|
await this.store.releaseRunLock(run.id);
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1976
|
+
if (run.status !== "cancelling") {
|
|
1977
|
+
await this.store.updateRun(run.id, {
|
|
1978
|
+
status: "pending",
|
|
1979
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
1980
|
+
});
|
|
1981
|
+
}
|
|
1978
1982
|
await this.runDispatcher.dispatch(run.id);
|
|
1979
1983
|
results.push({
|
|
1980
1984
|
runId: run.id,
|
|
1981
|
-
status: "pending"
|
|
1985
|
+
status: run.status === "cancelling" ? "cancelling" : "pending"
|
|
1982
1986
|
});
|
|
1983
1987
|
}
|
|
1984
1988
|
return results;
|
|
@@ -2097,7 +2101,7 @@ var WorkflowEngine = class {
|
|
|
2097
2101
|
* `start` when a call site needs the outcome — `await start(...); const r = await waitForRun(id)`.
|
|
2098
2102
|
*/
|
|
2099
2103
|
waitForRun(runId, opts) {
|
|
2100
|
-
const isSettled = /* @__PURE__ */ __name((s) => s !== "pending" && s !== "running", "isSettled");
|
|
2104
|
+
const isSettled = /* @__PURE__ */ __name((s) => s !== "pending" && s !== "running" && s !== "cancelling", "isSettled");
|
|
2101
2105
|
const toResult = /* @__PURE__ */ __name((run) => ({
|
|
2102
2106
|
runId,
|
|
2103
2107
|
status: run.status,
|
|
@@ -2261,8 +2265,19 @@ var WorkflowEngine = class {
|
|
|
2261
2265
|
error: run.error
|
|
2262
2266
|
};
|
|
2263
2267
|
}
|
|
2268
|
+
if (run.status === "cancelling") {
|
|
2269
|
+
return {
|
|
2270
|
+
runId,
|
|
2271
|
+
status: "cancelling"
|
|
2272
|
+
};
|
|
2273
|
+
}
|
|
2264
2274
|
if (opts?.compensate && (run.status === "suspended" || run.status === "running")) {
|
|
2265
2275
|
this.cancelRequested.add(runId);
|
|
2276
|
+
await this.store.updateRun(runId, {
|
|
2277
|
+
status: "cancelling",
|
|
2278
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
2279
|
+
});
|
|
2280
|
+
run.status = "cancelling";
|
|
2266
2281
|
if (this.controlPlane) {
|
|
2267
2282
|
void this.controlPlane.publishControl({
|
|
2268
2283
|
kind: "cancel",
|
|
@@ -2276,7 +2291,7 @@ var WorkflowEngine = class {
|
|
|
2276
2291
|
await this.cancelChildren(runId, opts);
|
|
2277
2292
|
return {
|
|
2278
2293
|
runId,
|
|
2279
|
-
status:
|
|
2294
|
+
status: "cancelling"
|
|
2280
2295
|
};
|
|
2281
2296
|
}
|
|
2282
2297
|
const error = {
|
|
@@ -2667,6 +2682,36 @@ var WorkflowEngine = class {
|
|
|
2667
2682
|
};
|
|
2668
2683
|
}
|
|
2669
2684
|
async runRemoteExecution(run, registered) {
|
|
2685
|
+
if (run.status === "cancelling") {
|
|
2686
|
+
const error = {
|
|
2687
|
+
message: "cancelled"
|
|
2688
|
+
};
|
|
2689
|
+
await this.store.updateRun(run.id, {
|
|
2690
|
+
status: "cancelled",
|
|
2691
|
+
error,
|
|
2692
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
2693
|
+
});
|
|
2694
|
+
this.emit({
|
|
2695
|
+
type: "run.failed",
|
|
2696
|
+
runId: run.id,
|
|
2697
|
+
workflow: run.workflow,
|
|
2698
|
+
error
|
|
2699
|
+
});
|
|
2700
|
+
this.notifyCancelled(run.id);
|
|
2701
|
+
if (this.controlPlane) {
|
|
2702
|
+
void this.controlPlane.publishControl({
|
|
2703
|
+
kind: "cancel",
|
|
2704
|
+
runId: run.id,
|
|
2705
|
+
from: this.instanceId
|
|
2706
|
+
}).catch(() => void 0);
|
|
2707
|
+
}
|
|
2708
|
+
await this.store.releaseRunLock(run.id);
|
|
2709
|
+
return {
|
|
2710
|
+
runId: run.id,
|
|
2711
|
+
status: "cancelled",
|
|
2712
|
+
error
|
|
2713
|
+
};
|
|
2714
|
+
}
|
|
2670
2715
|
const remote = registered.remote;
|
|
2671
2716
|
if (run.status === "pending") {
|
|
2672
2717
|
await this.store.updateRun(run.id, {
|
|
@@ -2760,6 +2805,15 @@ var WorkflowEngine = class {
|
|
|
2760
2805
|
status: "cancelled"
|
|
2761
2806
|
};
|
|
2762
2807
|
}
|
|
2808
|
+
const fresh = await this.store.getRun(run.id);
|
|
2809
|
+
if (fresh && (fresh.status === "cancelled" || fresh.status === "completed" || fresh.status === "dead")) {
|
|
2810
|
+
return {
|
|
2811
|
+
runId: run.id,
|
|
2812
|
+
status: fresh.status,
|
|
2813
|
+
output: fresh.output,
|
|
2814
|
+
error: fresh.error
|
|
2815
|
+
};
|
|
2816
|
+
}
|
|
2763
2817
|
const wakeAt = await this.applyCommands(run, decision.commands);
|
|
2764
2818
|
return this.settleRun(run, {
|
|
2765
2819
|
kind: "suspended",
|
|
@@ -2927,8 +2981,41 @@ var WorkflowEngine = class {
|
|
|
2927
2981
|
}
|
|
2928
2982
|
return wakeAt;
|
|
2929
2983
|
}
|
|
2984
|
+
/**
|
|
2985
|
+
* Undo the registered saga compensations in reverse and settle the run `cancelled`. Shared by EVERY
|
|
2986
|
+
* exit path of a run with a compensating cancel in flight — whether the resumed replay returned,
|
|
2987
|
+
* suspended, hit continue-as-new, or threw — so a cancel is never lost just because the body didn't
|
|
2988
|
+
* stop at a suspension point. Clears the in-memory cancel flag.
|
|
2989
|
+
*/
|
|
2990
|
+
async compensateAndCancel(run, compensations) {
|
|
2991
|
+
this.cancelRequested.delete(run.id);
|
|
2992
|
+
for (let i = compensations.length - 1; i >= 0; i -= 1) {
|
|
2993
|
+
const comp = compensations[i];
|
|
2994
|
+
if (comp) await this.runCompensation(run, comp);
|
|
2995
|
+
}
|
|
2996
|
+
const error = {
|
|
2997
|
+
message: "cancelled"
|
|
2998
|
+
};
|
|
2999
|
+
await this.store.updateRun(run.id, {
|
|
3000
|
+
status: "cancelled",
|
|
3001
|
+
error,
|
|
3002
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
3003
|
+
});
|
|
3004
|
+
this.emit({
|
|
3005
|
+
type: "run.failed",
|
|
3006
|
+
runId: run.id,
|
|
3007
|
+
workflow: run.workflow,
|
|
3008
|
+
error
|
|
3009
|
+
});
|
|
3010
|
+
return {
|
|
3011
|
+
runId: run.id,
|
|
3012
|
+
status: "cancelled",
|
|
3013
|
+
error
|
|
3014
|
+
};
|
|
3015
|
+
}
|
|
2930
3016
|
/** The run body, lease held + renewed by {@link execute}. */
|
|
2931
3017
|
async runExecution(run, fn, registered) {
|
|
3018
|
+
if (run.status === "cancelling") this.cancelRequested.add(run.id);
|
|
2932
3019
|
if (run.status === "pending") {
|
|
2933
3020
|
await this.store.updateRun(run.id, {
|
|
2934
3021
|
status: "running",
|
|
@@ -2941,7 +3028,7 @@ var WorkflowEngine = class {
|
|
|
2941
3028
|
workflow: run.workflow
|
|
2942
3029
|
});
|
|
2943
3030
|
}
|
|
2944
|
-
if (registered?.singleton && !await this.singletons.admit(run, registered.singleton)) {
|
|
3031
|
+
if (run.status !== "cancelling" && registered?.singleton && !await this.singletons.admit(run, registered.singleton)) {
|
|
2945
3032
|
const wakeAt = this.singletons.retryWakeAt();
|
|
2946
3033
|
await this.store.updateRun(run.id, {
|
|
2947
3034
|
status: "suspended",
|
|
@@ -2966,12 +3053,14 @@ var WorkflowEngine = class {
|
|
|
2966
3053
|
const ctx = createWorkflowCtx(this.ctxHostFor(replay), run.id, compensations, run.workflow);
|
|
2967
3054
|
try {
|
|
2968
3055
|
const output = await fn(ctx, run.input);
|
|
3056
|
+
if (this.cancelRequested.has(run.id)) return this.compensateAndCancel(run, compensations);
|
|
2969
3057
|
return this.settleRun(run, {
|
|
2970
3058
|
kind: "completed",
|
|
2971
3059
|
output
|
|
2972
3060
|
});
|
|
2973
3061
|
} catch (err) {
|
|
2974
3062
|
if (err instanceof ContinueAsNew) {
|
|
3063
|
+
if (this.cancelRequested.has(run.id)) return this.compensateAndCancel(run, compensations);
|
|
2975
3064
|
await this.store.updateRun(run.id, {
|
|
2976
3065
|
status: "completed",
|
|
2977
3066
|
output: void 0,
|
|
@@ -2995,37 +3084,13 @@ var WorkflowEngine = class {
|
|
|
2995
3084
|
};
|
|
2996
3085
|
}
|
|
2997
3086
|
if (err instanceof WorkflowSuspended) {
|
|
2998
|
-
if (this.cancelRequested.has(run.id))
|
|
2999
|
-
this.cancelRequested.delete(run.id);
|
|
3000
|
-
for (let i = compensations.length - 1; i >= 0; i -= 1) {
|
|
3001
|
-
const comp = compensations[i];
|
|
3002
|
-
if (comp) await this.runCompensation(run, comp);
|
|
3003
|
-
}
|
|
3004
|
-
const error2 = {
|
|
3005
|
-
message: "cancelled"
|
|
3006
|
-
};
|
|
3007
|
-
await this.store.updateRun(run.id, {
|
|
3008
|
-
status: "cancelled",
|
|
3009
|
-
error: error2,
|
|
3010
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
3011
|
-
});
|
|
3012
|
-
this.emit({
|
|
3013
|
-
type: "run.failed",
|
|
3014
|
-
runId: run.id,
|
|
3015
|
-
workflow: run.workflow,
|
|
3016
|
-
error: error2
|
|
3017
|
-
});
|
|
3018
|
-
return {
|
|
3019
|
-
runId: run.id,
|
|
3020
|
-
status: "cancelled",
|
|
3021
|
-
error: error2
|
|
3022
|
-
};
|
|
3023
|
-
}
|
|
3087
|
+
if (this.cancelRequested.has(run.id)) return this.compensateAndCancel(run, compensations);
|
|
3024
3088
|
return this.settleRun(run, {
|
|
3025
3089
|
kind: "suspended",
|
|
3026
3090
|
wakeAt: err.wakeAt
|
|
3027
3091
|
});
|
|
3028
3092
|
}
|
|
3093
|
+
if (this.cancelRequested.has(run.id)) return this.compensateAndCancel(run, compensations);
|
|
3029
3094
|
const error = {
|
|
3030
3095
|
message: err instanceof Error ? err.message : String(err),
|
|
3031
3096
|
stack: err instanceof Error ? err.stack : void 0
|
|
@@ -3979,7 +4044,7 @@ var InMemoryStateStore = class {
|
|
|
3979
4044
|
async listIncompleteRuns() {
|
|
3980
4045
|
return [
|
|
3981
4046
|
...this.runs.values()
|
|
3982
|
-
].filter((r) => r.status === "running").map((r) => ({
|
|
4047
|
+
].filter((r) => r.status === "running" || r.status === "cancelling").map((r) => ({
|
|
3983
4048
|
...r
|
|
3984
4049
|
}));
|
|
3985
4050
|
}
|