@dudousxd/nestjs-durable-core 0.75.1 → 0.75.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.d.cts CHANGED
@@ -3790,6 +3790,12 @@ declare class WorkflowEngine {
3790
3790
  private readonly updateValidators;
3791
3791
  /** Runs being cancelled WITH saga compensation — see `cancel({ compensate: true })`. */
3792
3792
  private readonly cancelRequested;
3793
+ /**
3794
+ * Seqs of the dispatched remote steps a turn suspended on, by run, while that turn executes on
3795
+ * THIS instance — so the turn can re-check them once its lease is released (see
3796
+ * {@link redriveSettledSteps}).
3797
+ */
3798
+ private readonly awaitedRemoteSteps;
3793
3799
  /** Flow-control admission backend for remote steps (see {@link registerQueue}). */
3794
3800
  private readonly admission;
3795
3801
  /** Runs on THIS instance blocked on admission, by queue — woken early on a freed-slot signal. */
@@ -4300,6 +4306,16 @@ declare class WorkflowEngine {
4300
4306
  * itself. Only re-drives for a group with no waiter left whose checkpoints are all settled, which
4301
4307
  * the next turn is then guaranteed to see — so it cannot loop.
4302
4308
  */
4309
+ /**
4310
+ * Re-drive a run that just suspended on dispatched remote steps which, by now, have a result.
4311
+ *
4312
+ * Same race as {@link redriveSettledChildren}, for `ctx.step`: a result landing while the turn
4313
+ * that dispatched it still holds the lease has its wake dropped by {@link execute}, and the turn
4314
+ * then suspends with nothing left to wake it before the step's redispatch deadline. Called after
4315
+ * the lease is released, so any later result wakes the run itself; it only re-drives for a
4316
+ * checkpoint that is already settled, which the next turn replays past — so it cannot loop.
4317
+ */
4318
+ private redriveSettledSteps;
4303
4319
  private redriveSettledChildren;
4304
4320
  /**
4305
4321
  * Deliver an external signal to the run waiting on `token`, resume it with `payload`, and return
package/dist/index.d.ts CHANGED
@@ -3790,6 +3790,12 @@ declare class WorkflowEngine {
3790
3790
  private readonly updateValidators;
3791
3791
  /** Runs being cancelled WITH saga compensation — see `cancel({ compensate: true })`. */
3792
3792
  private readonly cancelRequested;
3793
+ /**
3794
+ * Seqs of the dispatched remote steps a turn suspended on, by run, while that turn executes on
3795
+ * THIS instance — so the turn can re-check them once its lease is released (see
3796
+ * {@link redriveSettledSteps}).
3797
+ */
3798
+ private readonly awaitedRemoteSteps;
3793
3799
  /** Flow-control admission backend for remote steps (see {@link registerQueue}). */
3794
3800
  private readonly admission;
3795
3801
  /** Runs on THIS instance blocked on admission, by queue — woken early on a freed-slot signal. */
@@ -4300,6 +4306,16 @@ declare class WorkflowEngine {
4300
4306
  * itself. Only re-drives for a group with no waiter left whose checkpoints are all settled, which
4301
4307
  * the next turn is then guaranteed to see — so it cannot loop.
4302
4308
  */
4309
+ /**
4310
+ * Re-drive a run that just suspended on dispatched remote steps which, by now, have a result.
4311
+ *
4312
+ * Same race as {@link redriveSettledChildren}, for `ctx.step`: a result landing while the turn
4313
+ * that dispatched it still holds the lease has its wake dropped by {@link execute}, and the turn
4314
+ * then suspends with nothing left to wake it before the step's redispatch deadline. Called after
4315
+ * the lease is released, so any later result wakes the run itself; it only re-drives for a
4316
+ * checkpoint that is already settled, which the next turn replays past — so it cannot loop.
4317
+ */
4318
+ private redriveSettledSteps;
4303
4319
  private redriveSettledChildren;
4304
4320
  /**
4305
4321
  * Deliver an external signal to the run waiting on `token`, resume it with `payload`, and return
package/dist/index.js CHANGED
@@ -3698,6 +3698,12 @@ var WorkflowEngine = class {
3698
3698
  updateValidators = /* @__PURE__ */ new Map();
3699
3699
  /** Runs being cancelled WITH saga compensation — see `cancel({ compensate: true })`. */
3700
3700
  cancelRequested = /* @__PURE__ */ new Set();
3701
+ /**
3702
+ * Seqs of the dispatched remote steps a turn suspended on, by run, while that turn executes on
3703
+ * THIS instance — so the turn can re-check them once its lease is released (see
3704
+ * {@link redriveSettledSteps}).
3705
+ */
3706
+ awaitedRemoteSteps = /* @__PURE__ */ new Map();
3701
3707
  /** Flow-control admission backend for remote steps (see {@link registerQueue}). */
3702
3708
  admission;
3703
3709
  /** Runs on THIS instance blocked on admission, by queue — woken early on a freed-slot signal. */
@@ -5101,6 +5107,24 @@ var WorkflowEngine = class {
5101
5107
  * itself. Only re-drives for a group with no waiter left whose checkpoints are all settled, which
5102
5108
  * the next turn is then guaranteed to see — so it cannot loop.
5103
5109
  */
5110
+ /**
5111
+ * Re-drive a run that just suspended on dispatched remote steps which, by now, have a result.
5112
+ *
5113
+ * Same race as {@link redriveSettledChildren}, for `ctx.step`: a result landing while the turn
5114
+ * that dispatched it still holds the lease has its wake dropped by {@link execute}, and the turn
5115
+ * then suspends with nothing left to wake it before the step's redispatch deadline. Called after
5116
+ * the lease is released, so any later result wakes the run itself; it only re-drives for a
5117
+ * checkpoint that is already settled, which the next turn replays past — so it cannot loop.
5118
+ */
5119
+ async redriveSettledSteps(runId, seqs) {
5120
+ for (const seq of seqs) {
5121
+ const cp = await this.store.getCheckpoint(runId, seq);
5122
+ if (cp && (cp.status === "completed" || cp.status === "failed")) {
5123
+ await this.resumeImplicit(runId);
5124
+ return;
5125
+ }
5126
+ }
5127
+ }
5104
5128
  async redriveSettledChildren(runId, fan) {
5105
5129
  if (!this.store.hasSignalWaiter) return;
5106
5130
  for (const wait of fan.waits) {
@@ -6555,6 +6579,9 @@ var WorkflowEngine = class {
6555
6579
  const replay = /* @__PURE__ */ new Map();
6556
6580
  for (const cp of snapshot) replay.set(cp.seq, cp);
6557
6581
  let suspendedOnFan;
6582
+ let suspendedOnSteps = false;
6583
+ const awaitedSteps = /* @__PURE__ */ new Set();
6584
+ this.awaitedRemoteSteps.set(run.id, awaitedSteps);
6558
6585
  const ctx = createWorkflowCtx(this.ctxHostFor(replay, run.namespace), run.id, compensations, run.workflow, registered?.searchAttributesSchema);
6559
6586
  try {
6560
6587
  const output = await runInWorkflowCtx(ctx, () => fn(ctx, run.input));
@@ -6611,6 +6638,7 @@ var WorkflowEngine = class {
6611
6638
  wakeAt: err.wakeAt
6612
6639
  });
6613
6640
  suspendedOnFan = err.fan;
6641
+ suspendedOnSteps = suspended.status === "suspended";
6614
6642
  return suspended;
6615
6643
  }
6616
6644
  if (this.cancelRequested.has(run.id)) {
@@ -6630,10 +6658,16 @@ var WorkflowEngine = class {
6630
6658
  error: error2
6631
6659
  });
6632
6660
  } finally {
6661
+ if (this.awaitedRemoteSteps.get(run.id) === awaitedSteps) {
6662
+ this.awaitedRemoteSteps.delete(run.id);
6663
+ }
6633
6664
  await this.store.releaseRunLock(run.id);
6634
6665
  if (suspendedOnFan) {
6635
6666
  void this.redriveSettledChildren(run.id, suspendedOnFan).catch(() => void 0);
6636
6667
  }
6668
+ if (suspendedOnSteps && awaitedSteps.size > 0) {
6669
+ void this.redriveSettledSteps(run.id, awaitedSteps).catch(() => void 0);
6670
+ }
6637
6671
  }
6638
6672
  }
6639
6673
  /**
@@ -7053,6 +7087,7 @@ var WorkflowEngine = class {
7053
7087
  if (this.pool.size === 0) throw new Error("remote steps require a Transport");
7054
7088
  if (step.timeoutMs) return this.callRemoteInMemory(runId, seq, step, input, transport, group);
7055
7089
  if (existing?.status === "pending") {
7090
+ this.awaitedRemoteSteps.get(runId)?.add(seq);
7056
7091
  if (this.remoteRedispatchMs == null) throw new WorkflowSuspended();
7057
7092
  if (existing.wakeAt == null) {
7058
7093
  const wakeAt = this.clock() + this.remoteRedispatchMs;
@@ -7173,6 +7208,7 @@ var WorkflowEngine = class {
7173
7208
  name: step.name,
7174
7209
  kind: "remote"
7175
7210
  });
7211
+ this.awaitedRemoteSteps.get(runId)?.add(seq);
7176
7212
  throw new WorkflowSuspended();
7177
7213
  }
7178
7214
  /** Enqueue a remote step task to its worker group via the transport pool. Shared by the initial