@dudousxd/nestjs-durable-core 0.56.0 → 0.58.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.d.cts CHANGED
@@ -2477,7 +2477,7 @@ declare class WorkflowEngine {
2477
2477
  * inline — or null if the run is unknown. The dashboard "retry" goes through here so it can't block
2478
2478
  * the HTTP request on workflow execution.
2479
2479
  */
2480
- requeue(runId: string): Promise<RunResult | null>;
2480
+ requeue(runId: string, _seen?: Set<string>): Promise<RunResult | null>;
2481
2481
  /**
2482
2482
  * Explicitly re-dispatch every remote step of `runId` stuck `pending` — the OPERATOR escape hatch for
2483
2483
  * a run whose dispatched step job was LOST (worker crashed with no result, or a transport that dropped
package/dist/index.d.ts CHANGED
@@ -2477,7 +2477,7 @@ declare class WorkflowEngine {
2477
2477
  * inline — or null if the run is unknown. The dashboard "retry" goes through here so it can't block
2478
2478
  * the HTTP request on workflow execution.
2479
2479
  */
2480
- requeue(runId: string): Promise<RunResult | null>;
2480
+ requeue(runId: string, _seen?: Set<string>): Promise<RunResult | null>;
2481
2481
  /**
2482
2482
  * Explicitly re-dispatch every remote step of `runId` stuck `pending` — the OPERATOR escape hatch for
2483
2483
  * a run whose dispatched step job was LOST (worker crashed with no result, or a transport that dropped
package/dist/index.js CHANGED
@@ -1493,6 +1493,22 @@ function createWorkflowCtx(host, runId, compensations, workflow = "", searchAttr
1493
1493
  runId,
1494
1494
  seq: current
1495
1495
  });
1496
+ const buffered = await store.takeBufferedSignal(`child:${id}`);
1497
+ if (buffered) {
1498
+ await store.removeSignalWaiter({
1499
+ token: `child:${id}`,
1500
+ runId,
1501
+ seq: current
1502
+ });
1503
+ await writeCheckpoint(instantCheckpoint({
1504
+ runId,
1505
+ seq: current,
1506
+ name: `signal:child:${id}`,
1507
+ kind: "signal",
1508
+ output: buffered.payload
1509
+ }));
1510
+ return unwrapCompletion(buffered.payload, `child "${id}"`);
1511
+ }
1496
1512
  if (!await store.getRun(id)) host.startChild(workflowName(workflow2), input, id, priority);
1497
1513
  if (!existing) {
1498
1514
  await writeCheckpoint(instantCheckpoint({
@@ -2710,12 +2726,55 @@ var WorkflowEngine = class {
2710
2726
  * inline — or null if the run is unknown. The dashboard "retry" goes through here so it can't block
2711
2727
  * the HTTP request on workflow execution.
2712
2728
  */
2713
- async requeue(runId) {
2729
+ async requeue(runId, _seen) {
2730
+ const seen = _seen ?? /* @__PURE__ */ new Set();
2731
+ if (seen.has(runId)) return null;
2732
+ seen.add(runId);
2714
2733
  const run = await this.store.getRun(runId);
2715
2734
  if (!run) return null;
2735
+ if (run.status === "failed" || run.status === "dead") {
2736
+ const isFailureCompletion = /* @__PURE__ */ __name((v) => typeof v === "object" && v !== null && v.ok === false, "isFailureCompletion");
2737
+ for (const cp of await this.store.listCheckpoints(runId)) {
2738
+ if (cp.status === "failed") {
2739
+ await this.store.saveCheckpoint({
2740
+ ...cp,
2741
+ attempts: 0,
2742
+ wakeAt: this.clock(),
2743
+ ...cp.error ? {
2744
+ error: {
2745
+ ...cp.error,
2746
+ retryable: true
2747
+ }
2748
+ } : {}
2749
+ });
2750
+ } else if (cp.kind === "signal" && cp.name.startsWith("signal:child:") && cp.status === "completed" && isFailureCompletion(cp.output)) {
2751
+ await this.store.saveCheckpoint({
2752
+ ...cp,
2753
+ status: "running",
2754
+ output: void 0
2755
+ });
2756
+ const childId = cp.name.slice("signal:child:".length);
2757
+ const parked = [];
2758
+ for (; ; ) {
2759
+ const buffered = await this.store.takeBufferedSignal(`child:${childId}`);
2760
+ if (!buffered) break;
2761
+ parked.push(buffered.payload);
2762
+ }
2763
+ for (const payload of parked) await this.store.bufferSignal(`child:${childId}`, payload);
2764
+ const bufferedSuccess = parked.some((payload) => typeof payload === "object" && payload !== null && payload.ok === true);
2765
+ if (!bufferedSuccess) {
2766
+ const child = await this.store.getRun(childId);
2767
+ if (child && (child.status === "failed" || child.status === "dead")) {
2768
+ await this.requeue(childId, seen);
2769
+ }
2770
+ }
2771
+ }
2772
+ }
2773
+ }
2716
2774
  await this.store.releaseRunLock(runId);
2717
2775
  await this.store.updateRun(runId, {
2718
2776
  status: "pending",
2777
+ error: void 0,
2719
2778
  updatedAt: /* @__PURE__ */ new Date()
2720
2779
  });
2721
2780
  await this.runDispatcher.dispatch(runId);
@@ -3035,6 +3094,10 @@ var WorkflowEngine = class {
3035
3094
  */
3036
3095
  notifyParent(runId, completion) {
3037
3096
  void this.signal(`child:${runId}`, completion).catch(() => void 0);
3097
+ const at = runId.lastIndexOf("~retry~");
3098
+ if (at !== -1 && completion.ok) {
3099
+ void this.signal(`child:${runId.slice(0, at)}`, completion).catch(() => void 0);
3100
+ }
3038
3101
  }
3039
3102
  /**
3040
3103
  * Deferred child start shared by the in-process ctx host and the remote `startChild` command.