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