@dudousxd/nestjs-durable-core 0.39.0 → 0.40.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
@@ -1512,6 +1512,14 @@ function isNewerVersion(a, b) {
1512
1512
  }) > 0;
1513
1513
  }
1514
1514
  __name(isNewerVersion, "isNewerVersion");
1515
+ var NamespaceMismatch = class NamespaceMismatch2 extends Error {
1516
+ static {
1517
+ __name(this, "NamespaceMismatch");
1518
+ }
1519
+ constructor() {
1520
+ super("namespace-mismatch");
1521
+ }
1522
+ };
1515
1523
  var WorkflowEngine = class {
1516
1524
  static {
1517
1525
  __name(this, "WorkflowEngine");
@@ -1522,6 +1530,7 @@ var WorkflowEngine = class {
1522
1530
  controlPlane;
1523
1531
  clock;
1524
1532
  instanceId;
1533
+ namespace;
1525
1534
  leaseMs;
1526
1535
  maxRecoveryAttempts;
1527
1536
  remoteAdvanceSilenceMs;
@@ -1588,6 +1597,7 @@ var WorkflowEngine = class {
1588
1597
  this.admission = deps.admission ?? new InMemoryAdmissionBackend(this.clock);
1589
1598
  this.admission.onFreed?.((queue) => this.wakeQueueWaiters(queue));
1590
1599
  this.instanceId = deps.instanceId ?? globalThis.crypto.randomUUID();
1600
+ this.namespace = deps.namespace ?? "default";
1591
1601
  this.leaseMs = deps.leaseMs ?? 3e4;
1592
1602
  this.maxRecoveryAttempts = deps.maxRecoveryAttempts;
1593
1603
  this.remoteAdvanceSilenceMs = deps.remoteAdvanceSilenceMs;
@@ -1908,6 +1918,7 @@ var WorkflowEngine = class {
1908
1918
  workflow: name,
1909
1919
  workflowVersion: registered.version,
1910
1920
  status: "pending",
1921
+ namespace: this.namespace,
1911
1922
  input,
1912
1923
  tags,
1913
1924
  searchAttributes: opts?.searchAttributes,
@@ -1944,6 +1955,10 @@ var WorkflowEngine = class {
1944
1955
  error: run.error
1945
1956
  };
1946
1957
  }
1958
+ if (run.namespace !== void 0 && run.namespace !== this.namespace) {
1959
+ await this.store.releaseRunLock(runId);
1960
+ throw new NamespaceMismatch();
1961
+ }
1947
1962
  const registered = this.workflows.get(versionKey(run.workflow, run.workflowVersion)) ?? await this.findInheritedRegistration(run);
1948
1963
  if (!registered) {
1949
1964
  throw new Error(`workflow ${run.workflow}@${run.workflowVersion} is not registered \u2014 keep the prior version deployed so in-flight runs can drain (skew protection)`);
@@ -2062,11 +2077,13 @@ var WorkflowEngine = class {
2062
2077
  const inflight = [
2063
2078
  ...await this.store.listRuns({
2064
2079
  workflow: reg.name,
2065
- status: "running"
2080
+ status: "running",
2081
+ namespace: this.namespace
2066
2082
  }),
2067
2083
  ...await this.store.listRuns({
2068
2084
  workflow: reg.name,
2069
- status: "suspended"
2085
+ status: "suspended",
2086
+ namespace: this.namespace
2070
2087
  })
2071
2088
  ];
2072
2089
  for (const run of inflight) {
@@ -2096,7 +2113,7 @@ var WorkflowEngine = class {
2096
2113
  async recoverIncomplete(nowMs = this.clock()) {
2097
2114
  if (this.draining) return [];
2098
2115
  const results = [];
2099
- for (const run of await this.store.listIncompleteRuns()) {
2116
+ for (const run of await this.store.listIncompleteRuns(this.namespace)) {
2100
2117
  const acquired = await this.store.tryLockRun(run.id, this.instanceId, nowMs + this.leaseMs, nowMs);
2101
2118
  if (!acquired) continue;
2102
2119
  const settled = await this.countRecovery(run);
@@ -2166,7 +2183,7 @@ var WorkflowEngine = class {
2166
2183
  * boot. A run still not due re-suspends cheaply without running new work.
2167
2184
  */
2168
2185
  async resumeDueTimers(nowMs = this.clock()) {
2169
- return this.resumeLeased(await this.store.listDueTimers(nowMs), nowMs);
2186
+ return this.resumeLeased(await this.store.listDueTimers(nowMs, this.namespace), nowMs);
2170
2187
  }
2171
2188
  /**
2172
2189
  * Lease and execute one run by id — the worker side of dispatch. Acquires the recovery lease (so
@@ -2179,7 +2196,10 @@ var WorkflowEngine = class {
2179
2196
  const nowMs = this.clock();
2180
2197
  const acquired = await this.store.tryLockRun(runId, this.instanceId, nowMs + this.leaseMs, nowMs);
2181
2198
  if (!acquired) return null;
2182
- return this.resume(runId);
2199
+ return this.resume(runId).catch((err) => {
2200
+ if (err instanceof NamespaceMismatch) return null;
2201
+ throw err;
2202
+ });
2183
2203
  }
2184
2204
  /**
2185
2205
  * Re-enqueue a run for a worker to (re-)execute — the dispatch-model **retry**. Sets it back to
@@ -2225,7 +2245,7 @@ var WorkflowEngine = class {
2225
2245
  * {@link resumeDueTimers}.
2226
2246
  */
2227
2247
  async runPending(nowMs = this.clock()) {
2228
- return this.resumeLeased(await this.store.listPendingRuns(100), nowMs);
2248
+ return this.resumeLeased(await this.store.listPendingRuns(100, this.namespace), nowMs);
2229
2249
  }
2230
2250
  /**
2231
2251
  * Resolve once `runId` reaches a settled state — terminal (completed/failed/cancelled/dead) or
@@ -2337,7 +2357,10 @@ var WorkflowEngine = class {
2337
2357
  kind: "signal",
2338
2358
  output: payload
2339
2359
  }));
2340
- return this.resume(waiter.runId);
2360
+ return this.resume(waiter.runId).catch((err) => {
2361
+ if (err instanceof NamespaceMismatch) return null;
2362
+ throw err;
2363
+ });
2341
2364
  }
2342
2365
  /**
2343
2366
  * Ensure a run exists for `runId`, then deliver a signal to it — atomically race-free thanks to
@@ -3491,7 +3514,10 @@ var WorkflowEngine = class {
3491
3514
  queueMs: startedAt.getTime() - cp.enqueuedAt.getTime(),
3492
3515
  durationMs: finishedAt.getTime() - startedAt.getTime()
3493
3516
  });
3494
- await this.resume(result.runId);
3517
+ await this.resume(result.runId).catch((err) => {
3518
+ if (err instanceof NamespaceMismatch) return null;
3519
+ throw err;
3520
+ });
3495
3521
  }
3496
3522
  /**
3497
3523
  * A slot freed on `queue` (a fleet-wide signal): resume this instance's runs blocked on it so they
@@ -3789,14 +3815,14 @@ var CodecStateStore = class {
3789
3815
  saveCheckpoint: /* @__PURE__ */ __name((cp) => tx.saveCheckpoint(this.encCp(cp)), "saveCheckpoint")
3790
3816
  }));
3791
3817
  }
3792
- async listIncompleteRuns() {
3793
- return (await this.inner.listIncompleteRuns()).map((r) => this.decRun(r));
3818
+ async listIncompleteRuns(namespace) {
3819
+ return (await this.inner.listIncompleteRuns(namespace)).map((r) => this.decRun(r));
3794
3820
  }
3795
- async listPendingRuns(limit) {
3796
- return (await this.inner.listPendingRuns(limit)).map((r) => this.decRun(r));
3821
+ async listPendingRuns(limit, namespace) {
3822
+ return (await this.inner.listPendingRuns(limit, namespace)).map((r) => this.decRun(r));
3797
3823
  }
3798
- async listDueTimers(nowMs) {
3799
- return (await this.inner.listDueTimers(nowMs)).map((r) => this.decRun(r));
3824
+ async listDueTimers(nowMs, namespace) {
3825
+ return (await this.inner.listDueTimers(nowMs, namespace)).map((r) => this.decRun(r));
3800
3826
  }
3801
3827
  tryLockRun(runId, owner, leaseUntilMs, nowMs) {
3802
3828
  return this.inner.tryLockRun(runId, owner, leaseUntilMs, nowMs);
@@ -4151,7 +4177,8 @@ var InMemoryStateStore = class {
4151
4177
  }
4152
4178
  async createRun(run) {
4153
4179
  this.runs.set(run.id, {
4154
- ...run
4180
+ ...run,
4181
+ namespace: run.namespace ?? "default"
4155
4182
  });
4156
4183
  this.reindexAttributes(run.id, run.searchAttributes);
4157
4184
  }
@@ -4192,24 +4219,24 @@ var InMemoryStateStore = class {
4192
4219
  ...checkpoint
4193
4220
  });
4194
4221
  }
4195
- async listIncompleteRuns() {
4222
+ async listIncompleteRuns(namespace) {
4196
4223
  return [
4197
4224
  ...this.runs.values()
4198
- ].filter((r) => r.status === "running" || r.status === "cancelling").map((r) => ({
4225
+ ].filter((r) => (r.status === "running" || r.status === "cancelling") && (namespace === void 0 || r.namespace === namespace)).map((r) => ({
4199
4226
  ...r
4200
4227
  }));
4201
4228
  }
4202
- async listPendingRuns(limit) {
4229
+ async listPendingRuns(limit, namespace) {
4203
4230
  return [
4204
4231
  ...this.runs.values()
4205
- ].filter((r) => r.status === "pending").sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime() || a.id.localeCompare(b.id)).slice(0, limit).map((r) => ({
4232
+ ].filter((r) => r.status === "pending" && (namespace === void 0 || r.namespace === namespace)).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime() || a.id.localeCompare(b.id)).slice(0, limit).map((r) => ({
4206
4233
  ...r
4207
4234
  }));
4208
4235
  }
4209
- async listDueTimers(nowMs) {
4236
+ async listDueTimers(nowMs, namespace) {
4210
4237
  return [
4211
4238
  ...this.runs.values()
4212
- ].filter((r) => r.status === "suspended" && r.wakeAt !== void 0 && r.wakeAt <= nowMs).map((r) => ({
4239
+ ].filter((r) => r.status === "suspended" && r.wakeAt !== void 0 && r.wakeAt <= nowMs && (namespace === void 0 || r.namespace === namespace)).map((r) => ({
4213
4240
  ...r
4214
4241
  }));
4215
4242
  }
@@ -4324,6 +4351,7 @@ var InMemoryStateStore = class {
4324
4351
  if (query.status) runs = runs.filter((r) => r.status === query.status);
4325
4352
  if (query.statuses) runs = runs.filter((r) => query.statuses?.includes(r.status));
4326
4353
  if (query.tag) runs = runs.filter((r) => r.tags?.includes(query.tag));
4354
+ if (query.namespace !== void 0) runs = runs.filter((r) => r.namespace === query.namespace);
4327
4355
  if (query.attributes?.length) {
4328
4356
  let candidates = null;
4329
4357
  for (const f of query.attributes) {