@dudousxd/nestjs-durable 0.18.1 → 0.20.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,5 +1,7 @@
1
1
  import { StepError, WorkflowRef, SingletonConfig, StateStore, Transport, NamedTransport, ControlPlane, ScheduledWorkflow, QueueConfig, AdmissionBackend, WorkflowEngine, EntityHandler, StepInvocation, WorkflowClass, WorkflowInputOf, StartOptions, RunResult } from '@dudousxd/nestjs-durable-core';
2
- import { DynamicModule, InjectionToken } from '@nestjs/common';
2
+ import { RunRedisWorkerOptions, RunningWorker, DurableWorkerRuntime } from '@dudousxd/durable-worker';
3
+ import { DynamicModule, InjectionToken, OnModuleInit, OnApplicationBootstrap, OnApplicationShutdown } from '@nestjs/common';
4
+ import { DiscoveryService, MetadataScanner } from '@nestjs/core';
3
5
 
4
6
  /**
5
7
  * Local, structural mirror of `@dudousxd/nestjs-context`'s public accessor
@@ -176,6 +178,96 @@ declare function OnEvent(...events: string[]): ClassDecorator;
176
178
  /** All events a workflow class subscribes to — the union of `@Workflow({ onEvent })` and `@OnEvent`. */
177
179
  declare function getOnEvents(meta: WorkflowMeta, target: object): string[];
178
180
 
181
+ /**
182
+ * Options for a **store-less thin worker** process: where to consume (`connection`/`prefix`) and
183
+ * which worker `groups` this process serves. There is deliberately NO `store`, `transport`, engine,
184
+ * dashboard, recovery, or timer config — a thin worker only registers `@Workflow`/`@DurableStep`
185
+ * handlers and runs the BullMQ consumer (see {@link DurableWorkerModule}).
186
+ */
187
+ interface DurableWorkerModuleOptions {
188
+ /** ioredis connection (string or options), as `runRedisWorker` / `BullMQTransport` accept. */
189
+ connection: string | Record<string, unknown>;
190
+ /** The worker groups this process serves — one BullMQ consumer is started per group. */
191
+ groups: string[];
192
+ /** Key prefix namespacing the durable queues. Defaults to `durable` (matches the transport). */
193
+ prefix?: string;
194
+ /** Stable id for this worker process in heartbeats/control. Defaults to a per-host/pid id. */
195
+ instanceId?: string;
196
+ }
197
+ interface DurableWorkerModuleAsyncOptions {
198
+ useFactory: (...args: never[]) => DurableWorkerModuleOptions | Promise<DurableWorkerModuleOptions>;
199
+ inject?: InjectionToken[];
200
+ }
201
+ /** The resolved {@link DurableWorkerModuleOptions} (canonical token). */
202
+ declare const DURABLE_WORKER_OPTIONS: unique symbol;
203
+ /**
204
+ * The `runRedisWorker` function the module uses to start each group's BullMQ consumer. Defaults to
205
+ * the real one from `@dudousxd/durable-worker`; tests `overrideProvider` it with a fake so no real
206
+ * Redis is needed.
207
+ */
208
+ declare const RUN_REDIS_WORKER: unique symbol;
209
+ /** The list of started {@link RunningWorker} handles (one per group), closed on shutdown. */
210
+ declare const DURABLE_WORKER_RUNNERS: unique symbol;
211
+ /** The signature of `runRedisWorker` — injected behind {@link RUN_REDIS_WORKER}. */
212
+ type RunRedisWorkerFn = (opts: RunRedisWorkerOptions) => Promise<RunningWorker>;
213
+ /**
214
+ * Discovers every provider carrying `@Workflow` metadata and registers its `run(ctx, input)` on the
215
+ * thin {@link DurableWorkerRuntime}. Mirrors the engine-side `WorkflowRegistrar`, but registers on
216
+ * the runner-core runtime instead of a `WorkflowEngine` — the runtime drives `run` with the thin
217
+ * `WorkflowContext` (which `implements WorkflowCtx`), so the body runs unchanged. NO store/engine.
218
+ */
219
+ declare class ThinWorkflowRegistrar implements OnModuleInit {
220
+ private readonly discovery;
221
+ private readonly runtime;
222
+ constructor(discovery: DiscoveryService, runtime: DurableWorkerRuntime);
223
+ onModuleInit(): void;
224
+ }
225
+ /**
226
+ * Discovers every `@DurableStep` method and registers it as a step handler on the thin
227
+ * {@link DurableWorkerRuntime}. Mirrors the engine-side `DurableStepRegistrar`, but always registers
228
+ * on the runtime (a thin worker IS the consumer — there is no in-process-vs-queue branch).
229
+ */
230
+ declare class ThinStepRegistrar implements OnModuleInit {
231
+ private readonly discovery;
232
+ private readonly metadataScanner;
233
+ private readonly runtime;
234
+ constructor(discovery: DiscoveryService, metadataScanner: MetadataScanner, runtime: DurableWorkerRuntime);
235
+ onModuleInit(): void;
236
+ }
237
+ /**
238
+ * Starts one BullMQ consumer per configured group on bootstrap (after both registrars have run, so
239
+ * every handler is registered before any task is consumed) and closes them on shutdown. The only
240
+ * runtime side effect of a thin worker: register handlers, run the consumer. No engine, no store,
241
+ * no recovery, no timers, no dispatch.
242
+ *
243
+ * For the shutdown close to fire, enable Nest's shutdown hooks: `app.enableShutdownHooks()`.
244
+ */
245
+ declare class ThinWorkerBootstrap implements OnApplicationBootstrap, OnApplicationShutdown {
246
+ private readonly runtime;
247
+ private readonly options;
248
+ private readonly runRedisWorker;
249
+ private readonly runnersSink;
250
+ private readonly runners;
251
+ constructor(runtime: DurableWorkerRuntime, options: DurableWorkerModuleOptions, runRedisWorker: RunRedisWorkerFn, runnersSink: RunningWorker[]);
252
+ onApplicationBootstrap(): Promise<void>;
253
+ onApplicationShutdown(): Promise<void>;
254
+ }
255
+ /**
256
+ * A NestJS dynamic module that turns an app into a **PURE durable worker**: it discovers
257
+ * `@Workflow`/`@DurableStep` providers, registers them on the thin {@link DurableWorkerRuntime}, and
258
+ * runs one BullMQ consumer per group via `runRedisWorker`. It is **control-plane-less** — it binds
259
+ * NO `WorkflowEngine`, NO store/ORM, NO dashboard, NO timer poller, NO recovery, and NO run dispatch.
260
+ * Use it for a worker pod that only executes work an engine elsewhere coordinates.
261
+ *
262
+ * Contrast with `DurableModule` (`worker: true`), which is a full control plane WITH a store: this
263
+ * module is the store-less half. A workflow body runs identically on either (conformance-tested).
264
+ */
265
+ declare class DurableWorkerModule {
266
+ static forRoot(options: DurableWorkerModuleOptions): DynamicModule;
267
+ static forRootAsync(options: DurableWorkerModuleAsyncOptions): DynamicModule;
268
+ private static build;
269
+ }
270
+
179
271
  interface DurableModuleOptions {
180
272
  store: StateStore;
181
273
  transport?: Transport;
@@ -209,6 +301,14 @@ interface DurableModuleOptions {
209
301
  * (a poison pill that crashes the process every boot). Omit for unlimited.
210
302
  */
211
303
  maxRecoveryAttempts?: number;
304
+ /**
305
+ * Opt-in liveness deadline (ms) for a remote (polyglot) workflow `advance`. If the worker neither
306
+ * returns a decision nor sends a run-scoped heartbeat within this window, the engine presumes it dead
307
+ * and lets recovery re-drive; each heartbeat rearms the window so a slow-but-alive worker is never
308
+ * re-driven. Pair with a worker SDK that emits run-scoped heartbeats (`@dudousxd/durable-worker` ≥ the
309
+ * release that ships them, and the Python `durable-worker`). Omit for the prior unbounded await.
310
+ */
311
+ remoteAdvanceSilenceMs?: number;
212
312
  /**
213
313
  * The **default** workflow to route dead-lettered runs to, for workflows that don't declare their
214
314
  * own. When a run is moved to `dead` (exceeded `maxRecoveryAttempts`), the started handler gets a
@@ -414,4 +514,4 @@ declare class WorkflowService {
414
514
  }): Promise<number>;
415
515
  }
416
516
 
417
- export { CONTEXT_ACCESSOR, type ContextAccessor, type ContextStore, DEAD_LETTER_METADATA, DURABLE_STEP_METADATA, DeadLetter, DurableModule, type DurableModuleAsyncOptions, type DurableModuleOptions, DurableStep, type DurableStepInterceptor, type DurableStepMeta, ENTITY_METADATA, ENTITY_ON_METADATA, Entity, EntityService, ON_EVENT_METADATA, On, OnEvent, STEP_INTERCEPTOR_METADATA, StepInterceptor, type UserRef, WORKFLOW_METADATA, Workflow, type WorkflowMeta, type WorkflowOptions, WorkflowService, entityConfigFor, getDurableStepMeta, getEntityMeta, getOnEvents, getWorkflowMeta, isDeadLetterHandler, isStepInterceptor };
517
+ 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, 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 };