@dudousxd/nestjs-durable 0.43.2 → 0.45.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
@@ -1,5 +1,5 @@
1
- import { WorkflowCtx, SearchAttributes, WorkflowClass, StepError, WorkflowRef, SingletonConfig, SearchAttributesSchema, StateStore, Transport, NamedTransport, ControlPlane, ScheduledWorkflow, RetentionPolicy, QueueConfig, AdmissionBackend, WorkflowInputOf, StartOptions, RunResult, RunGateway, WorkflowEngine, EntityHandler, DurableTopology, RunDetail, RunQuery, RunListItem, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, GroupHealth, RunWaiting, EngineEvent, RunRequest, RunReply, StepInvocation, TenantEvent } from '@dudousxd/nestjs-durable-core';
2
- export { AttributeFilter, EngineEvent, InferSearchAttributes, RunDetail, RunGateway, RunListItem, RunQuery, RunStatus, RunWaiting, SearchAttributes, SearchAttributesSchema, StepCheckpoint, StepEvent, StepLogger, WorkflowCtx, WorkflowEngine, WorkflowHandler, WorkflowRun, readSearchAttributes } from '@dudousxd/nestjs-durable-core';
1
+ import { WorkflowCtx, SearchAttributes, WorkflowClass, StepError, WorkflowRef, SingletonConfig, ConcurrencyConfig, SearchAttributesSchema, StateStore, Transport, NamedTransport, ControlPlane, ScheduledWorkflow, RetentionPolicy, QueueConfig, AdmissionBackend, WorkflowInputOf, StartOptions, RunResult, RunGateway, WorkflowEngine, EntityHandler, DurableTopology, RunDetail, RunQuery, RunListItem, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, GroupHealth, RunWaiting, EngineEvent, RunRequest, RunReply, StepInvocation, TenantEvent } from '@dudousxd/nestjs-durable-core';
2
+ export { AttributeFilter, DynamicWorkflowCtx, EngineEvent, InferSearchAttributes, RunDetail, RunGateway, RunListItem, RunQuery, RunStatus, RunWaiting, SearchAttributes, SearchAttributesSchema, StepCheckpoint, StepEvent, StepLogger, WorkflowCtx, WorkflowEngine, WorkflowHandler, WorkflowRun, readSearchAttributes } from '@dudousxd/nestjs-durable-core';
3
3
  import { z } from 'zod';
4
4
  import { ConcurrencyOption, StartRunDeps, RunRedisWorkerOptions, RunningWorker, DurableWorkerRuntime } from '@dudousxd/durable-worker';
5
5
  import { DynamicModule, InjectionToken, OnModuleInit, OnApplicationBootstrap, OnApplicationShutdown, Provider } from '@nestjs/common';
@@ -112,6 +112,8 @@ interface WorkflowMeta {
112
112
  tags?: string[] | undefined;
113
113
  /** Per-key serialization (a durable mutex). See `WorkflowOptions`. */
114
114
  singleton?: SingletonConfig | undefined;
115
+ /** Start-time concurrency quota (rejecting). See `WorkflowOptions`. */
116
+ concurrency?: ConcurrencyConfig | undefined;
115
117
  /** Max wall-clock lifetime before a run is cancelled (e.g. `'2h'`). See `WorkflowOptions`. */
116
118
  executionTimeout?: string | number | undefined;
117
119
  /** class-validator DTO validated at start. See `WorkflowOptions`. */
@@ -156,6 +158,15 @@ interface WorkflowOptions {
156
158
  * 1) raises the concurrency.
157
159
  */
158
160
  singleton?: SingletonConfig;
161
+ /**
162
+ * A start-time concurrency QUOTA: at most `limit` runs sharing a key in flight, and a start over it
163
+ * is REJECTED (`ConcurrencyLimitError`, nothing created) rather than queued. e.g.
164
+ * `concurrency: { key: (input) => `tenant:${input.tenantId}`, limit: 8 }` caps what one tenant can
165
+ * have executing at once. The key is shared across workflows; `limit` may be a (async) function of
166
+ * the key for per-plan limits; `countStatuses` narrows what occupies a slot (default: every
167
+ * non-terminal status). Use `singleton` instead when excess runs should wait their turn.
168
+ */
169
+ concurrency?: ConcurrencyConfig;
159
170
  /**
160
171
  * Max wall-clock lifetime for a run of this workflow (e.g. `'2h'`, `'7 days'`, or ms). A run that
161
172
  * outlives it is moved to `cancelled` (`execution_timeout`) by the timer poller — a backstop for
@@ -363,7 +374,7 @@ declare function getOnEvents(meta: WorkflowMeta, target: object): string[];
363
374
 
364
375
  /**
365
376
  * Retention config for the {@link RetentionPoller}. One or more {@link RetentionPolicy policies}
366
- * (status sets must be disjoint — validated at boot), swept together on a shared interval.
377
+ * (status sets must be disjoint per scope — validated at boot), swept together on a shared interval.
367
378
  *
368
379
  * ```ts
369
380
  * retention: {
@@ -372,9 +383,14 @@ declare function getOnEvents(meta: WorkflowMeta, target: object): string[];
372
383
  * policies: [
373
384
  * { statuses: ['completed', 'cancelled'], maxAge: '14d', maxCount: 200 },
374
385
  * { statuses: ['failed'], maxAge: '90d' }, // keep failures longer for debugging
386
+ * // Scoped: chat turns age out after a day, whatever the defaults above say.
387
+ * { statuses: ['completed', 'failed', 'cancelled'], maxAge: '1d', scope: { tags: ['chat'] } },
375
388
  * ],
376
389
  * }
377
390
  * ```
391
+ *
392
+ * Policies are applied one after another, so a run matched by several scopes is pruned by the
393
+ * strictest of them.
378
394
  */
379
395
  interface DurableRetentionOptions {
380
396
  /** The retention rules, one per (disjoint) status group. */
@@ -464,6 +480,26 @@ interface DurableModuleOptions {
464
480
  * Operator only.
465
481
  */
466
482
  remoteAdvanceSilenceMs?: number;
483
+ /**
484
+ * Opt-in self-heal window (ms) for a dispatched remote step whose job was LOST — the worker was
485
+ * killed mid-step (an OOM kill leaves no result, and a non-TS consumer has no way to bridge the
486
+ * job's terminal failure back into one), or the broker dropped the job. The `pending` checkpoint
487
+ * then has nothing left to settle it, so the run waits forever. When set, the pending checkpoint
488
+ * carries a LEASE: a result — or a step-scoped heartbeat, which renews it, so a worker still
489
+ * holding the step is never double-dispatched — must land within the window, else the engine
490
+ * re-dispatches the same step (bumping `attempts`, bounded by {@link remoteRedispatchMax}).
491
+ * Covers both `ctx.step` and a polyglot workflow's `call` fan-out (`ctx.gather_calls`).
492
+ *
493
+ * Off by default: a re-dispatch double-runs a step whose original job was merely SLOW, so the
494
+ * window MUST exceed your longest remote step and the step MUST be idempotent. Operator only.
495
+ */
496
+ remoteRedispatchMs?: number;
497
+ /**
498
+ * Max times {@link remoteRedispatchMs} re-dispatches one lost step before failing it
499
+ * (`remote_step_lost`, surfaced on the run) instead of re-dispatching forever. Defaults to 10.
500
+ * Ignored when `remoteRedispatchMs` is unset. Operator only.
501
+ */
502
+ remoteRedispatchMax?: number;
467
503
  /**
468
504
  * The **default** workflow to route dead-lettered runs to, for workflows that don't declare their
469
505
  * own. When a run is moved to `dead` (exceeded `maxRecoveryAttempts`), the started handler gets a
@@ -493,12 +529,21 @@ interface DurableModuleOptions {
493
529
  * optional `cron-parser` peer dependency. Operator only.
494
530
  */
495
531
  schedules?: ScheduledWorkflow[];
532
+ /**
533
+ * Fire the PERSISTED schedules managed at runtime through `engine.schedules` (create/upsert/pause/
534
+ * resume/delete/list) on every timer-poll tick of a driving instance — one indexed "due by now"
535
+ * query per tick. Off by default, so a deployment that never uses them doesn't need the
536
+ * `durable_schedules` table. Safe with any number of driving instances: each window's run id is
537
+ * deterministic and advancing a schedule is a compare-and-set. Operator only.
538
+ */
539
+ persistedSchedules?: boolean;
496
540
  /**
497
541
  * Hard-prune terminal run history on an interval so `durable_workflow_runs` (and its child tables)
498
542
  * stays bounded — without it, completed/failed/cancelled runs accumulate forever and the timer
499
543
  * poller's per-tick status scans get linearly slower. Driving instances only. Omit to keep all
500
- * history (the default). Requires a store adapter that implements `pruneTerminalRuns` (the
501
- * MikroORM adapter does); other adapters no-op with a warning. See {@link DurableRetentionOptions}.
544
+ * history (the default). Requires a store adapter that implements `pruneTerminalRuns` (every
545
+ * first-party adapter does); a custom store without it no-ops with a warning. See
546
+ * {@link DurableRetentionOptions}.
502
547
  * Operator only.
503
548
  */
504
549
  retention?: DurableRetentionOptions;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { WorkflowCtx, SearchAttributes, WorkflowClass, StepError, WorkflowRef, SingletonConfig, SearchAttributesSchema, StateStore, Transport, NamedTransport, ControlPlane, ScheduledWorkflow, RetentionPolicy, QueueConfig, AdmissionBackend, WorkflowInputOf, StartOptions, RunResult, RunGateway, WorkflowEngine, EntityHandler, DurableTopology, RunDetail, RunQuery, RunListItem, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, GroupHealth, RunWaiting, EngineEvent, RunRequest, RunReply, StepInvocation, TenantEvent } from '@dudousxd/nestjs-durable-core';
2
- export { AttributeFilter, EngineEvent, InferSearchAttributes, RunDetail, RunGateway, RunListItem, RunQuery, RunStatus, RunWaiting, SearchAttributes, SearchAttributesSchema, StepCheckpoint, StepEvent, StepLogger, WorkflowCtx, WorkflowEngine, WorkflowHandler, WorkflowRun, readSearchAttributes } from '@dudousxd/nestjs-durable-core';
1
+ import { WorkflowCtx, SearchAttributes, WorkflowClass, StepError, WorkflowRef, SingletonConfig, ConcurrencyConfig, SearchAttributesSchema, StateStore, Transport, NamedTransport, ControlPlane, ScheduledWorkflow, RetentionPolicy, QueueConfig, AdmissionBackend, WorkflowInputOf, StartOptions, RunResult, RunGateway, WorkflowEngine, EntityHandler, DurableTopology, RunDetail, RunQuery, RunListItem, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, GroupHealth, RunWaiting, EngineEvent, RunRequest, RunReply, StepInvocation, TenantEvent } from '@dudousxd/nestjs-durable-core';
2
+ export { AttributeFilter, DynamicWorkflowCtx, EngineEvent, InferSearchAttributes, RunDetail, RunGateway, RunListItem, RunQuery, RunStatus, RunWaiting, SearchAttributes, SearchAttributesSchema, StepCheckpoint, StepEvent, StepLogger, WorkflowCtx, WorkflowEngine, WorkflowHandler, WorkflowRun, readSearchAttributes } from '@dudousxd/nestjs-durable-core';
3
3
  import { z } from 'zod';
4
4
  import { ConcurrencyOption, StartRunDeps, RunRedisWorkerOptions, RunningWorker, DurableWorkerRuntime } from '@dudousxd/durable-worker';
5
5
  import { DynamicModule, InjectionToken, OnModuleInit, OnApplicationBootstrap, OnApplicationShutdown, Provider } from '@nestjs/common';
@@ -112,6 +112,8 @@ interface WorkflowMeta {
112
112
  tags?: string[] | undefined;
113
113
  /** Per-key serialization (a durable mutex). See `WorkflowOptions`. */
114
114
  singleton?: SingletonConfig | undefined;
115
+ /** Start-time concurrency quota (rejecting). See `WorkflowOptions`. */
116
+ concurrency?: ConcurrencyConfig | undefined;
115
117
  /** Max wall-clock lifetime before a run is cancelled (e.g. `'2h'`). See `WorkflowOptions`. */
116
118
  executionTimeout?: string | number | undefined;
117
119
  /** class-validator DTO validated at start. See `WorkflowOptions`. */
@@ -156,6 +158,15 @@ interface WorkflowOptions {
156
158
  * 1) raises the concurrency.
157
159
  */
158
160
  singleton?: SingletonConfig;
161
+ /**
162
+ * A start-time concurrency QUOTA: at most `limit` runs sharing a key in flight, and a start over it
163
+ * is REJECTED (`ConcurrencyLimitError`, nothing created) rather than queued. e.g.
164
+ * `concurrency: { key: (input) => `tenant:${input.tenantId}`, limit: 8 }` caps what one tenant can
165
+ * have executing at once. The key is shared across workflows; `limit` may be a (async) function of
166
+ * the key for per-plan limits; `countStatuses` narrows what occupies a slot (default: every
167
+ * non-terminal status). Use `singleton` instead when excess runs should wait their turn.
168
+ */
169
+ concurrency?: ConcurrencyConfig;
159
170
  /**
160
171
  * Max wall-clock lifetime for a run of this workflow (e.g. `'2h'`, `'7 days'`, or ms). A run that
161
172
  * outlives it is moved to `cancelled` (`execution_timeout`) by the timer poller — a backstop for
@@ -363,7 +374,7 @@ declare function getOnEvents(meta: WorkflowMeta, target: object): string[];
363
374
 
364
375
  /**
365
376
  * Retention config for the {@link RetentionPoller}. One or more {@link RetentionPolicy policies}
366
- * (status sets must be disjoint — validated at boot), swept together on a shared interval.
377
+ * (status sets must be disjoint per scope — validated at boot), swept together on a shared interval.
367
378
  *
368
379
  * ```ts
369
380
  * retention: {
@@ -372,9 +383,14 @@ declare function getOnEvents(meta: WorkflowMeta, target: object): string[];
372
383
  * policies: [
373
384
  * { statuses: ['completed', 'cancelled'], maxAge: '14d', maxCount: 200 },
374
385
  * { statuses: ['failed'], maxAge: '90d' }, // keep failures longer for debugging
386
+ * // Scoped: chat turns age out after a day, whatever the defaults above say.
387
+ * { statuses: ['completed', 'failed', 'cancelled'], maxAge: '1d', scope: { tags: ['chat'] } },
375
388
  * ],
376
389
  * }
377
390
  * ```
391
+ *
392
+ * Policies are applied one after another, so a run matched by several scopes is pruned by the
393
+ * strictest of them.
378
394
  */
379
395
  interface DurableRetentionOptions {
380
396
  /** The retention rules, one per (disjoint) status group. */
@@ -464,6 +480,26 @@ interface DurableModuleOptions {
464
480
  * Operator only.
465
481
  */
466
482
  remoteAdvanceSilenceMs?: number;
483
+ /**
484
+ * Opt-in self-heal window (ms) for a dispatched remote step whose job was LOST — the worker was
485
+ * killed mid-step (an OOM kill leaves no result, and a non-TS consumer has no way to bridge the
486
+ * job's terminal failure back into one), or the broker dropped the job. The `pending` checkpoint
487
+ * then has nothing left to settle it, so the run waits forever. When set, the pending checkpoint
488
+ * carries a LEASE: a result — or a step-scoped heartbeat, which renews it, so a worker still
489
+ * holding the step is never double-dispatched — must land within the window, else the engine
490
+ * re-dispatches the same step (bumping `attempts`, bounded by {@link remoteRedispatchMax}).
491
+ * Covers both `ctx.step` and a polyglot workflow's `call` fan-out (`ctx.gather_calls`).
492
+ *
493
+ * Off by default: a re-dispatch double-runs a step whose original job was merely SLOW, so the
494
+ * window MUST exceed your longest remote step and the step MUST be idempotent. Operator only.
495
+ */
496
+ remoteRedispatchMs?: number;
497
+ /**
498
+ * Max times {@link remoteRedispatchMs} re-dispatches one lost step before failing it
499
+ * (`remote_step_lost`, surfaced on the run) instead of re-dispatching forever. Defaults to 10.
500
+ * Ignored when `remoteRedispatchMs` is unset. Operator only.
501
+ */
502
+ remoteRedispatchMax?: number;
467
503
  /**
468
504
  * The **default** workflow to route dead-lettered runs to, for workflows that don't declare their
469
505
  * own. When a run is moved to `dead` (exceeded `maxRecoveryAttempts`), the started handler gets a
@@ -493,12 +529,21 @@ interface DurableModuleOptions {
493
529
  * optional `cron-parser` peer dependency. Operator only.
494
530
  */
495
531
  schedules?: ScheduledWorkflow[];
532
+ /**
533
+ * Fire the PERSISTED schedules managed at runtime through `engine.schedules` (create/upsert/pause/
534
+ * resume/delete/list) on every timer-poll tick of a driving instance — one indexed "due by now"
535
+ * query per tick. Off by default, so a deployment that never uses them doesn't need the
536
+ * `durable_schedules` table. Safe with any number of driving instances: each window's run id is
537
+ * deterministic and advancing a schedule is a compare-and-set. Operator only.
538
+ */
539
+ persistedSchedules?: boolean;
496
540
  /**
497
541
  * Hard-prune terminal run history on an interval so `durable_workflow_runs` (and its child tables)
498
542
  * stays bounded — without it, completed/failed/cancelled runs accumulate forever and the timer
499
543
  * poller's per-tick status scans get linearly slower. Driving instances only. Omit to keep all
500
- * history (the default). Requires a store adapter that implements `pruneTerminalRuns` (the
501
- * MikroORM adapter does); other adapters no-op with a warning. See {@link DurableRetentionOptions}.
544
+ * history (the default). Requires a store adapter that implements `pruneTerminalRuns` (every
545
+ * first-party adapter does); a custom store without it no-ops with a warning. See
546
+ * {@link DurableRetentionOptions}.
502
547
  * Operator only.
503
548
  */
504
549
  retention?: DurableRetentionOptions;
package/dist/index.js CHANGED
@@ -127,6 +127,7 @@ function Workflow(options) {
127
127
  deadLetterWorkflow: options.deadLetterWorkflow,
128
128
  tags: options.tags,
129
129
  singleton: options.singleton,
130
+ concurrency: options.concurrency,
130
131
  executionTimeout: options.executionTimeout,
131
132
  inputSchema: options.inputSchema,
132
133
  validateInput: options.validateInput,
@@ -263,13 +264,22 @@ __name(createWorkerRuntime, "createWorkerRuntime");
263
264
  // src/durable-start-client.ts
264
265
  function _ts_decorate(decorators, target, key, desc) {
265
266
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
266
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
267
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
267
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
268
+ r = Reflect.decorate(decorators, target, key, desc);
269
+ } else {
270
+ for (var i = decorators.length - 1; i >= 0; i--) {
271
+ if (d = decorators[i]) {
272
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
273
+ }
274
+ }
275
+ }
268
276
  return c > 3 && r && Object.defineProperty(target, key, r), r;
269
277
  }
270
278
  __name(_ts_decorate, "_ts_decorate");
271
- function _ts_metadata(k, v) {
272
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
279
+ function _ts_metadata(metadataKey, metadataValue) {
280
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
281
+ return Reflect.metadata(metadataKey, metadataValue);
282
+ }
273
283
  }
274
284
  __name(_ts_metadata, "_ts_metadata");
275
285
  var DurableStartClient = class {
@@ -397,13 +407,22 @@ __name(scanSteps, "scanSteps");
397
407
  // src/durable-worker.module.ts
398
408
  function _ts_decorate2(decorators, target, key, desc) {
399
409
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
400
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
401
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
410
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
411
+ r = Reflect.decorate(decorators, target, key, desc);
412
+ } else {
413
+ for (var i = decorators.length - 1; i >= 0; i--) {
414
+ if (d = decorators[i]) {
415
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
416
+ }
417
+ }
418
+ }
402
419
  return c > 3 && r && Object.defineProperty(target, key, r), r;
403
420
  }
404
421
  __name(_ts_decorate2, "_ts_decorate");
405
- function _ts_metadata2(k, v) {
406
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
422
+ function _ts_metadata2(metadataKey, metadataValue) {
423
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
424
+ return Reflect.metadata(metadataKey, metadataValue);
425
+ }
407
426
  }
408
427
  __name(_ts_metadata2, "_ts_metadata");
409
428
  function _ts_param(paramIndex, decorator) {
@@ -655,13 +674,22 @@ __name(isDrivingOperator, "isDrivingOperator");
655
674
  // src/durable-step.registrar.ts
656
675
  function _ts_decorate3(decorators, target, key, desc) {
657
676
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
658
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
659
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
677
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
678
+ r = Reflect.decorate(decorators, target, key, desc);
679
+ } else {
680
+ for (var i = decorators.length - 1; i >= 0; i--) {
681
+ if (d = decorators[i]) {
682
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
683
+ }
684
+ }
685
+ }
660
686
  return c > 3 && r && Object.defineProperty(target, key, r), r;
661
687
  }
662
688
  __name(_ts_decorate3, "_ts_decorate");
663
- function _ts_metadata3(k, v) {
664
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
689
+ function _ts_metadata3(metadataKey, metadataValue) {
690
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
691
+ return Reflect.metadata(metadataKey, metadataValue);
692
+ }
665
693
  }
666
694
  __name(_ts_metadata3, "_ts_metadata");
667
695
  function _ts_param2(paramIndex, decorator) {
@@ -714,13 +742,22 @@ import { Injectable as Injectable4 } from "@nestjs/common";
714
742
  import "reflect-metadata";
715
743
  function _ts_decorate4(decorators, target, key, desc) {
716
744
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
717
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
718
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
745
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
746
+ r = Reflect.decorate(decorators, target, key, desc);
747
+ } else {
748
+ for (var i = decorators.length - 1; i >= 0; i--) {
749
+ if (d = decorators[i]) {
750
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
751
+ }
752
+ }
753
+ }
719
754
  return c > 3 && r && Object.defineProperty(target, key, r), r;
720
755
  }
721
756
  __name(_ts_decorate4, "_ts_decorate");
722
- function _ts_metadata4(k, v) {
723
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
757
+ function _ts_metadata4(metadataKey, metadataValue) {
758
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
759
+ return Reflect.metadata(metadataKey, metadataValue);
760
+ }
724
761
  }
725
762
  __name(_ts_metadata4, "_ts_metadata");
726
763
  var ENTITY_METADATA = Symbol("nestjs-durable:entity");
@@ -793,13 +830,22 @@ import { Inject as Inject3, Injectable as Injectable5 } from "@nestjs/common";
793
830
  import { DiscoveryService as DiscoveryService3, MetadataScanner as MetadataScanner3 } from "@nestjs/core";
794
831
  function _ts_decorate5(decorators, target, key, desc) {
795
832
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
796
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
797
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
833
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
834
+ r = Reflect.decorate(decorators, target, key, desc);
835
+ } else {
836
+ for (var i = decorators.length - 1; i >= 0; i--) {
837
+ if (d = decorators[i]) {
838
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
839
+ }
840
+ }
841
+ }
798
842
  return c > 3 && r && Object.defineProperty(target, key, r), r;
799
843
  }
800
844
  __name(_ts_decorate5, "_ts_decorate");
801
- function _ts_metadata5(k, v) {
802
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
845
+ function _ts_metadata5(metadataKey, metadataValue) {
846
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
847
+ return Reflect.metadata(metadataKey, metadataValue);
848
+ }
803
849
  }
804
850
  __name(_ts_metadata5, "_ts_metadata");
805
851
  function _ts_param3(paramIndex, decorator) {
@@ -952,13 +998,22 @@ __name(inAppWorkerProviders, "inAppWorkerProviders");
952
998
  import { Injectable as Injectable6 } from "@nestjs/common";
953
999
  function _ts_decorate6(decorators, target, key, desc) {
954
1000
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
955
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
956
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1001
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
1002
+ r = Reflect.decorate(decorators, target, key, desc);
1003
+ } else {
1004
+ for (var i = decorators.length - 1; i >= 0; i--) {
1005
+ if (d = decorators[i]) {
1006
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1007
+ }
1008
+ }
1009
+ }
957
1010
  return c > 3 && r && Object.defineProperty(target, key, r), r;
958
1011
  }
959
1012
  __name(_ts_decorate6, "_ts_decorate");
960
- function _ts_metadata6(k, v) {
961
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1013
+ function _ts_metadata6(metadataKey, metadataValue) {
1014
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
1015
+ return Reflect.metadata(metadataKey, metadataValue);
1016
+ }
962
1017
  }
963
1018
  __name(_ts_metadata6, "_ts_metadata");
964
1019
  var ProxyRunGateway = class {
@@ -1120,13 +1175,22 @@ import { DURABLE_OPTIONS_CANONICAL as DURABLE_OPTIONS_CANONICAL4, STATE_STORE_CA
1120
1175
  import { Inject as Inject4, Injectable as Injectable7 } from "@nestjs/common";
1121
1176
  function _ts_decorate7(decorators, target, key, desc) {
1122
1177
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1123
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1124
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1178
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
1179
+ r = Reflect.decorate(decorators, target, key, desc);
1180
+ } else {
1181
+ for (var i = decorators.length - 1; i >= 0; i--) {
1182
+ if (d = decorators[i]) {
1183
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1184
+ }
1185
+ }
1186
+ }
1125
1187
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1126
1188
  }
1127
1189
  __name(_ts_decorate7, "_ts_decorate");
1128
- function _ts_metadata7(k, v) {
1129
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1190
+ function _ts_metadata7(metadataKey, metadataValue) {
1191
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
1192
+ return Reflect.metadata(metadataKey, metadataValue);
1193
+ }
1130
1194
  }
1131
1195
  __name(_ts_metadata7, "_ts_metadata");
1132
1196
  function _ts_param4(paramIndex, decorator) {
@@ -1141,6 +1205,7 @@ var MAX_BATCHES_PER_POLICY = 100;
1141
1205
  function validateRetention(retention) {
1142
1206
  const seen = /* @__PURE__ */ new Set();
1143
1207
  for (const policy of retention.policies) {
1208
+ const scopeKey = policy.scope ? stableKey(policy.scope) : "";
1144
1209
  if (policy.statuses.length === 0) {
1145
1210
  throw new Error("durable retention: each policy must list at least one status");
1146
1211
  }
@@ -1152,14 +1217,24 @@ function validateRetention(retention) {
1152
1217
  if (!TERMINAL_RUN_STATUSES.includes(status)) {
1153
1218
  throw new Error(`durable retention: status "${status}" is not terminal; only ${TERMINAL_RUN_STATUSES.join(", ")} can be pruned`);
1154
1219
  }
1155
- if (seen.has(status)) {
1156
- throw new Error(`durable retention: status "${status}" appears in more than one policy; status sets must be disjoint`);
1220
+ const key = `${scopeKey}|${status}`;
1221
+ if (seen.has(key)) {
1222
+ throw new Error(`durable retention: status "${status}" appears in more than one policy with the same scope; status sets must be disjoint per scope`);
1157
1223
  }
1158
- seen.add(status);
1224
+ seen.add(key);
1159
1225
  }
1160
1226
  }
1161
1227
  }
1162
1228
  __name(validateRetention, "validateRetention");
1229
+ function stableKey(value) {
1230
+ if (Array.isArray(value)) return `[${value.map(stableKey).join(",")}]`;
1231
+ if (value && typeof value === "object") {
1232
+ const entries = Object.entries(value).filter(([, v]) => v !== void 0).sort(([a], [b]) => a.localeCompare(b));
1233
+ return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${stableKey(v)}`).join(",")}}`;
1234
+ }
1235
+ return JSON.stringify(value);
1236
+ }
1237
+ __name(stableKey, "stableKey");
1163
1238
  var RetentionPoller = class {
1164
1239
  static {
1165
1240
  __name(this, "RetentionPoller");
@@ -1397,13 +1472,22 @@ import { STATE_STORE_CANONICAL as STATE_STORE_CANONICAL2, WorkflowEngine as Work
1397
1472
  import { Inject as Inject5, Injectable as Injectable8 } from "@nestjs/common";
1398
1473
  function _ts_decorate8(decorators, target, key, desc) {
1399
1474
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1400
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1401
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1475
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
1476
+ r = Reflect.decorate(decorators, target, key, desc);
1477
+ } else {
1478
+ for (var i = decorators.length - 1; i >= 0; i--) {
1479
+ if (d = decorators[i]) {
1480
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1481
+ }
1482
+ }
1483
+ }
1402
1484
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1403
1485
  }
1404
1486
  __name(_ts_decorate8, "_ts_decorate");
1405
- function _ts_metadata8(k, v) {
1406
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1487
+ function _ts_metadata8(metadataKey, metadataValue) {
1488
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
1489
+ return Reflect.metadata(metadataKey, metadataValue);
1490
+ }
1407
1491
  }
1408
1492
  __name(_ts_metadata8, "_ts_metadata");
1409
1493
  function _ts_param5(paramIndex, decorator) {
@@ -1589,13 +1673,22 @@ import { DURABLE_OPTIONS_CANONICAL as DURABLE_OPTIONS_CANONICAL5, WorkflowEngine
1589
1673
  import { Inject as Inject6, Injectable as Injectable9 } from "@nestjs/common";
1590
1674
  function _ts_decorate9(decorators, target, key, desc) {
1591
1675
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1592
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1593
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1676
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
1677
+ r = Reflect.decorate(decorators, target, key, desc);
1678
+ } else {
1679
+ for (var i = decorators.length - 1; i >= 0; i--) {
1680
+ if (d = decorators[i]) {
1681
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1682
+ }
1683
+ }
1684
+ }
1594
1685
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1595
1686
  }
1596
1687
  __name(_ts_decorate9, "_ts_decorate");
1597
- function _ts_metadata9(k, v) {
1598
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1688
+ function _ts_metadata9(metadataKey, metadataValue) {
1689
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
1690
+ return Reflect.metadata(metadataKey, metadataValue);
1691
+ }
1599
1692
  }
1600
1693
  __name(_ts_metadata9, "_ts_metadata");
1601
1694
  function _ts_param6(paramIndex, decorator) {
@@ -1662,6 +1755,9 @@ var TimerPoller = class {
1662
1755
  if (schedules && schedules.length > 0) {
1663
1756
  await this.sweep("schedules", () => runSchedules(this.engine, schedules, Date.now()));
1664
1757
  }
1758
+ if (this.options.persistedSchedules) {
1759
+ await this.sweep("persistedSchedules", () => this.engine.schedules.tick());
1760
+ }
1665
1761
  } finally {
1666
1762
  this.polling = false;
1667
1763
  }
@@ -1737,13 +1833,22 @@ __name(isStepInterceptor, "isStepInterceptor");
1737
1833
  // src/workflow.registrar.ts
1738
1834
  function _ts_decorate10(decorators, target, key, desc) {
1739
1835
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1740
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1741
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1836
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
1837
+ r = Reflect.decorate(decorators, target, key, desc);
1838
+ } else {
1839
+ for (var i = decorators.length - 1; i >= 0; i--) {
1840
+ if (d = decorators[i]) {
1841
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1842
+ }
1843
+ }
1844
+ }
1742
1845
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1743
1846
  }
1744
1847
  __name(_ts_decorate10, "_ts_decorate");
1745
- function _ts_metadata10(k, v) {
1746
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1848
+ function _ts_metadata10(metadataKey, metadataValue) {
1849
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
1850
+ return Reflect.metadata(metadataKey, metadataValue);
1851
+ }
1747
1852
  }
1748
1853
  __name(_ts_metadata10, "_ts_metadata");
1749
1854
  function _ts_param7(paramIndex, decorator) {
@@ -1829,6 +1934,7 @@ var WorkflowRegistrar = class {
1829
1934
  origin,
1830
1935
  tags: meta.tags,
1831
1936
  singleton: meta.singleton,
1937
+ concurrency: meta.concurrency,
1832
1938
  executionTimeout: meta.executionTimeout,
1833
1939
  requires: meta.requires,
1834
1940
  validateInput,
@@ -1942,13 +2048,22 @@ import { WorkflowEngine as WorkflowEngine5 } from "@dudousxd/nestjs-durable-core
1942
2048
  import { Injectable as Injectable11 } from "@nestjs/common";
1943
2049
  function _ts_decorate11(decorators, target, key, desc) {
1944
2050
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1945
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1946
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2051
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
2052
+ r = Reflect.decorate(decorators, target, key, desc);
2053
+ } else {
2054
+ for (var i = decorators.length - 1; i >= 0; i--) {
2055
+ if (d = decorators[i]) {
2056
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2057
+ }
2058
+ }
2059
+ }
1947
2060
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1948
2061
  }
1949
2062
  __name(_ts_decorate11, "_ts_decorate");
1950
- function _ts_metadata11(k, v) {
1951
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2063
+ function _ts_metadata11(metadataKey, metadataValue) {
2064
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
2065
+ return Reflect.metadata(metadataKey, metadataValue);
2066
+ }
1952
2067
  }
1953
2068
  __name(_ts_metadata11, "_ts_metadata");
1954
2069
  var WorkflowService = class {
@@ -2005,13 +2120,22 @@ WorkflowService = _ts_decorate11([
2005
2120
  // src/durable.module.ts
2006
2121
  function _ts_decorate12(decorators, target, key, desc) {
2007
2122
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2008
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2009
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2123
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
2124
+ r = Reflect.decorate(decorators, target, key, desc);
2125
+ } else {
2126
+ for (var i = decorators.length - 1; i >= 0; i--) {
2127
+ if (d = decorators[i]) {
2128
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2129
+ }
2130
+ }
2131
+ }
2010
2132
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2011
2133
  }
2012
2134
  __name(_ts_decorate12, "_ts_decorate");
2013
- function _ts_metadata12(k, v) {
2014
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2135
+ function _ts_metadata12(metadataKey, metadataValue) {
2136
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
2137
+ return Reflect.metadata(metadataKey, metadataValue);
2138
+ }
2015
2139
  }
2016
2140
  __name(_ts_metadata12, "_ts_metadata");
2017
2141
  function _ts_param8(paramIndex, decorator) {
@@ -2306,6 +2430,8 @@ var DurableModule = class _DurableModule {
2306
2430
  admission: options.admission,
2307
2431
  maxRecoveryAttempts: options.maxRecoveryAttempts,
2308
2432
  remoteAdvanceSilenceMs: options.remoteAdvanceSilenceMs,
2433
+ remoteRedispatchMs: options.remoteRedispatchMs,
2434
+ remoteRedispatchMax: options.remoteRedispatchMax,
2309
2435
  instanceId: options.instanceId,
2310
2436
  namespace: options.namespace,
2311
2437
  webhookUrl: options.webhookUrl,