@dudousxd/nestjs-durable 0.35.0 → 0.37.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
@@ -129,6 +129,9 @@ interface WorkflowMeta {
129
129
  maxSize: number;
130
130
  within: string | number;
131
131
  } | undefined;
132
+ /** Capabilities a live worker must advertise to run this workflow's turns (handshake §7.5). See
133
+ * `WorkflowOptions`. */
134
+ requires?: string[] | undefined;
132
135
  }
133
136
  interface WorkflowOptions {
134
137
  name: string;
@@ -159,6 +162,14 @@ interface WorkflowOptions {
159
162
  * runs that get stuck or loop forever. Omit for no limit.
160
163
  */
161
164
  executionTimeout?: string | number;
165
+ /**
166
+ * Capabilities a live worker MUST advertise to run this workflow's turns (handshake design §7.5).
167
+ * Only meaningful for a group-served / remote workflow (an in-app worker or a cross-runtime body):
168
+ * the control-plane dispatches a turn only to a capability-capable + protocol-compatible worker, and
169
+ * if descriptors are published on its group but none qualifies the run parks `blocked` until the
170
+ * recovery poll finds one. Absent/empty = "runs anywhere" (a legacy fleet skips the guard, §7.7).
171
+ */
172
+ requires?: string[];
162
173
  /**
163
174
  * Validate the workflow input at `start` against a **class-validator DTO** (the same
164
175
  * `plainToInstance` + `validate` NestJS runs in controllers) — invalid input is rejected before any
@@ -266,6 +277,15 @@ interface StepOptions {
266
277
  * `retries`). Omit to wait indefinitely.
267
278
  */
268
279
  timeoutMs?: number;
280
+ /**
281
+ * Capabilities a live worker MUST advertise to run this step (handshake design §7.5). The
282
+ * control-plane routes the step only to workers whose descriptor advertises every name here; if
283
+ * descriptors are published on the step's group but none is capability-capable + protocol-compatible,
284
+ * the run parks `blocked` (never a silent hang) until the recovery poll finds one. Absent/empty =
285
+ * "runs anywhere" (the default — a legacy fleet publishing no descriptors skips the guard, §7.7). A
286
+ * per-call `ctx.step(ref, input, { requires })` overrides this.
287
+ */
288
+ requires?: string[];
269
289
  }
270
290
  /**
271
291
  * Marks a provider method as a durable step handler. An in-process transport (e.g. the
@@ -623,18 +643,6 @@ interface DurableModuleOptions {
623
643
  topology?: {
624
644
  role: 'control-plane';
625
645
  tenant?: string;
626
- /**
627
- * `'bridge'` — this operator's tenant workers follow the OPERATOR convention (bare
628
- * transport prefix + `@<tenant>`-suffixed groups: the Python SDK, the TS `role: 'tenant'`
629
- * worker). When `tenant` is set, the preset pairs the configured `transport` with a
630
- * bare-prefix sibling (`transport.withNamespace('default')`) in a pool, so those workers
631
- * are discoverable and dispatchable from this otherwise-namespaced keyspace. INERT when
632
- * `tenant` is unset (a global operator is already on the bare prefix) — safe to leave on a
633
- * static config that reads `tenant` from an env var. CAUTION: the bare sibling consumes
634
- * the shared bare control queues — only sound when this stack owns its broker (a private
635
- * Redis); on a shared broker, point the tenant workers at a scoped prefix instead.
636
- */
637
- tenantWorkers?: 'bridge';
638
646
  } | {
639
647
  role: 'tenant';
640
648
  tenant: string;
package/dist/index.d.ts CHANGED
@@ -129,6 +129,9 @@ interface WorkflowMeta {
129
129
  maxSize: number;
130
130
  within: string | number;
131
131
  } | undefined;
132
+ /** Capabilities a live worker must advertise to run this workflow's turns (handshake §7.5). See
133
+ * `WorkflowOptions`. */
134
+ requires?: string[] | undefined;
132
135
  }
133
136
  interface WorkflowOptions {
134
137
  name: string;
@@ -159,6 +162,14 @@ interface WorkflowOptions {
159
162
  * runs that get stuck or loop forever. Omit for no limit.
160
163
  */
161
164
  executionTimeout?: string | number;
165
+ /**
166
+ * Capabilities a live worker MUST advertise to run this workflow's turns (handshake design §7.5).
167
+ * Only meaningful for a group-served / remote workflow (an in-app worker or a cross-runtime body):
168
+ * the control-plane dispatches a turn only to a capability-capable + protocol-compatible worker, and
169
+ * if descriptors are published on its group but none qualifies the run parks `blocked` until the
170
+ * recovery poll finds one. Absent/empty = "runs anywhere" (a legacy fleet skips the guard, §7.7).
171
+ */
172
+ requires?: string[];
162
173
  /**
163
174
  * Validate the workflow input at `start` against a **class-validator DTO** (the same
164
175
  * `plainToInstance` + `validate` NestJS runs in controllers) — invalid input is rejected before any
@@ -266,6 +277,15 @@ interface StepOptions {
266
277
  * `retries`). Omit to wait indefinitely.
267
278
  */
268
279
  timeoutMs?: number;
280
+ /**
281
+ * Capabilities a live worker MUST advertise to run this step (handshake design §7.5). The
282
+ * control-plane routes the step only to workers whose descriptor advertises every name here; if
283
+ * descriptors are published on the step's group but none is capability-capable + protocol-compatible,
284
+ * the run parks `blocked` (never a silent hang) until the recovery poll finds one. Absent/empty =
285
+ * "runs anywhere" (the default — a legacy fleet publishing no descriptors skips the guard, §7.7). A
286
+ * per-call `ctx.step(ref, input, { requires })` overrides this.
287
+ */
288
+ requires?: string[];
269
289
  }
270
290
  /**
271
291
  * Marks a provider method as a durable step handler. An in-process transport (e.g. the
@@ -623,18 +643,6 @@ interface DurableModuleOptions {
623
643
  topology?: {
624
644
  role: 'control-plane';
625
645
  tenant?: string;
626
- /**
627
- * `'bridge'` — this operator's tenant workers follow the OPERATOR convention (bare
628
- * transport prefix + `@<tenant>`-suffixed groups: the Python SDK, the TS `role: 'tenant'`
629
- * worker). When `tenant` is set, the preset pairs the configured `transport` with a
630
- * bare-prefix sibling (`transport.withNamespace('default')`) in a pool, so those workers
631
- * are discoverable and dispatchable from this otherwise-namespaced keyspace. INERT when
632
- * `tenant` is unset (a global operator is already on the bare prefix) — safe to leave on a
633
- * static config that reads `tenant` from an env var. CAUTION: the bare sibling consumes
634
- * the shared bare control queues — only sound when this stack owns its broker (a private
635
- * Redis); on a shared broker, point the tenant workers at a scoped prefix instead.
636
- */
637
- tenantWorkers?: 'bridge';
638
646
  } | {
639
647
  role: 'tenant';
640
648
  tenant: string;
package/dist/index.js CHANGED
@@ -28,7 +28,8 @@ function Workflow(options) {
28
28
  searchAttributes: options.searchAttributes,
29
29
  onEvent: options.onEvent,
30
30
  debounce: options.debounce,
31
- batch: options.batch
31
+ batch: options.batch,
32
+ requires: options.requires
32
33
  };
33
34
  Reflect.defineMetadata(WORKFLOW_METADATA, meta, target);
34
35
  Object.defineProperty(target, WORKFLOW_NAME_KEY, {
@@ -50,7 +51,8 @@ function stepConfigFrom(options) {
50
51
  backoffMs: options.backoffMs,
51
52
  backoffMaxMs: options.backoffMaxMs,
52
53
  jitter: options.jitter,
53
- timeoutMs: options.timeoutMs
54
+ timeoutMs: options.timeoutMs,
55
+ requires: options.requires
54
56
  };
55
57
  const hasAnyField = Object.values(config).some((value) => value !== void 0);
56
58
  return hasAnyField ? config : void 0;
@@ -1553,6 +1555,7 @@ var WorkflowRegistrar = class {
1553
1555
  tags: meta.tags,
1554
1556
  singleton: meta.singleton,
1555
1557
  executionTimeout: meta.executionTimeout,
1558
+ requires: meta.requires,
1556
1559
  validateInput,
1557
1560
  searchAttributesSchema: meta.searchAttributes,
1558
1561
  onEvent: getOnEvents(meta, workflowCtor),
@@ -1828,10 +1831,10 @@ function resolveTopology(options) {
1828
1831
  if (topology === void 0) return options;
1829
1832
  if (topology.role === "control-plane") {
1830
1833
  if (topology.tenant === void 0 || options.namespace !== void 0) return options;
1831
- return resolveTenantWorkersBridge({
1834
+ return {
1832
1835
  ...options,
1833
1836
  namespace: topology.tenant
1834
- });
1837
+ };
1835
1838
  }
1836
1839
  if (options.partition !== void 0) return options;
1837
1840
  return {
@@ -1840,30 +1843,6 @@ function resolveTopology(options) {
1840
1843
  };
1841
1844
  }
1842
1845
  __name(resolveTopology, "resolveTopology");
1843
- function resolveTenantWorkersBridge(options) {
1844
- const topology = options.topology;
1845
- if (topology?.role !== "control-plane" || topology.tenantWorkers !== "bridge") return options;
1846
- if (options.transports !== void 0) return options;
1847
- const primary = options.transport;
1848
- if (primary === void 0) return options;
1849
- if (primary.withNamespace === void 0) {
1850
- throw new Error("topology: { tenantWorkers: 'bridge' } needs a transport implementing `withNamespace` (e.g. BullMQTransport) \u2014 the bridge derives a bare-prefix sibling from the configured transport to reach operator-convention tenant workers.");
1851
- }
1852
- return {
1853
- ...options,
1854
- transports: [
1855
- {
1856
- id: "default",
1857
- transport: primary
1858
- },
1859
- {
1860
- id: "tenant-workers",
1861
- transport: primary.withNamespace("default")
1862
- }
1863
- ]
1864
- };
1865
- }
1866
- __name(resolveTenantWorkersBridge, "resolveTenantWorkersBridge");
1867
1846
  var RunGatewayBootstrap = class RunGatewayBootstrap2 {
1868
1847
  static {
1869
1848
  __name(this, "RunGatewayBootstrap");