@dudousxd/nestjs-durable 0.22.1 → 0.23.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.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { StepError, WorkflowRef, SingletonConfig, StateStore, Transport, NamedTransport, ControlPlane, ScheduledWorkflow, RetentionPolicy, QueueConfig, AdmissionBackend, WorkflowEngine, EntityHandler, StepInvocation, WorkflowClass, WorkflowInputOf, StartOptions, RunResult } from '@dudousxd/nestjs-durable-core';
1
+ import { StepError, WorkflowRef, SingletonConfig, WorkflowExecutor, StateStore, Transport, NamedTransport, ControlPlane, ScheduledWorkflow, RetentionPolicy, QueueConfig, AdmissionBackend, WorkflowEngine, EntityHandler, StepInvocation, WorkflowClass, WorkflowInputOf, StartOptions, RunResult } from '@dudousxd/nestjs-durable-core';
2
2
  import { RunRedisWorkerOptions, RunningWorker, DurableWorkerRuntime } from '@dudousxd/durable-worker';
3
- import { DynamicModule, InjectionToken, OnModuleInit, OnApplicationBootstrap, OnApplicationShutdown } from '@nestjs/common';
3
+ import { DynamicModule, InjectionToken, OnModuleInit, OnApplicationBootstrap, OnApplicationShutdown, Provider } from '@nestjs/common';
4
4
  import { DiscoveryService, MetadataScanner } from '@nestjs/core';
5
5
 
6
6
  /**
@@ -268,6 +268,73 @@ declare class DurableWorkerModule {
268
268
  private static build;
269
269
  }
270
270
 
271
+ /**
272
+ * Opt-in config for an **in-app worker**: the same NestJS process runs the engine AND serves its own
273
+ * discovered `@Workflow`/`@DurableStep` on one default `group`. The engine registers each `@Workflow`
274
+ * GROUP-SERVED (its turns are dispatched to `group` over the transport via a {@link RemoteWorkflowExecutor}
275
+ * instead of run inline), and a co-located {@link DurableWorkerRuntime} consumes `group` and replays the
276
+ * very same TS bodies. This is the uniform-dispatch "one app, both roles" shape — every turn pays a
277
+ * transport round-trip even though the worker is the same process. Requires a transport that carries
278
+ * workflow tasks (BullMQ); an in-process-only transport cannot dispatch a {@link WorkflowExecutor}.
279
+ */
280
+ interface DurableInAppWorkerOptions {
281
+ /** The default group this app dispatches its `@Workflow` turns to AND consumes as a worker. */
282
+ group: string;
283
+ /** ioredis connection (string or options) for the co-located worker consumer (`runRedisWorker`). */
284
+ connection: string | Record<string, unknown>;
285
+ /** Key prefix namespacing the durable queues. Defaults to `durable` (matches the transport). */
286
+ prefix?: string;
287
+ /** Stable id for this worker process in heartbeats/control. Defaults to a per-host/pid id. */
288
+ instanceId?: string;
289
+ }
290
+ /** The resolved {@link DurableInAppWorkerOptions} or `null` when the app didn't opt in. */
291
+ declare const IN_APP_WORKER_OPTIONS: unique symbol;
292
+ /**
293
+ * The group-served binding the {@link import('./workflow.registrar').WorkflowRegistrar} applies to every
294
+ * discovered `@Workflow`: `{ group, executor }` when the app opted into an in-app worker, else `null`
295
+ * (workflows register inline — the unchanged default). The executor is a {@link RemoteWorkflowExecutor}
296
+ * over the engine's own transport, so a group-served turn is dispatched to `group` and the co-located
297
+ * worker (below) advances it.
298
+ */
299
+ declare const IN_APP_WORKER_BINDING: unique symbol;
300
+ /** The co-located worker's {@link DurableWorkerRuntime} (the consumer half). */
301
+ declare const IN_APP_WORKER_RUNTIME: unique symbol;
302
+ /** `runRedisWorker`, injected so tests can substitute a fake (no real Redis). Defaults to the real one. */
303
+ declare const IN_APP_RUN_REDIS_WORKER: unique symbol;
304
+ /** Started {@link RunningWorker} handles for the in-app group(s), closed on shutdown. */
305
+ declare const IN_APP_WORKER_RUNNERS: unique symbol;
306
+ /** The group-served binding shape resolved behind {@link IN_APP_WORKER_BINDING}. */
307
+ interface InAppWorkerBinding {
308
+ group: string;
309
+ executor: WorkflowExecutor;
310
+ }
311
+ /**
312
+ * The consumer half of the in-app worker: on init it registers every discovered `@Workflow`/`@DurableStep`
313
+ * on a {@link DurableWorkerRuntime} (the SAME bodies the engine registered group-served), and on bootstrap
314
+ * it starts one `runRedisWorker` consumer on the configured group, closing it on shutdown. A no-op when
315
+ * the app didn't opt in. Mirrors the thin {@link import('./durable-worker.module').DurableWorkerModule},
316
+ * but co-located with a full engine.
317
+ */
318
+ declare class InAppWorkerBootstrap implements OnModuleInit, OnApplicationBootstrap, OnApplicationShutdown {
319
+ private readonly discovery;
320
+ private readonly metadataScanner;
321
+ private readonly options;
322
+ private readonly runtime;
323
+ private readonly runRedisWorker;
324
+ private readonly runnersSink;
325
+ private readonly runners;
326
+ constructor(discovery: DiscoveryService, metadataScanner: MetadataScanner, options: DurableInAppWorkerOptions | null, runtime: DurableWorkerRuntime, runRedisWorker: RunRedisWorkerFn, runnersSink: RunningWorker[]);
327
+ onModuleInit(): void;
328
+ onApplicationBootstrap(): Promise<void>;
329
+ onApplicationShutdown(): Promise<void>;
330
+ }
331
+ /**
332
+ * The providers that stand up an in-app worker, added to {@link import('./durable.module').DurableModule}.
333
+ * All are inert when `inAppWorker` is unset (the binding resolves to `null`, the bootstrap no-ops), so a
334
+ * plain `DurableModule` is byte-for-byte unchanged.
335
+ */
336
+ declare function inAppWorkerProviders(): Provider[];
337
+
271
338
  /**
272
339
  * Retention config for the {@link RetentionPoller}. One or more {@link RetentionPolicy policies}
273
340
  * (status sets must be disjoint — validated at boot), swept together on a shared interval.
@@ -411,6 +478,15 @@ interface DurableModuleOptions {
411
478
  context?: () => Record<string, unknown> | undefined;
412
479
  /** Attempts for each saga compensation when a run fails. Default 1 (no retry). Idempotent undos. */
413
480
  compensationRetries?: number;
481
+ /**
482
+ * Opt into an **in-app worker** (uniform dispatch): the same process runs the engine AND serves its
483
+ * own discovered `@Workflow`/`@DurableStep` on one default `group`. Each `@Workflow` is registered
484
+ * GROUP-SERVED — its turns are dispatched to `group` over the transport and replayed by a co-located
485
+ * worker consumer — instead of run inline. Requires a workflow-task transport (BullMQ). Omit (the
486
+ * default) to keep every `@Workflow` on the inline fast path with zero dispatch round-trips. See
487
+ * {@link DurableInAppWorkerOptions}.
488
+ */
489
+ inAppWorker?: DurableInAppWorkerOptions;
414
490
  }
415
491
  interface DurableModuleAsyncOptions {
416
492
  useFactory: (...args: never[]) => DurableModuleOptions | Promise<DurableModuleOptions>;
@@ -548,4 +624,4 @@ declare class WorkflowService {
548
624
  }): Promise<number>;
549
625
  }
550
626
 
551
- export { CONTEXT_ACCESSOR, type ContextAccessor, type ContextStore, DEAD_LETTER_METADATA, DURABLE_STEP_METADATA, DURABLE_WORKER_OPTIONS, DURABLE_WORKER_RUNNERS, DeadLetter, DurableModule, type DurableModuleAsyncOptions, type DurableModuleOptions, type DurableRetentionOptions, DurableStep, type DurableStepInterceptor, type DurableStepMeta, DurableWorkerModule, type DurableWorkerModuleAsyncOptions, type DurableWorkerModuleOptions, ENTITY_METADATA, ENTITY_ON_METADATA, Entity, EntityService, ON_EVENT_METADATA, On, OnEvent, RUN_REDIS_WORKER, type RunRedisWorkerFn, STEP_INTERCEPTOR_METADATA, StepInterceptor, ThinStepRegistrar, ThinWorkerBootstrap, ThinWorkflowRegistrar, type UserRef, WORKFLOW_METADATA, Workflow, type WorkflowMeta, type WorkflowOptions, WorkflowService, entityConfigFor, getDurableStepMeta, getEntityMeta, getOnEvents, getWorkflowMeta, isDeadLetterHandler, isStepInterceptor };
627
+ export { CONTEXT_ACCESSOR, type ContextAccessor, type ContextStore, DEAD_LETTER_METADATA, DURABLE_STEP_METADATA, DURABLE_WORKER_OPTIONS, DURABLE_WORKER_RUNNERS, DeadLetter, type DurableInAppWorkerOptions, DurableModule, type DurableModuleAsyncOptions, type DurableModuleOptions, type DurableRetentionOptions, DurableStep, type DurableStepInterceptor, type DurableStepMeta, DurableWorkerModule, type DurableWorkerModuleAsyncOptions, type DurableWorkerModuleOptions, ENTITY_METADATA, ENTITY_ON_METADATA, Entity, EntityService, IN_APP_RUN_REDIS_WORKER, IN_APP_WORKER_BINDING, IN_APP_WORKER_OPTIONS, IN_APP_WORKER_RUNNERS, IN_APP_WORKER_RUNTIME, type InAppWorkerBinding, InAppWorkerBootstrap, ON_EVENT_METADATA, On, OnEvent, RUN_REDIS_WORKER, type RunRedisWorkerFn, STEP_INTERCEPTOR_METADATA, StepInterceptor, ThinStepRegistrar, ThinWorkerBootstrap, ThinWorkflowRegistrar, type UserRef, WORKFLOW_METADATA, Workflow, type WorkflowMeta, type WorkflowOptions, WorkflowService, entityConfigFor, getDurableStepMeta, getEntityMeta, getOnEvents, getWorkflowMeta, inAppWorkerProviders, isDeadLetterHandler, isStepInterceptor };
package/dist/index.js CHANGED
@@ -293,7 +293,7 @@ DurableWorkerModule = _ts_decorate([
293
293
  ], DurableWorkerModule);
294
294
 
295
295
  // src/durable.module.ts
296
- import { DURABLE_OPTIONS, DURABLE_OPTIONS_CANONICAL as DURABLE_OPTIONS_CANONICAL5, STATE_STORE, STATE_STORE_CANONICAL as STATE_STORE_CANONICAL3, TRANSPORT, TRANSPORT_CANONICAL as TRANSPORT_CANONICAL2, WorkflowEngine as WorkflowEngine5 } from "@dudousxd/nestjs-durable-core";
296
+ import { DURABLE_OPTIONS, DURABLE_OPTIONS_CANONICAL as DURABLE_OPTIONS_CANONICAL6, STATE_STORE, STATE_STORE_CANONICAL as STATE_STORE_CANONICAL3, TRANSPORT, TRANSPORT_CANONICAL as TRANSPORT_CANONICAL3, WorkflowEngine as WorkflowEngine5 } from "@dudousxd/nestjs-durable-core";
297
297
  import { Module as Module2 } from "@nestjs/common";
298
298
  import { DiscoveryModule as DiscoveryModule2, ModuleRef } from "@nestjs/core";
299
299
 
@@ -435,9 +435,11 @@ EntityService = _ts_decorate3([
435
435
  ])
436
436
  ], EntityService);
437
437
 
438
- // src/retention-poller.ts
439
- import { DURABLE_OPTIONS_CANONICAL as DURABLE_OPTIONS_CANONICAL2, STATE_STORE_CANONICAL, TERMINAL_RUN_STATUSES, parseDuration } from "@dudousxd/nestjs-durable-core";
438
+ // src/in-app-worker.ts
439
+ import { DurableWorkerRuntime as DurableWorkerRuntime2, runRedisWorker as defaultRunRedisWorker2 } from "@dudousxd/durable-worker";
440
+ import { DURABLE_OPTIONS_CANONICAL as DURABLE_OPTIONS_CANONICAL2, RemoteWorkflowExecutor, TRANSPORT_CANONICAL as TRANSPORT_CANONICAL2 } from "@dudousxd/nestjs-durable-core";
440
441
  import { Inject as Inject3, Injectable as Injectable4 } from "@nestjs/common";
442
+ import { DiscoveryService as DiscoveryService3, MetadataScanner as MetadataScanner3 } from "@nestjs/core";
441
443
  function _ts_decorate4(decorators, target, key, desc) {
442
444
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
443
445
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -455,6 +457,136 @@ function _ts_param3(paramIndex, decorator) {
455
457
  };
456
458
  }
457
459
  __name(_ts_param3, "_ts_param");
460
+ var IN_APP_WORKER_OPTIONS = Symbol("nestjs-durable:in-app-worker-options");
461
+ var IN_APP_WORKER_BINDING = Symbol("nestjs-durable:in-app-worker-binding");
462
+ var IN_APP_WORKER_RUNTIME = Symbol("nestjs-durable:in-app-worker-runtime");
463
+ var IN_APP_RUN_REDIS_WORKER = Symbol("nestjs-durable:in-app-run-redis-worker");
464
+ var IN_APP_WORKER_RUNNERS = Symbol("nestjs-durable:in-app-worker-runners");
465
+ function inAppWorkerBinding(transport, options) {
466
+ if (!options) return null;
467
+ if (!transport?.dispatchWorkflowTask || !transport.onDecision) {
468
+ throw new Error("inAppWorker requires a transport that carries workflow tasks (dispatchWorkflowTask + onDecision), e.g. BullMQTransport. An in-process transport cannot serve a group-served workflow.");
469
+ }
470
+ return {
471
+ group: options.group,
472
+ executor: new RemoteWorkflowExecutor(transport, options.group)
473
+ };
474
+ }
475
+ __name(inAppWorkerBinding, "inAppWorkerBinding");
476
+ var InAppWorkerBootstrap = class {
477
+ static {
478
+ __name(this, "InAppWorkerBootstrap");
479
+ }
480
+ discovery;
481
+ metadataScanner;
482
+ options;
483
+ runtime;
484
+ runRedisWorker;
485
+ runnersSink;
486
+ runners = [];
487
+ constructor(discovery, metadataScanner, options, runtime, runRedisWorker, runnersSink) {
488
+ this.discovery = discovery;
489
+ this.metadataScanner = metadataScanner;
490
+ this.options = options;
491
+ this.runtime = runtime;
492
+ this.runRedisWorker = runRedisWorker;
493
+ this.runnersSink = runnersSink;
494
+ }
495
+ onModuleInit() {
496
+ if (!this.options) return;
497
+ scanWorkflows(this.discovery, (meta, instance) => this.runtime.registerWorkflow(meta.name, (ctx, input) => instance.run(ctx, input)));
498
+ scanSteps(this.discovery, this.metadataScanner, (meta, handler) => this.runtime.registerStep(meta.name, handler));
499
+ }
500
+ async onApplicationBootstrap() {
501
+ if (!this.options) return;
502
+ const handle = await this.runRedisWorker({
503
+ runtime: this.runtime,
504
+ group: this.options.group,
505
+ connection: this.options.connection,
506
+ ...this.options.prefix !== void 0 ? {
507
+ prefix: this.options.prefix
508
+ } : {},
509
+ ...this.options.instanceId !== void 0 ? {
510
+ instanceId: this.options.instanceId
511
+ } : {}
512
+ });
513
+ this.runners.push(handle);
514
+ this.runnersSink.push(handle);
515
+ }
516
+ async onApplicationShutdown() {
517
+ await Promise.allSettled(this.runners.map((handle) => handle.close()));
518
+ }
519
+ };
520
+ InAppWorkerBootstrap = _ts_decorate4([
521
+ Injectable4(),
522
+ _ts_param3(2, Inject3(IN_APP_WORKER_OPTIONS)),
523
+ _ts_param3(3, Inject3(IN_APP_WORKER_RUNTIME)),
524
+ _ts_param3(4, Inject3(IN_APP_RUN_REDIS_WORKER)),
525
+ _ts_param3(5, Inject3(IN_APP_WORKER_RUNNERS)),
526
+ _ts_metadata4("design:type", Function),
527
+ _ts_metadata4("design:paramtypes", [
528
+ typeof DiscoveryService3 === "undefined" ? Object : DiscoveryService3,
529
+ typeof MetadataScanner3 === "undefined" ? Object : MetadataScanner3,
530
+ Object,
531
+ typeof DurableWorkerRuntime2 === "undefined" ? Object : DurableWorkerRuntime2,
532
+ typeof RunRedisWorkerFn === "undefined" ? Object : RunRedisWorkerFn,
533
+ Array
534
+ ])
535
+ ], InAppWorkerBootstrap);
536
+ function inAppWorkerProviders() {
537
+ return [
538
+ {
539
+ provide: IN_APP_WORKER_BINDING,
540
+ useFactory: /* @__PURE__ */ __name((transport, options) => inAppWorkerBinding(transport, options.inAppWorker ?? null), "useFactory"),
541
+ inject: [
542
+ TRANSPORT_CANONICAL2,
543
+ DURABLE_OPTIONS_CANONICAL2
544
+ ]
545
+ },
546
+ {
547
+ provide: IN_APP_WORKER_OPTIONS,
548
+ useFactory: /* @__PURE__ */ __name((options) => options.inAppWorker ?? null, "useFactory"),
549
+ inject: [
550
+ DURABLE_OPTIONS_CANONICAL2
551
+ ]
552
+ },
553
+ {
554
+ provide: IN_APP_WORKER_RUNTIME,
555
+ useFactory: /* @__PURE__ */ __name(() => new DurableWorkerRuntime2(), "useFactory")
556
+ },
557
+ {
558
+ provide: IN_APP_RUN_REDIS_WORKER,
559
+ useValue: defaultRunRedisWorker2
560
+ },
561
+ {
562
+ provide: IN_APP_WORKER_RUNNERS,
563
+ useValue: []
564
+ },
565
+ InAppWorkerBootstrap
566
+ ];
567
+ }
568
+ __name(inAppWorkerProviders, "inAppWorkerProviders");
569
+
570
+ // src/retention-poller.ts
571
+ import { DURABLE_OPTIONS_CANONICAL as DURABLE_OPTIONS_CANONICAL3, STATE_STORE_CANONICAL, TERMINAL_RUN_STATUSES, parseDuration } from "@dudousxd/nestjs-durable-core";
572
+ import { Inject as Inject4, Injectable as Injectable5 } from "@nestjs/common";
573
+ function _ts_decorate5(decorators, target, key, desc) {
574
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
575
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
576
+ 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;
577
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
578
+ }
579
+ __name(_ts_decorate5, "_ts_decorate");
580
+ function _ts_metadata5(k, v) {
581
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
582
+ }
583
+ __name(_ts_metadata5, "_ts_metadata");
584
+ function _ts_param4(paramIndex, decorator) {
585
+ return function(target, key) {
586
+ decorator(target, key, paramIndex);
587
+ };
588
+ }
589
+ __name(_ts_param4, "_ts_param");
458
590
  var DEFAULT_SWEEP_INTERVAL_MS = 6e4;
459
591
  var DEFAULT_BATCH_SIZE = 1e3;
460
592
  var MAX_BATCHES_PER_POLICY = 100;
@@ -531,37 +663,37 @@ var RetentionPoller = class {
531
663
  }
532
664
  }
533
665
  };
534
- RetentionPoller = _ts_decorate4([
535
- Injectable4(),
536
- _ts_param3(0, Inject3(STATE_STORE_CANONICAL)),
537
- _ts_param3(1, Inject3(DURABLE_OPTIONS_CANONICAL2)),
538
- _ts_metadata4("design:type", Function),
539
- _ts_metadata4("design:paramtypes", [
666
+ RetentionPoller = _ts_decorate5([
667
+ Injectable5(),
668
+ _ts_param4(0, Inject4(STATE_STORE_CANONICAL)),
669
+ _ts_param4(1, Inject4(DURABLE_OPTIONS_CANONICAL3)),
670
+ _ts_metadata5("design:type", Function),
671
+ _ts_metadata5("design:paramtypes", [
540
672
  typeof StateStore === "undefined" ? Object : StateStore,
541
673
  typeof DurableModuleOptions === "undefined" ? Object : DurableModuleOptions
542
674
  ])
543
675
  ], RetentionPoller);
544
676
 
545
677
  // src/timer-poller.ts
546
- import { DURABLE_OPTIONS_CANONICAL as DURABLE_OPTIONS_CANONICAL3, WorkflowEngine as WorkflowEngine2, runSchedules } from "@dudousxd/nestjs-durable-core";
547
- import { Inject as Inject4, Injectable as Injectable5 } from "@nestjs/common";
548
- function _ts_decorate5(decorators, target, key, desc) {
678
+ import { DURABLE_OPTIONS_CANONICAL as DURABLE_OPTIONS_CANONICAL4, WorkflowEngine as WorkflowEngine2, runSchedules } from "@dudousxd/nestjs-durable-core";
679
+ import { Inject as Inject5, Injectable as Injectable6 } from "@nestjs/common";
680
+ function _ts_decorate6(decorators, target, key, desc) {
549
681
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
550
682
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
551
683
  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;
552
684
  return c > 3 && r && Object.defineProperty(target, key, r), r;
553
685
  }
554
- __name(_ts_decorate5, "_ts_decorate");
555
- function _ts_metadata5(k, v) {
686
+ __name(_ts_decorate6, "_ts_decorate");
687
+ function _ts_metadata6(k, v) {
556
688
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
557
689
  }
558
- __name(_ts_metadata5, "_ts_metadata");
559
- function _ts_param4(paramIndex, decorator) {
690
+ __name(_ts_metadata6, "_ts_metadata");
691
+ function _ts_param5(paramIndex, decorator) {
560
692
  return function(target, key) {
561
693
  decorator(target, key, paramIndex);
562
694
  };
563
695
  }
564
- __name(_ts_param4, "_ts_param");
696
+ __name(_ts_param5, "_ts_param");
565
697
  var TimerPoller = class {
566
698
  static {
567
699
  __name(this, "TimerPoller");
@@ -606,11 +738,11 @@ var TimerPoller = class {
606
738
  }
607
739
  }
608
740
  };
609
- TimerPoller = _ts_decorate5([
610
- Injectable5(),
611
- _ts_param4(1, Inject4(DURABLE_OPTIONS_CANONICAL3)),
612
- _ts_metadata5("design:type", Function),
613
- _ts_metadata5("design:paramtypes", [
741
+ TimerPoller = _ts_decorate6([
742
+ Injectable6(),
743
+ _ts_param5(1, Inject5(DURABLE_OPTIONS_CANONICAL4)),
744
+ _ts_metadata6("design:type", Function),
745
+ _ts_metadata6("design:paramtypes", [
614
746
  typeof WorkflowEngine2 === "undefined" ? Object : WorkflowEngine2,
615
747
  typeof DurableModuleOptions === "undefined" ? Object : DurableModuleOptions
616
748
  ])
@@ -620,9 +752,9 @@ TimerPoller = _ts_decorate5([
620
752
  var CONTEXT_ACCESSOR = Symbol.for("@dudousxd/nestjs-context:accessor");
621
753
 
622
754
  // src/workflow.registrar.ts
623
- import { DURABLE_OPTIONS_CANONICAL as DURABLE_OPTIONS_CANONICAL4, STATE_STORE_CANONICAL as STATE_STORE_CANONICAL2, WorkflowEngine as WorkflowEngine3, parseDuration as parseDuration2, workflowName } from "@dudousxd/nestjs-durable-core";
624
- import { Inject as Inject5, Injectable as Injectable6 } from "@nestjs/common";
625
- import { DiscoveryService as DiscoveryService3, MetadataScanner as MetadataScanner3 } from "@nestjs/core";
755
+ import { DURABLE_OPTIONS_CANONICAL as DURABLE_OPTIONS_CANONICAL5, STATE_STORE_CANONICAL as STATE_STORE_CANONICAL2, WorkflowEngine as WorkflowEngine3, parseDuration as parseDuration2, workflowName } from "@dudousxd/nestjs-durable-core";
756
+ import { Inject as Inject6, Injectable as Injectable7 } from "@nestjs/common";
757
+ import { DiscoveryService as DiscoveryService4, MetadataScanner as MetadataScanner4 } from "@nestjs/core";
626
758
 
627
759
  // src/input-validation.ts
628
760
  function classValidatorInput(cls) {
@@ -664,23 +796,23 @@ function isStepInterceptor(target) {
664
796
  __name(isStepInterceptor, "isStepInterceptor");
665
797
 
666
798
  // src/workflow.registrar.ts
667
- function _ts_decorate6(decorators, target, key, desc) {
799
+ function _ts_decorate7(decorators, target, key, desc) {
668
800
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
669
801
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
670
802
  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;
671
803
  return c > 3 && r && Object.defineProperty(target, key, r), r;
672
804
  }
673
- __name(_ts_decorate6, "_ts_decorate");
674
- function _ts_metadata6(k, v) {
805
+ __name(_ts_decorate7, "_ts_decorate");
806
+ function _ts_metadata7(k, v) {
675
807
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
676
808
  }
677
- __name(_ts_metadata6, "_ts_metadata");
678
- function _ts_param5(paramIndex, decorator) {
809
+ __name(_ts_metadata7, "_ts_metadata");
810
+ function _ts_param6(paramIndex, decorator) {
679
811
  return function(target, key) {
680
812
  decorator(target, key, paramIndex);
681
813
  };
682
814
  }
683
- __name(_ts_param5, "_ts_param");
815
+ __name(_ts_param6, "_ts_param");
684
816
  var WorkflowRegistrar = class {
685
817
  static {
686
818
  __name(this, "WorkflowRegistrar");
@@ -690,12 +822,14 @@ var WorkflowRegistrar = class {
690
822
  engine;
691
823
  store;
692
824
  options;
693
- constructor(discovery, metadataScanner, engine, store, options) {
825
+ inAppWorker;
826
+ constructor(discovery, metadataScanner, engine, store, options, inAppWorker) {
694
827
  this.discovery = discovery;
695
828
  this.metadataScanner = metadataScanner;
696
829
  this.engine = engine;
697
830
  this.store = store;
698
831
  this.options = options;
832
+ this.inAppWorker = inAppWorker;
699
833
  }
700
834
  async onApplicationBootstrap() {
701
835
  if (this.options.worker === false) return;
@@ -746,7 +880,14 @@ var WorkflowRegistrar = class {
746
880
  executionTimeout: meta.executionTimeout,
747
881
  validateInput,
748
882
  onEvent: getOnEvents(meta, workflowCtor),
749
- eventBatch
883
+ eventBatch,
884
+ // Uniform dispatch (opt-in): when an in-app worker is configured, register the body GROUP-SERVED
885
+ // so the engine dispatches its turns to the app's own group instead of running it inline; the
886
+ // co-located worker consumer replays the same body. Absent → the inline fast path (unchanged).
887
+ ...this.inAppWorker ? {
888
+ group: this.inAppWorker.group,
889
+ executor: this.inAppWorker.executor
890
+ } : {}
750
891
  });
751
892
  const inline = this.findDeadLetterHandler(workflow);
752
893
  if (inline && meta.deadLetterWorkflow) {
@@ -793,35 +934,37 @@ var WorkflowRegistrar = class {
793
934
  });
794
935
  }
795
936
  };
796
- WorkflowRegistrar = _ts_decorate6([
797
- Injectable6(),
798
- _ts_param5(3, Inject5(STATE_STORE_CANONICAL2)),
799
- _ts_param5(4, Inject5(DURABLE_OPTIONS_CANONICAL4)),
800
- _ts_metadata6("design:type", Function),
801
- _ts_metadata6("design:paramtypes", [
802
- typeof DiscoveryService3 === "undefined" ? Object : DiscoveryService3,
803
- typeof MetadataScanner3 === "undefined" ? Object : MetadataScanner3,
937
+ WorkflowRegistrar = _ts_decorate7([
938
+ Injectable7(),
939
+ _ts_param6(3, Inject6(STATE_STORE_CANONICAL2)),
940
+ _ts_param6(4, Inject6(DURABLE_OPTIONS_CANONICAL5)),
941
+ _ts_param6(5, Inject6(IN_APP_WORKER_BINDING)),
942
+ _ts_metadata7("design:type", Function),
943
+ _ts_metadata7("design:paramtypes", [
944
+ typeof DiscoveryService4 === "undefined" ? Object : DiscoveryService4,
945
+ typeof MetadataScanner4 === "undefined" ? Object : MetadataScanner4,
804
946
  typeof WorkflowEngine3 === "undefined" ? Object : WorkflowEngine3,
805
947
  typeof StateStore === "undefined" ? Object : StateStore,
806
- typeof DurableModuleOptions === "undefined" ? Object : DurableModuleOptions
948
+ typeof DurableModuleOptions === "undefined" ? Object : DurableModuleOptions,
949
+ Object
807
950
  ])
808
951
  ], WorkflowRegistrar);
809
952
 
810
953
  // src/workflow.service.ts
811
954
  import { randomUUID } from "node:crypto";
812
955
  import { WorkflowEngine as WorkflowEngine4 } from "@dudousxd/nestjs-durable-core";
813
- import { Injectable as Injectable7 } from "@nestjs/common";
814
- function _ts_decorate7(decorators, target, key, desc) {
956
+ import { Injectable as Injectable8 } from "@nestjs/common";
957
+ function _ts_decorate8(decorators, target, key, desc) {
815
958
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
816
959
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
817
960
  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;
818
961
  return c > 3 && r && Object.defineProperty(target, key, r), r;
819
962
  }
820
- __name(_ts_decorate7, "_ts_decorate");
821
- function _ts_metadata7(k, v) {
963
+ __name(_ts_decorate8, "_ts_decorate");
964
+ function _ts_metadata8(k, v) {
822
965
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
823
966
  }
824
- __name(_ts_metadata7, "_ts_metadata");
967
+ __name(_ts_metadata8, "_ts_metadata");
825
968
  var WorkflowService = class {
826
969
  static {
827
970
  __name(this, "WorkflowService");
@@ -861,22 +1004,22 @@ var WorkflowService = class {
861
1004
  return this.engine.publishEvent(name, payload, opts);
862
1005
  }
863
1006
  };
864
- WorkflowService = _ts_decorate7([
865
- Injectable7(),
866
- _ts_metadata7("design:type", Function),
867
- _ts_metadata7("design:paramtypes", [
1007
+ WorkflowService = _ts_decorate8([
1008
+ Injectable8(),
1009
+ _ts_metadata8("design:type", Function),
1010
+ _ts_metadata8("design:paramtypes", [
868
1011
  typeof WorkflowEngine4 === "undefined" ? Object : WorkflowEngine4
869
1012
  ])
870
1013
  ], WorkflowService);
871
1014
 
872
1015
  // src/durable.module.ts
873
- function _ts_decorate8(decorators, target, key, desc) {
1016
+ function _ts_decorate9(decorators, target, key, desc) {
874
1017
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
875
1018
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
876
1019
  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;
877
1020
  return c > 3 && r && Object.defineProperty(target, key, r), r;
878
1021
  }
879
- __name(_ts_decorate8, "_ts_decorate");
1022
+ __name(_ts_decorate9, "_ts_decorate");
880
1023
  function resolveAccessor(moduleRef) {
881
1024
  try {
882
1025
  return moduleRef.get(CONTEXT_ACCESSOR, {
@@ -922,13 +1065,13 @@ var DurableModule = class _DurableModule {
922
1065
  }
923
1066
  static forRoot(options) {
924
1067
  return _DurableModule.build({
925
- provide: DURABLE_OPTIONS_CANONICAL5,
1068
+ provide: DURABLE_OPTIONS_CANONICAL6,
926
1069
  useValue: options
927
1070
  });
928
1071
  }
929
1072
  static forRootAsync(options) {
930
1073
  return _DurableModule.build({
931
- provide: DURABLE_OPTIONS_CANONICAL5,
1074
+ provide: DURABLE_OPTIONS_CANONICAL6,
932
1075
  useFactory: options.useFactory,
933
1076
  inject: options.inject ?? []
934
1077
  });
@@ -946,14 +1089,14 @@ var DurableModule = class _DurableModule {
946
1089
  provide: STATE_STORE_CANONICAL3,
947
1090
  useFactory: /* @__PURE__ */ __name((options) => options.store, "useFactory"),
948
1091
  inject: [
949
- DURABLE_OPTIONS_CANONICAL5
1092
+ DURABLE_OPTIONS_CANONICAL6
950
1093
  ]
951
1094
  },
952
1095
  {
953
- provide: TRANSPORT_CANONICAL2,
1096
+ provide: TRANSPORT_CANONICAL3,
954
1097
  useFactory: /* @__PURE__ */ __name((options) => options.transport ?? null, "useFactory"),
955
1098
  inject: [
956
- DURABLE_OPTIONS_CANONICAL5
1099
+ DURABLE_OPTIONS_CANONICAL6
957
1100
  ]
958
1101
  },
959
1102
  // Legacy back-compat aliases (deprecated tokens still resolve to the same instances):
@@ -963,11 +1106,11 @@ var DurableModule = class _DurableModule {
963
1106
  },
964
1107
  {
965
1108
  provide: TRANSPORT,
966
- useExisting: TRANSPORT_CANONICAL2
1109
+ useExisting: TRANSPORT_CANONICAL3
967
1110
  },
968
1111
  {
969
1112
  provide: DURABLE_OPTIONS,
970
- useExisting: DURABLE_OPTIONS_CANONICAL5
1113
+ useExisting: DURABLE_OPTIONS_CANONICAL6
971
1114
  },
972
1115
  {
973
1116
  provide: WorkflowEngine5,
@@ -1005,8 +1148,8 @@ var DurableModule = class _DurableModule {
1005
1148
  }, "useFactory"),
1006
1149
  inject: [
1007
1150
  STATE_STORE_CANONICAL3,
1008
- TRANSPORT_CANONICAL2,
1009
- DURABLE_OPTIONS_CANONICAL5,
1151
+ TRANSPORT_CANONICAL3,
1152
+ DURABLE_OPTIONS_CANONICAL6,
1010
1153
  ModuleRef
1011
1154
  ]
1012
1155
  },
@@ -1015,7 +1158,10 @@ var DurableModule = class _DurableModule {
1015
1158
  WorkflowRegistrar,
1016
1159
  DurableStepRegistrar,
1017
1160
  TimerPoller,
1018
- RetentionPoller
1161
+ RetentionPoller,
1162
+ // In-app worker (uniform dispatch, opt-in): inert when `inAppWorker` is unset — the binding
1163
+ // resolves to null and the bootstrap no-ops, so a plain DurableModule is unchanged.
1164
+ ...inAppWorkerProviders()
1019
1165
  ],
1020
1166
  exports: [
1021
1167
  WorkflowService,
@@ -1024,13 +1170,13 @@ var DurableModule = class _DurableModule {
1024
1170
  STATE_STORE,
1025
1171
  STATE_STORE_CANONICAL3,
1026
1172
  TRANSPORT,
1027
- TRANSPORT_CANONICAL2,
1028
- DURABLE_OPTIONS_CANONICAL5
1173
+ TRANSPORT_CANONICAL3,
1174
+ DURABLE_OPTIONS_CANONICAL6
1029
1175
  ]
1030
1176
  };
1031
1177
  }
1032
1178
  };
1033
- DurableModule = _ts_decorate8([
1179
+ DurableModule = _ts_decorate9([
1034
1180
  Module2({})
1035
1181
  ], DurableModule);
1036
1182
  export {
@@ -1047,6 +1193,12 @@ export {
1047
1193
  ENTITY_ON_METADATA,
1048
1194
  Entity,
1049
1195
  EntityService,
1196
+ IN_APP_RUN_REDIS_WORKER,
1197
+ IN_APP_WORKER_BINDING,
1198
+ IN_APP_WORKER_OPTIONS,
1199
+ IN_APP_WORKER_RUNNERS,
1200
+ IN_APP_WORKER_RUNTIME,
1201
+ InAppWorkerBootstrap,
1050
1202
  ON_EVENT_METADATA,
1051
1203
  On,
1052
1204
  OnEvent,
@@ -1064,6 +1216,7 @@ export {
1064
1216
  getEntityMeta,
1065
1217
  getOnEvents,
1066
1218
  getWorkflowMeta,
1219
+ inAppWorkerProviders,
1067
1220
  isDeadLetterHandler,
1068
1221
  isStepInterceptor
1069
1222
  };