@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.cjs CHANGED
@@ -1584,6 +1584,22 @@ function createWorkflowCtx(host, runId, compensations, workflow = "", searchAttr
1584
1584
  runId,
1585
1585
  seq: current
1586
1586
  });
1587
+ const buffered = await store.takeBufferedSignal(`child:${id}`);
1588
+ if (buffered) {
1589
+ await store.removeSignalWaiter({
1590
+ token: `child:${id}`,
1591
+ runId,
1592
+ seq: current
1593
+ });
1594
+ await writeCheckpoint(instantCheckpoint({
1595
+ runId,
1596
+ seq: current,
1597
+ name: `signal:child:${id}`,
1598
+ kind: "signal",
1599
+ output: buffered.payload
1600
+ }));
1601
+ return unwrapCompletion(buffered.payload, `child "${id}"`);
1602
+ }
1587
1603
  if (!await store.getRun(id)) host.startChild(workflowName(workflow2), input, id, priority);
1588
1604
  if (!existing) {
1589
1605
  await writeCheckpoint(instantCheckpoint({
@@ -2801,12 +2817,55 @@ var WorkflowEngine = class {
2801
2817
  * inline — or null if the run is unknown. The dashboard "retry" goes through here so it can't block
2802
2818
  * the HTTP request on workflow execution.
2803
2819
  */
2804
- async requeue(runId) {
2820
+ async requeue(runId, _seen) {
2821
+ const seen = _seen ?? /* @__PURE__ */ new Set();
2822
+ if (seen.has(runId)) return null;
2823
+ seen.add(runId);
2805
2824
  const run = await this.store.getRun(runId);
2806
2825
  if (!run) return null;
2826
+ if (run.status === "failed" || run.status === "dead") {
2827
+ const isFailureCompletion = /* @__PURE__ */ __name((v) => typeof v === "object" && v !== null && v.ok === false, "isFailureCompletion");
2828
+ for (const cp of await this.store.listCheckpoints(runId)) {
2829
+ if (cp.status === "failed") {
2830
+ await this.store.saveCheckpoint({
2831
+ ...cp,
2832
+ attempts: 0,
2833
+ wakeAt: this.clock(),
2834
+ ...cp.error ? {
2835
+ error: {
2836
+ ...cp.error,
2837
+ retryable: true
2838
+ }
2839
+ } : {}
2840
+ });
2841
+ } else if (cp.kind === "signal" && cp.name.startsWith("signal:child:") && cp.status === "completed" && isFailureCompletion(cp.output)) {
2842
+ await this.store.saveCheckpoint({
2843
+ ...cp,
2844
+ status: "running",
2845
+ output: void 0
2846
+ });
2847
+ const childId = cp.name.slice("signal:child:".length);
2848
+ const parked = [];
2849
+ for (; ; ) {
2850
+ const buffered = await this.store.takeBufferedSignal(`child:${childId}`);
2851
+ if (!buffered) break;
2852
+ parked.push(buffered.payload);
2853
+ }
2854
+ for (const payload of parked) await this.store.bufferSignal(`child:${childId}`, payload);
2855
+ const bufferedSuccess = parked.some((payload) => typeof payload === "object" && payload !== null && payload.ok === true);
2856
+ if (!bufferedSuccess) {
2857
+ const child = await this.store.getRun(childId);
2858
+ if (child && (child.status === "failed" || child.status === "dead")) {
2859
+ await this.requeue(childId, seen);
2860
+ }
2861
+ }
2862
+ }
2863
+ }
2864
+ }
2807
2865
  await this.store.releaseRunLock(runId);
2808
2866
  await this.store.updateRun(runId, {
2809
2867
  status: "pending",
2868
+ error: void 0,
2810
2869
  updatedAt: /* @__PURE__ */ new Date()
2811
2870
  });
2812
2871
  await this.runDispatcher.dispatch(runId);
@@ -3126,6 +3185,10 @@ var WorkflowEngine = class {
3126
3185
  */
3127
3186
  notifyParent(runId, completion) {
3128
3187
  void this.signal(`child:${runId}`, completion).catch(() => void 0);
3188
+ const at = runId.lastIndexOf("~retry~");
3189
+ if (at !== -1 && completion.ok) {
3190
+ void this.signal(`child:${runId.slice(0, at)}`, completion).catch(() => void 0);
3191
+ }
3129
3192
  }
3130
3193
  /**
3131
3194
  * Deferred child start shared by the in-process ctx host and the remote `startChild` command.