@dudousxd/nestjs-durable-core 0.39.0 → 0.40.1

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
@@ -246,6 +246,13 @@ interface WorkflowRun {
246
246
  tags?: string[] | undefined;
247
247
  /** Typed, queryable run data (e.g. `{ amount: 200, tier: 'pro' }`) — see {@link RunQuery.attributes}. */
248
248
  searchAttributes?: SearchAttributes | undefined;
249
+ /**
250
+ * The worker-pool partition this run belongs to. Stamped at creation from the creating engine's
251
+ * `namespace` (default `'default'`). A worker only picks up / recovers / resumes-timers-for /
252
+ * times-out runs in its own namespace. `undefined` on a run created before this field existed; the
253
+ * store persists it as `'default'`. Read paths (dashboard, `getRun`) are NOT namespace-scoped.
254
+ */
255
+ namespace?: string | undefined;
249
256
  /**
250
257
  * Dispatch priority for a REMOTE run (one advanced by a {@link WorkflowExecutor} over a broker):
251
258
  * carried onto each {@link WorkflowTask} so an urgent child workflow can jump ahead of enqueued
@@ -433,11 +440,11 @@ interface StateStore {
433
440
  */
434
441
  saveCheckpoint(checkpoint: StepCheckpoint): Promise<void>;
435
442
  /** Used by recovery on boot to find runs to resume (crashed, left `running`). */
436
- listIncompleteRuns(): Promise<WorkflowRun[]>;
443
+ listIncompleteRuns(namespace?: string): Promise<WorkflowRun[]>;
437
444
  /** The oldest `pending` runs awaiting dispatch (FIFO, by `createdAt`), capped at `limit`. */
438
- listPendingRuns(limit: number): Promise<WorkflowRun[]>;
445
+ listPendingRuns(limit: number, namespace?: string): Promise<WorkflowRun[]>;
439
446
  /** Suspended runs whose durable timer is due (`wakeAt <= nowMs`), ready to resume. */
440
- listDueTimers(nowMs: number): Promise<WorkflowRun[]>;
447
+ listDueTimers(nowMs: number, namespace?: string): Promise<WorkflowRun[]>;
441
448
  /**
442
449
  * Atomically acquire the recovery lease on a run for `owner` until `leaseUntilMs`, but only if
443
450
  * it is currently unlocked or its lease has expired (`<= nowMs`). Returns whether it was
@@ -549,6 +556,8 @@ interface RunQuery {
549
556
  * `workflow`/`status`/`tag` to bound the scan on large stores.
550
557
  */
551
558
  attributes?: AttributeFilter[] | undefined;
559
+ /** Restrict to runs in this namespace (exact match), ANDed with the other predicates. */
560
+ namespace?: string | undefined;
552
561
  limit?: number | undefined;
553
562
  offset?: number | undefined;
554
563
  }
@@ -565,6 +574,15 @@ interface SignalWaiter {
565
574
  token: string;
566
575
  runId: string;
567
576
  seq: number;
577
+ /**
578
+ * The parallel-fan group this waiter belongs to, carried from the awaiting command so the resolving
579
+ * `signal:<token>` checkpoint (notably `signal:child:<id>` for an awaited child run) can be tagged
580
+ * with it. A worker's `ctx.gather_children`/`ctx.all` fan-out stamps every `startChild` with the same
581
+ * group; without threading it through the waiter, the child-await checkpoint comes out untagged and the
582
+ * dashboard renders the fan as a sequential chain instead of one parallel group. Undefined for an
583
+ * ordinary (non-fan) signal/child await.
584
+ */
585
+ parallelGroup?: string | undefined;
568
586
  }
569
587
  /** A unit of work dispatched to a remote worker. This is the documented wire payload. */
570
588
  interface RemoteTask {
@@ -1336,6 +1354,13 @@ interface WorkflowEngineDeps {
1336
1354
  admission?: AdmissionBackend | undefined;
1337
1355
  /** Unique id for this engine instance, used for recovery leases. Defaults to a random id. */
1338
1356
  instanceId?: string | undefined;
1357
+ /**
1358
+ * Worker-pool partition for this engine. Stamped on every run it creates; the poll paths
1359
+ * (`runPending`/`recoverIncomplete`/`resumeDueTimers`/`sweepTimeouts`) only act on runs in this
1360
+ * namespace. Default `'default'` — byte-identical to a single-pool deployment. Set distinct values
1361
+ * to safely share ONE state store across non-interchangeable pools (e.g. local dev vs a cluster).
1362
+ */
1363
+ namespace?: string | undefined;
1339
1364
  /** Recovery lease duration in ms — how long this instance owns a run it picked up. Default 30s. */
1340
1365
  leaseMs?: number | undefined;
1341
1366
  /**
@@ -1427,6 +1452,7 @@ declare class WorkflowEngine {
1427
1452
  private readonly controlPlane?;
1428
1453
  private readonly clock;
1429
1454
  private readonly instanceId;
1455
+ private readonly namespace;
1430
1456
  private readonly leaseMs;
1431
1457
  private readonly maxRecoveryAttempts?;
1432
1458
  private readonly remoteAdvanceSilenceMs?;
@@ -2146,9 +2172,9 @@ declare class CodecStateStore implements StateStore {
2146
2172
  raw: unknown;
2147
2173
  saveCheckpoint: (cp: StepCheckpoint) => Promise<void>;
2148
2174
  }) => Promise<T>): Promise<T>;
2149
- listIncompleteRuns(): Promise<WorkflowRun[]>;
2150
- listPendingRuns(limit: number): Promise<WorkflowRun[]>;
2151
- listDueTimers(nowMs: number): Promise<WorkflowRun[]>;
2175
+ listIncompleteRuns(namespace?: string): Promise<WorkflowRun[]>;
2176
+ listPendingRuns(limit: number, namespace?: string): Promise<WorkflowRun[]>;
2177
+ listDueTimers(nowMs: number, namespace?: string): Promise<WorkflowRun[]>;
2152
2178
  tryLockRun(runId: string, owner: string, leaseUntilMs: number, nowMs: number): Promise<boolean>;
2153
2179
  releaseRunLock(runId: string): Promise<void>;
2154
2180
  renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean>;
@@ -2410,9 +2436,9 @@ declare class InMemoryStateStore implements StateStore {
2410
2436
  deleteRun(runId: string): Promise<void>;
2411
2437
  getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null>;
2412
2438
  saveCheckpoint(checkpoint: StepCheckpoint): Promise<void>;
2413
- listIncompleteRuns(): Promise<WorkflowRun[]>;
2414
- listPendingRuns(limit: number): Promise<WorkflowRun[]>;
2415
- listDueTimers(nowMs: number): Promise<WorkflowRun[]>;
2439
+ listIncompleteRuns(namespace?: string): Promise<WorkflowRun[]>;
2440
+ listPendingRuns(limit: number, namespace?: string): Promise<WorkflowRun[]>;
2441
+ listDueTimers(nowMs: number, namespace?: string): Promise<WorkflowRun[]>;
2416
2442
  tryLockRun(runId: string, owner: string, leaseUntilMs: number, nowMs: number): Promise<boolean>;
2417
2443
  releaseRunLock(runId: string): Promise<void>;
2418
2444
  renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean>;
package/dist/index.d.ts CHANGED
@@ -246,6 +246,13 @@ interface WorkflowRun {
246
246
  tags?: string[] | undefined;
247
247
  /** Typed, queryable run data (e.g. `{ amount: 200, tier: 'pro' }`) — see {@link RunQuery.attributes}. */
248
248
  searchAttributes?: SearchAttributes | undefined;
249
+ /**
250
+ * The worker-pool partition this run belongs to. Stamped at creation from the creating engine's
251
+ * `namespace` (default `'default'`). A worker only picks up / recovers / resumes-timers-for /
252
+ * times-out runs in its own namespace. `undefined` on a run created before this field existed; the
253
+ * store persists it as `'default'`. Read paths (dashboard, `getRun`) are NOT namespace-scoped.
254
+ */
255
+ namespace?: string | undefined;
249
256
  /**
250
257
  * Dispatch priority for a REMOTE run (one advanced by a {@link WorkflowExecutor} over a broker):
251
258
  * carried onto each {@link WorkflowTask} so an urgent child workflow can jump ahead of enqueued
@@ -433,11 +440,11 @@ interface StateStore {
433
440
  */
434
441
  saveCheckpoint(checkpoint: StepCheckpoint): Promise<void>;
435
442
  /** Used by recovery on boot to find runs to resume (crashed, left `running`). */
436
- listIncompleteRuns(): Promise<WorkflowRun[]>;
443
+ listIncompleteRuns(namespace?: string): Promise<WorkflowRun[]>;
437
444
  /** The oldest `pending` runs awaiting dispatch (FIFO, by `createdAt`), capped at `limit`. */
438
- listPendingRuns(limit: number): Promise<WorkflowRun[]>;
445
+ listPendingRuns(limit: number, namespace?: string): Promise<WorkflowRun[]>;
439
446
  /** Suspended runs whose durable timer is due (`wakeAt <= nowMs`), ready to resume. */
440
- listDueTimers(nowMs: number): Promise<WorkflowRun[]>;
447
+ listDueTimers(nowMs: number, namespace?: string): Promise<WorkflowRun[]>;
441
448
  /**
442
449
  * Atomically acquire the recovery lease on a run for `owner` until `leaseUntilMs`, but only if
443
450
  * it is currently unlocked or its lease has expired (`<= nowMs`). Returns whether it was
@@ -549,6 +556,8 @@ interface RunQuery {
549
556
  * `workflow`/`status`/`tag` to bound the scan on large stores.
550
557
  */
551
558
  attributes?: AttributeFilter[] | undefined;
559
+ /** Restrict to runs in this namespace (exact match), ANDed with the other predicates. */
560
+ namespace?: string | undefined;
552
561
  limit?: number | undefined;
553
562
  offset?: number | undefined;
554
563
  }
@@ -565,6 +574,15 @@ interface SignalWaiter {
565
574
  token: string;
566
575
  runId: string;
567
576
  seq: number;
577
+ /**
578
+ * The parallel-fan group this waiter belongs to, carried from the awaiting command so the resolving
579
+ * `signal:<token>` checkpoint (notably `signal:child:<id>` for an awaited child run) can be tagged
580
+ * with it. A worker's `ctx.gather_children`/`ctx.all` fan-out stamps every `startChild` with the same
581
+ * group; without threading it through the waiter, the child-await checkpoint comes out untagged and the
582
+ * dashboard renders the fan as a sequential chain instead of one parallel group. Undefined for an
583
+ * ordinary (non-fan) signal/child await.
584
+ */
585
+ parallelGroup?: string | undefined;
568
586
  }
569
587
  /** A unit of work dispatched to a remote worker. This is the documented wire payload. */
570
588
  interface RemoteTask {
@@ -1336,6 +1354,13 @@ interface WorkflowEngineDeps {
1336
1354
  admission?: AdmissionBackend | undefined;
1337
1355
  /** Unique id for this engine instance, used for recovery leases. Defaults to a random id. */
1338
1356
  instanceId?: string | undefined;
1357
+ /**
1358
+ * Worker-pool partition for this engine. Stamped on every run it creates; the poll paths
1359
+ * (`runPending`/`recoverIncomplete`/`resumeDueTimers`/`sweepTimeouts`) only act on runs in this
1360
+ * namespace. Default `'default'` — byte-identical to a single-pool deployment. Set distinct values
1361
+ * to safely share ONE state store across non-interchangeable pools (e.g. local dev vs a cluster).
1362
+ */
1363
+ namespace?: string | undefined;
1339
1364
  /** Recovery lease duration in ms — how long this instance owns a run it picked up. Default 30s. */
1340
1365
  leaseMs?: number | undefined;
1341
1366
  /**
@@ -1427,6 +1452,7 @@ declare class WorkflowEngine {
1427
1452
  private readonly controlPlane?;
1428
1453
  private readonly clock;
1429
1454
  private readonly instanceId;
1455
+ private readonly namespace;
1430
1456
  private readonly leaseMs;
1431
1457
  private readonly maxRecoveryAttempts?;
1432
1458
  private readonly remoteAdvanceSilenceMs?;
@@ -2146,9 +2172,9 @@ declare class CodecStateStore implements StateStore {
2146
2172
  raw: unknown;
2147
2173
  saveCheckpoint: (cp: StepCheckpoint) => Promise<void>;
2148
2174
  }) => Promise<T>): Promise<T>;
2149
- listIncompleteRuns(): Promise<WorkflowRun[]>;
2150
- listPendingRuns(limit: number): Promise<WorkflowRun[]>;
2151
- listDueTimers(nowMs: number): Promise<WorkflowRun[]>;
2175
+ listIncompleteRuns(namespace?: string): Promise<WorkflowRun[]>;
2176
+ listPendingRuns(limit: number, namespace?: string): Promise<WorkflowRun[]>;
2177
+ listDueTimers(nowMs: number, namespace?: string): Promise<WorkflowRun[]>;
2152
2178
  tryLockRun(runId: string, owner: string, leaseUntilMs: number, nowMs: number): Promise<boolean>;
2153
2179
  releaseRunLock(runId: string): Promise<void>;
2154
2180
  renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean>;
@@ -2410,9 +2436,9 @@ declare class InMemoryStateStore implements StateStore {
2410
2436
  deleteRun(runId: string): Promise<void>;
2411
2437
  getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null>;
2412
2438
  saveCheckpoint(checkpoint: StepCheckpoint): Promise<void>;
2413
- listIncompleteRuns(): Promise<WorkflowRun[]>;
2414
- listPendingRuns(limit: number): Promise<WorkflowRun[]>;
2415
- listDueTimers(nowMs: number): Promise<WorkflowRun[]>;
2439
+ listIncompleteRuns(namespace?: string): Promise<WorkflowRun[]>;
2440
+ listPendingRuns(limit: number, namespace?: string): Promise<WorkflowRun[]>;
2441
+ listDueTimers(nowMs: number, namespace?: string): Promise<WorkflowRun[]>;
2416
2442
  tryLockRun(runId: string, owner: string, leaseUntilMs: number, nowMs: number): Promise<boolean>;
2417
2443
  releaseRunLock(runId: string): Promise<void>;
2418
2444
  renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean>;
package/dist/index.js CHANGED
@@ -1208,7 +1208,8 @@ function createWorkflowCtx(host, runId, compensations, workflow = "") {
1208
1208
  await store.putSignalWaiter({
1209
1209
  token: `child:${childId}`,
1210
1210
  runId,
1211
- seq
1211
+ seq,
1212
+ parallelGroup: group
1212
1213
  });
1213
1214
  if (!await store.getRun(childId)) host.startChild(name, inputs[i], childId);
1214
1215
  if (!cp) {
@@ -1440,6 +1441,14 @@ function isNewerVersion(a, b) {
1440
1441
  }) > 0;
1441
1442
  }
1442
1443
  __name(isNewerVersion, "isNewerVersion");
1444
+ var NamespaceMismatch = class NamespaceMismatch2 extends Error {
1445
+ static {
1446
+ __name(this, "NamespaceMismatch");
1447
+ }
1448
+ constructor() {
1449
+ super("namespace-mismatch");
1450
+ }
1451
+ };
1443
1452
  var WorkflowEngine = class {
1444
1453
  static {
1445
1454
  __name(this, "WorkflowEngine");
@@ -1450,6 +1459,7 @@ var WorkflowEngine = class {
1450
1459
  controlPlane;
1451
1460
  clock;
1452
1461
  instanceId;
1462
+ namespace;
1453
1463
  leaseMs;
1454
1464
  maxRecoveryAttempts;
1455
1465
  remoteAdvanceSilenceMs;
@@ -1516,6 +1526,7 @@ var WorkflowEngine = class {
1516
1526
  this.admission = deps.admission ?? new InMemoryAdmissionBackend(this.clock);
1517
1527
  this.admission.onFreed?.((queue) => this.wakeQueueWaiters(queue));
1518
1528
  this.instanceId = deps.instanceId ?? globalThis.crypto.randomUUID();
1529
+ this.namespace = deps.namespace ?? "default";
1519
1530
  this.leaseMs = deps.leaseMs ?? 3e4;
1520
1531
  this.maxRecoveryAttempts = deps.maxRecoveryAttempts;
1521
1532
  this.remoteAdvanceSilenceMs = deps.remoteAdvanceSilenceMs;
@@ -1836,6 +1847,7 @@ var WorkflowEngine = class {
1836
1847
  workflow: name,
1837
1848
  workflowVersion: registered.version,
1838
1849
  status: "pending",
1850
+ namespace: this.namespace,
1839
1851
  input,
1840
1852
  tags,
1841
1853
  searchAttributes: opts?.searchAttributes,
@@ -1872,6 +1884,10 @@ var WorkflowEngine = class {
1872
1884
  error: run.error
1873
1885
  };
1874
1886
  }
1887
+ if (run.namespace !== void 0 && run.namespace !== this.namespace) {
1888
+ await this.store.releaseRunLock(runId);
1889
+ throw new NamespaceMismatch();
1890
+ }
1875
1891
  const registered = this.workflows.get(versionKey(run.workflow, run.workflowVersion)) ?? await this.findInheritedRegistration(run);
1876
1892
  if (!registered) {
1877
1893
  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)`);
@@ -1990,11 +2006,13 @@ var WorkflowEngine = class {
1990
2006
  const inflight = [
1991
2007
  ...await this.store.listRuns({
1992
2008
  workflow: reg.name,
1993
- status: "running"
2009
+ status: "running",
2010
+ namespace: this.namespace
1994
2011
  }),
1995
2012
  ...await this.store.listRuns({
1996
2013
  workflow: reg.name,
1997
- status: "suspended"
2014
+ status: "suspended",
2015
+ namespace: this.namespace
1998
2016
  })
1999
2017
  ];
2000
2018
  for (const run of inflight) {
@@ -2024,7 +2042,7 @@ var WorkflowEngine = class {
2024
2042
  async recoverIncomplete(nowMs = this.clock()) {
2025
2043
  if (this.draining) return [];
2026
2044
  const results = [];
2027
- for (const run of await this.store.listIncompleteRuns()) {
2045
+ for (const run of await this.store.listIncompleteRuns(this.namespace)) {
2028
2046
  const acquired = await this.store.tryLockRun(run.id, this.instanceId, nowMs + this.leaseMs, nowMs);
2029
2047
  if (!acquired) continue;
2030
2048
  const settled = await this.countRecovery(run);
@@ -2094,7 +2112,7 @@ var WorkflowEngine = class {
2094
2112
  * boot. A run still not due re-suspends cheaply without running new work.
2095
2113
  */
2096
2114
  async resumeDueTimers(nowMs = this.clock()) {
2097
- return this.resumeLeased(await this.store.listDueTimers(nowMs), nowMs);
2115
+ return this.resumeLeased(await this.store.listDueTimers(nowMs, this.namespace), nowMs);
2098
2116
  }
2099
2117
  /**
2100
2118
  * Lease and execute one run by id — the worker side of dispatch. Acquires the recovery lease (so
@@ -2107,7 +2125,10 @@ var WorkflowEngine = class {
2107
2125
  const nowMs = this.clock();
2108
2126
  const acquired = await this.store.tryLockRun(runId, this.instanceId, nowMs + this.leaseMs, nowMs);
2109
2127
  if (!acquired) return null;
2110
- return this.resume(runId);
2128
+ return this.resume(runId).catch((err) => {
2129
+ if (err instanceof NamespaceMismatch) return null;
2130
+ throw err;
2131
+ });
2111
2132
  }
2112
2133
  /**
2113
2134
  * Re-enqueue a run for a worker to (re-)execute — the dispatch-model **retry**. Sets it back to
@@ -2153,7 +2174,7 @@ var WorkflowEngine = class {
2153
2174
  * {@link resumeDueTimers}.
2154
2175
  */
2155
2176
  async runPending(nowMs = this.clock()) {
2156
- return this.resumeLeased(await this.store.listPendingRuns(100), nowMs);
2177
+ return this.resumeLeased(await this.store.listPendingRuns(100, this.namespace), nowMs);
2157
2178
  }
2158
2179
  /**
2159
2180
  * Resolve once `runId` reaches a settled state — terminal (completed/failed/cancelled/dead) or
@@ -2263,9 +2284,17 @@ var WorkflowEngine = class {
2263
2284
  seq: waiter.seq,
2264
2285
  name: `signal:${token}`,
2265
2286
  kind: "signal",
2266
- output: payload
2287
+ output: payload,
2288
+ // Carry the awaiting command's fan group (set when a `ctx.gather_children`/`ctx.all` fan-out
2289
+ // registered this waiter) onto the resolving `signal:child:<id>` checkpoint, so the dashboard
2290
+ // groups the child fan-out vertically instead of rendering it as a sequential chain. Undefined
2291
+ // for an ordinary (non-fan) signal/child await.
2292
+ parallelGroup: waiter.parallelGroup
2267
2293
  }));
2268
- return this.resume(waiter.runId);
2294
+ return this.resume(waiter.runId).catch((err) => {
2295
+ if (err instanceof NamespaceMismatch) return null;
2296
+ throw err;
2297
+ });
2269
2298
  }
2270
2299
  /**
2271
2300
  * Ensure a run exists for `runId`, then deliver a signal to it — atomically race-free thanks to
@@ -3030,7 +3059,12 @@ var WorkflowEngine = class {
3030
3059
  await this.store.putSignalWaiter({
3031
3060
  token: `child:${childId}`,
3032
3061
  runId: run.id,
3033
- seq: cmd.seq
3062
+ seq: cmd.seq,
3063
+ // A `ctx.gather_children`/`ctx.all` fan-out stamps every `startChild` in the fan with the same
3064
+ // group. Thread it onto the waiter so the child's terminal `signal:child:<id>` checkpoint
3065
+ // (written by engine.signal when the child notifies the parent) carries the group and the
3066
+ // dashboard renders the fan as one parallel group. Undefined for a lone (non-fan) child.
3067
+ parallelGroup: cmd.parallelGroup
3034
3068
  });
3035
3069
  if (!await this.store.getRun(childId)) {
3036
3070
  queueMicrotask(() => void this.start(cmd.workflow, cmd.input, childId).catch(() => void 0));
@@ -3419,7 +3453,10 @@ var WorkflowEngine = class {
3419
3453
  queueMs: startedAt.getTime() - cp.enqueuedAt.getTime(),
3420
3454
  durationMs: finishedAt.getTime() - startedAt.getTime()
3421
3455
  });
3422
- await this.resume(result.runId);
3456
+ await this.resume(result.runId).catch((err) => {
3457
+ if (err instanceof NamespaceMismatch) return null;
3458
+ throw err;
3459
+ });
3423
3460
  }
3424
3461
  /**
3425
3462
  * A slot freed on `queue` (a fleet-wide signal): resume this instance's runs blocked on it so they
@@ -3717,14 +3754,14 @@ var CodecStateStore = class {
3717
3754
  saveCheckpoint: /* @__PURE__ */ __name((cp) => tx.saveCheckpoint(this.encCp(cp)), "saveCheckpoint")
3718
3755
  }));
3719
3756
  }
3720
- async listIncompleteRuns() {
3721
- return (await this.inner.listIncompleteRuns()).map((r) => this.decRun(r));
3757
+ async listIncompleteRuns(namespace) {
3758
+ return (await this.inner.listIncompleteRuns(namespace)).map((r) => this.decRun(r));
3722
3759
  }
3723
- async listPendingRuns(limit) {
3724
- return (await this.inner.listPendingRuns(limit)).map((r) => this.decRun(r));
3760
+ async listPendingRuns(limit, namespace) {
3761
+ return (await this.inner.listPendingRuns(limit, namespace)).map((r) => this.decRun(r));
3725
3762
  }
3726
- async listDueTimers(nowMs) {
3727
- return (await this.inner.listDueTimers(nowMs)).map((r) => this.decRun(r));
3763
+ async listDueTimers(nowMs, namespace) {
3764
+ return (await this.inner.listDueTimers(nowMs, namespace)).map((r) => this.decRun(r));
3728
3765
  }
3729
3766
  tryLockRun(runId, owner, leaseUntilMs, nowMs) {
3730
3767
  return this.inner.tryLockRun(runId, owner, leaseUntilMs, nowMs);
@@ -4079,7 +4116,8 @@ var InMemoryStateStore = class {
4079
4116
  }
4080
4117
  async createRun(run) {
4081
4118
  this.runs.set(run.id, {
4082
- ...run
4119
+ ...run,
4120
+ namespace: run.namespace ?? "default"
4083
4121
  });
4084
4122
  this.reindexAttributes(run.id, run.searchAttributes);
4085
4123
  }
@@ -4120,24 +4158,24 @@ var InMemoryStateStore = class {
4120
4158
  ...checkpoint
4121
4159
  });
4122
4160
  }
4123
- async listIncompleteRuns() {
4161
+ async listIncompleteRuns(namespace) {
4124
4162
  return [
4125
4163
  ...this.runs.values()
4126
- ].filter((r) => r.status === "running" || r.status === "cancelling").map((r) => ({
4164
+ ].filter((r) => (r.status === "running" || r.status === "cancelling") && (namespace === void 0 || r.namespace === namespace)).map((r) => ({
4127
4165
  ...r
4128
4166
  }));
4129
4167
  }
4130
- async listPendingRuns(limit) {
4168
+ async listPendingRuns(limit, namespace) {
4131
4169
  return [
4132
4170
  ...this.runs.values()
4133
- ].filter((r) => r.status === "pending").sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime() || a.id.localeCompare(b.id)).slice(0, limit).map((r) => ({
4171
+ ].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) => ({
4134
4172
  ...r
4135
4173
  }));
4136
4174
  }
4137
- async listDueTimers(nowMs) {
4175
+ async listDueTimers(nowMs, namespace) {
4138
4176
  return [
4139
4177
  ...this.runs.values()
4140
- ].filter((r) => r.status === "suspended" && r.wakeAt !== void 0 && r.wakeAt <= nowMs).map((r) => ({
4178
+ ].filter((r) => r.status === "suspended" && r.wakeAt !== void 0 && r.wakeAt <= nowMs && (namespace === void 0 || r.namespace === namespace)).map((r) => ({
4141
4179
  ...r
4142
4180
  }));
4143
4181
  }
@@ -4252,6 +4290,7 @@ var InMemoryStateStore = class {
4252
4290
  if (query.status) runs = runs.filter((r) => r.status === query.status);
4253
4291
  if (query.statuses) runs = runs.filter((r) => query.statuses?.includes(r.status));
4254
4292
  if (query.tag) runs = runs.filter((r) => r.tags?.includes(query.tag));
4293
+ if (query.namespace !== void 0) runs = runs.filter((r) => r.namespace === query.namespace);
4255
4294
  if (query.attributes?.length) {
4256
4295
  let candidates = null;
4257
4296
  for (const f of query.attributes) {