@nest-batch/bullmq 0.2.0 → 0.2.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/README.md CHANGED
@@ -218,7 +218,7 @@ every sub-module.
218
218
  The adapter enqueues **one BullMQ job per step** (or, in a future
219
219
  enhancement, one job per partition for chunked steps). It does not
220
220
  enqueue one job per row, per chunk, or per item. The contract is
221
- enforced by the `BullmqRuntimeService.launch()` method, which
221
+ enforced by the `BullmqRuntime.launch()` method, which
222
222
  takes the step's `id` from the `JobDefinition` and uses it as the
223
223
  BullMQ `name` discriminator. The chunk loop runs _inside_ the
224
224
  single BullMQ job, in the worker.
@@ -297,11 +297,12 @@ cannot poison the BullMQ event stream.
297
297
  - A batch engine. Step / chunk / tasklet semantics, skip, restart,
298
298
  checkpoint, and business retry live in
299
299
  [`@nest-batch/core`](../core). BullMQ is the courier.
300
- - A scheduler. Cron-style scheduling lives in
301
- `@nest-batch/core`'s `@BatchScheduled` decorator, which stamps
302
- metadata read by the `BatchScheduleRegistry`. A future package
303
- (or a follow-up release of this one) will translate that metadata
304
- into BullMQ `QueueScheduler` jobs.
300
+ - A separate scheduler package. Cron-style scheduling starts with
301
+ `@nest-batch/core`'s `@BatchScheduled` decorator, and this BullMQ
302
+ adapter installs the non-inert entries with `upsertJobScheduler`.
303
+ When `autoStartWorker` is enabled, `BullmqSchedule` also
304
+ consumes the schedule queue and bridges each fire to
305
+ `JobLauncher.launch(jobId, params)`.
305
306
  - An admin UI, metrics backend, tracing backend, or webhook system.
306
307
  Hook a `BatchObserver` to ship events where you need them.
307
308
  - Alternative queue transports (Sidekiq, RabbitMQ, SQS, ...).
@@ -22,8 +22,8 @@ export declare class BullmqModule {
22
22
  * Overrides the default `EXECUTION_STRATEGY` token with a BullMQ-
23
23
  * backed `IExecutionStrategy` (`BullMqExecutionStrategy`) and wires
24
24
  * the runtime services that own the BullMQ client lifecycle
25
- * (`BullmqRuntimeService` for step enqueue + worker, plus
26
- * `BullmqScheduleService` for `@BatchScheduled` cron entries).
25
+ * (`BullmqRuntime` for step enqueue + worker, plus
26
+ * `BullmqSchedule` for `@BatchScheduled` cron entries).
27
27
  *
28
28
  * Two static methods:
29
29
  *
@@ -1 +1 @@
1
- {"version":3,"file":"bullmq.adapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/bullmq.adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,aAAa,EAAiB,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAMzE,OAAO,EAEL,KAAK,mBAAmB,EAEzB,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;;GAUG;AACH,qBACa,YAAY;CAAG;AAsD5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkFG;AACH,qBAAa,aAAa;IACxB;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,GAAE,mBAAwB,GAAG,YAAY;IAa/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE;QAChC,OAAO,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;QACnC,MAAM,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;QAC5B,UAAU,EAAE,CACV,GAAG,IAAI,EAAE,OAAO,EAAE,KACf,OAAO,CAAC,mBAAmB,CAAC,GAAG,mBAAmB,CAAC;KACzD,GAAG,YAAY;CAoDjB"}
1
+ {"version":3,"file":"bullmq.adapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/bullmq.adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,aAAa,EAAiB,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAMzE,OAAO,EAEL,KAAK,mBAAmB,EAEzB,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;;GAUG;AACH,qBACa,YAAY;CAAG;AAwD5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkFG;AACH,qBAAa,aAAa;IACxB;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,GAAE,mBAAwB,GAAG,YAAY;IAa/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE;QAChC,OAAO,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;QACnC,MAAM,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;QAC5B,UAAU,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,GAAG,mBAAmB,CAAC;KACxF,GAAG,YAAY;CAkDjB"}
@@ -19,8 +19,8 @@ _export(exports, {
19
19
  const _common = require("@nestjs/common");
20
20
  const _core = require("@nest-batch/core");
21
21
  const _bullmqexecutionstrategy = require("../bullmq-execution-strategy");
22
- const _bullmqruntimeservice = require("../bullmq-runtime.service");
23
- const _bullmqscheduleservice = require("../bullmq-schedule.service");
22
+ const _bullmqruntime = require("../bullmq-runtime");
23
+ const _bullmqschedule = require("../bullmq-schedule");
24
24
  const _connection = require("../connection");
25
25
  const _moduleoptions = require("../module-options");
26
26
  function _ts_decorate(decorators, target, key, desc) {
@@ -60,7 +60,7 @@ BullmqModule = _ts_decorate([
60
60
  *
61
61
  * The set mirrors the legacy `BullmqBatchModule.forRoot()` exports
62
62
  * (the `forRootAsync()` legacy path was missing
63
- * `BullmqRuntimeService` from `exports` — that omission is fixed
63
+ * `BullmqRuntime` from `exports` — that omission is fixed
64
64
  * here, both paths now export the same five entries).
65
65
  *
66
66
  * - `EXECUTION_STRATEGY` — the DI token, so host code (e.g. a
@@ -71,16 +71,16 @@ BullmqModule = _ts_decorate([
71
71
  * builders.
72
72
  * - `BullMqExecutionStrategy` — the concrete class, for type-
73
73
  * strict consumers that prefer class injection.
74
- * - `BullmqRuntimeService` — the runtime that owns the
74
+ * - `BullmqRuntime` — the runtime that owns the
75
75
  * `Queue` / `Worker` / `QueueEvents` lifecycle.
76
- * - `BullmqScheduleService` — the runtime that owns the
76
+ * - `BullmqSchedule` — the runtime that owns the
77
77
  * `@BatchScheduled` cron-to-BullMQ translation.
78
78
  */ const ADAPTER_EXPORTS = [
79
79
  _core.EXECUTION_STRATEGY,
80
80
  _moduleoptions.BULLMQ_MODULE_OPTIONS,
81
81
  _bullmqexecutionstrategy.BullMqExecutionStrategy,
82
- _bullmqruntimeservice.BullmqRuntimeService,
83
- _bullmqscheduleservice.BullmqScheduleService
82
+ _bullmqruntime.BullmqRuntime,
83
+ _bullmqschedule.BullmqSchedule
84
84
  ];
85
85
  let BullmqAdapter = class BullmqAdapter {
86
86
  /**
@@ -202,8 +202,8 @@ let BullmqAdapter = class BullmqAdapter {
202
202
  */ function buildStaticProviders(resolved) {
203
203
  return [
204
204
  _bullmqexecutionstrategy.BullMqExecutionStrategy,
205
- _bullmqruntimeservice.BullmqRuntimeService,
206
- _bullmqscheduleservice.BullmqScheduleService,
205
+ _bullmqruntime.BullmqRuntime,
206
+ _bullmqschedule.BullmqSchedule,
207
207
  {
208
208
  provide: _core.EXECUTION_STRATEGY,
209
209
  useExisting: _bullmqexecutionstrategy.BullMqExecutionStrategy
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/adapters/bullmq.adapter.ts"],"sourcesContent":["import { Module, type DynamicModule, type Provider } from '@nestjs/common';\nimport { EXECUTION_STRATEGY, type BatchAdapter } from '@nest-batch/core';\n\nimport { BullMqExecutionStrategy } from '../bullmq-execution-strategy';\nimport { BullmqRuntimeService } from '../bullmq-runtime.service';\nimport { BullmqScheduleService } from '../bullmq-schedule.service';\nimport { resolveBullMqConnection } from '../connection';\nimport {\n BULLMQ_MODULE_OPTIONS,\n type BullMqModuleOptions,\n type ResolvedBullMqModuleOptions,\n} from '../module-options';\n\n/**\n * Empty Nest module class that owns the BullMQ transport's\n * provider graph.\n *\n * Mirrors `InProcessModule` in `@nest-batch/core/src/adapters/\n * in-process.adapter.ts`: the class has no body on purpose. It is\n * purely a `DynamicModule` carrier — Nest's module system requires\n * *some* class to identify the module, and the empty class is the\n * minimum possible surface (no decorators, no lifecycle hooks, no\n * metadata). All real behaviour lives on the providers.\n */\n@Module({})\nexport class BullmqModule {}\n\n/**\n * Sentinel token for the async-options factory chain.\n *\n * `forRootAsync` registers a `useFactory` provider under this token\n * that runs the user's factory, then a second provider\n * (`BULLMQ_MODULE_OPTIONS`) that depends on it and freezes the\n * resolved options. A duplicate `provide` for\n * `BULLMQ_MODULE_OPTIONS` would crash Nest's container, so the\n * chain uses this private symbol as the intermediate step.\n *\n * Mirrors the `Symbol.for('@nest-batch/bullmq/OPTIONS_FACTORY')`\n * used by the legacy `BullmqBatchModule.forRootAsync()` — the\n * `Symbol.for` key is process-scoped and stable across module\n * versions, so any host still wiring up the legacy class is not\n * affected.\n */\nconst OPTIONS_FACTORY: symbol = Symbol.for('@nest-batch/bullmq/OPTIONS_FACTORY');\n\n/**\n * The list of exports the BullMQ adapter's `DynamicModule` exposes\n * to the host application.\n *\n * Centralised so the sync and async paths stay in lockstep — any\n * future addition (e.g. a `BullmqScheduler` controller) only needs\n * to be added here.\n *\n * The set mirrors the legacy `BullmqBatchModule.forRoot()` exports\n * (the `forRootAsync()` legacy path was missing\n * `BullmqRuntimeService` from `exports` — that omission is fixed\n * here, both paths now export the same five entries).\n *\n * - `EXECUTION_STRATEGY` — the DI token, so host code (e.g. a\n * `/healthz` endpoint) can resolve the strategy class via\n * `moduleRef.get(EXECUTION_STRATEGY)`.\n * - `BULLMQ_MODULE_OPTIONS` — the resolved connection / worker\n * config bag, for inspection and (future) for per-role client\n * builders.\n * - `BullMqExecutionStrategy` — the concrete class, for type-\n * strict consumers that prefer class injection.\n * - `BullmqRuntimeService` — the runtime that owns the\n * `Queue` / `Worker` / `QueueEvents` lifecycle.\n * - `BullmqScheduleService` — the runtime that owns the\n * `@BatchScheduled` cron-to-BullMQ translation.\n */\nconst ADAPTER_EXPORTS: ReadonlyArray<symbol | typeof BullMqExecutionStrategy | typeof BullmqRuntimeService | typeof BullmqScheduleService> = [\n EXECUTION_STRATEGY,\n BULLMQ_MODULE_OPTIONS,\n BullMqExecutionStrategy,\n BullmqRuntimeService,\n BullmqScheduleService,\n];\n\n/**\n * `BullmqAdapter` — the transport adapter for `@nest-batch/bullmq`\n * used by the new factory-pattern\n * `NestBatchModule.forRoot({ adapters: { transport, ... } })` API.\n *\n * Overrides the default `EXECUTION_STRATEGY` token with a BullMQ-\n * backed `IExecutionStrategy` (`BullMqExecutionStrategy`) and wires\n * the runtime services that own the BullMQ client lifecycle\n * (`BullmqRuntimeService` for step enqueue + worker, plus\n * `BullmqScheduleService` for `@BatchScheduled` cron entries).\n *\n * Two static methods:\n *\n * - `forRoot(options)` — synchronous configuration. The\n * connection options are resolved up-front and frozen under\n * the `BULLMQ_MODULE_OPTIONS` token. Use this when the Redis\n * host is known at module composition time.\n *\n * - `forRootAsync({ imports, inject, useFactory })` — async\n * configuration. The factory is registered as a sentinel\n * provider; the `BULLMQ_MODULE_OPTIONS` provider depends on\n * it. Use this when the connection comes from a config\n * service or another async source.\n *\n * The two methods share the same provider list via the\n * `buildStaticProviders` helper — the only difference is whether\n * `BULLMQ_MODULE_OPTIONS` is a value provider (sync) or a factory\n * provider that resolves the user's `useFactory` result (async).\n *\n * `globalProviders` is intentionally omitted. The recommended path\n * is to expose host-visible providers via the module's own\n * `exports` (see `ADAPTER_EXPORTS` above) — the `BatchAdapter`\n * interface's `globalProviders` field is for runtime classes the\n * adapter's own module needs but that core itself would also\n * re-export. `JobLauncher` (registered by `NestBatchModule`, not\n * by this adapter) injects the strategy by the `EXECUTION_STRATEGY`\n * token, which is already in `exports`, so the resolution chain\n * works without core having to know which adapter is active.\n *\n * @example\n * ```ts\n * // Synchronous wiring (connection known at module-build time)\n * import { Module } from '@nestjs/common';\n * import { NestBatchModule, InProcessAdapter } from '@nest-batch/core';\n * import { MikroOrmAdapter } from '@nest-batch/mikro-orm';\n * import { BullmqAdapter } from '@nest-batch/bullmq';\n *\n * @Module({\n * imports: [\n * NestBatchModule.forRoot({\n * adapters: {\n * persistence: MikroOrmAdapter,\n * transport: BullmqAdapter.forRoot({\n * connection: {\n * host: process.env.REDIS_HOST,\n * port: Number(process.env.REDIS_PORT),\n * keyPrefix: 'nest-batch:',\n * },\n * autoStartWorker: true,\n * }),\n * },\n * }),\n * ],\n * })\n * class AppModule {}\n * ```\n *\n * @example\n * ```ts\n * // Async wiring (connection sourced from ConfigService)\n * BullmqAdapter.forRootAsync({\n * imports: [ConfigModule],\n * inject: [ConfigService],\n * useFactory: (cfg: ConfigService) => ({\n * connection: {\n * host: cfg.get<string>('redis.host'),\n * port: cfg.get<number>('redis.port'),\n * password: cfg.get<string>('redis.password'),\n * },\n * }),\n * });\n * ```\n */\nexport class BullmqAdapter {\n /**\n * Synchronous configuration.\n *\n * Resolves the connection options up-front (`resolveBullMqConnection`\n * fills in defaults + freezes the bag) and emits a\n * `BatchAdapter` whose `module` is a `global: true`\n * `DynamicModule` registering the strategy class, the runtime\n * services, the `EXECUTION_STRATEGY` binding, and the resolved\n * options as a value provider under `BULLMQ_MODULE_OPTIONS`.\n *\n * No options object is required: the module accepts an empty\n * `{}` and applies all defaults (host `127.0.0.1`, port `6379`,\n * keyPrefix `nest-batch:`, no auth, no TLS, `autoStartWorker:\n * false`).\n *\n * @param options - Connection + worker config. All fields optional.\n * @returns A `BatchAdapter` with `name: 'bullmq'` and the\n * `BullmqModule` dynamic module.\n */\n static forRoot(options: BullMqModuleOptions = {}): BatchAdapter {\n const resolved: ResolvedBullMqModuleOptions = Object.freeze({\n connection: resolveBullMqConnection(options.connection),\n autoStartWorker: options.autoStartWorker ?? false,\n });\n return {\n name: 'bullmq',\n module: buildBullmqDynamicModule({\n providers: buildStaticProviders(resolved),\n }),\n };\n }\n\n /**\n * Async configuration — useful when the Redis connection comes\n * from a config service or another async provider.\n *\n * The shape mirrors `NestBatchModule.forRootAsync`:\n * - `imports` is forwarded to the resulting\n * `DynamicModule.imports` (so `ConfigModule` is available\n * when the factory runs).\n * - `inject` lists the providers the factory needs in its\n * argument list.\n * - `useFactory` resolves the options bag at module-build\n * time. The factory's return value is treated as\n * `BullMqModuleOptions` and is fed through\n * `resolveBullMqConnection` by the `BULLMQ_MODULE_OPTIONS`\n * factory provider (defaults applied, bag frozen).\n *\n * Implementation note: the factory is registered under the\n * package-private `OPTIONS_FACTORY` sentinel token; the\n * `BULLMQ_MODULE_OPTIONS` provider depends on it. This is the\n * same chain the legacy `BullmqBatchModule.forRootAsync` used\n * — the dynamic module is built off the static provider list,\n * with the static `BULLMQ_MODULE_OPTIONS` value provider\n * replaced by the async factory pair.\n *\n * @param asyncOptions - `{ imports, inject, useFactory }` bag.\n * `useFactory` is required; `imports` and `inject` are\n * optional and default to `[]`.\n * @returns A `BatchAdapter` with `name: 'bullmq'` and the\n * `BullmqModule` dynamic module (with `imports` wired).\n */\n static forRootAsync(asyncOptions: {\n imports?: DynamicModule['imports'];\n inject?: readonly unknown[];\n useFactory: (\n ...args: unknown[]\n ) => Promise<BullMqModuleOptions> | BullMqModuleOptions;\n }): BatchAdapter {\n const factoryProvider: Provider = {\n provide: OPTIONS_FACTORY,\n useFactory: asyncOptions.useFactory as (...args: unknown[]) => unknown,\n inject: [...(asyncOptions.inject ?? [])] as Array<string | symbol | Function>,\n };\n\n const mergedOptionsProvider: Provider = {\n provide: BULLMQ_MODULE_OPTIONS,\n useFactory: (\n fromFactory: BullMqModuleOptions | undefined,\n ): ResolvedBullMqModuleOptions => {\n return Object.freeze({\n connection: resolveBullMqConnection(fromFactory?.connection),\n autoStartWorker: fromFactory?.autoStartWorker ?? false,\n });\n },\n inject: [OPTIONS_FACTORY],\n };\n\n // The static provider list is the same as `forRoot` except\n // the value provider for `BULLMQ_MODULE_OPTIONS` is replaced\n // with the async factory above (a duplicate `provide` would\n // crash Nest's container). We seed `buildStaticProviders`\n // with a placeholder resolved bag (its value is discarded\n // — the async provider overrides the slot) so the function\n // can be the single source of truth for the rest of the\n // provider list.\n const baseProviders = buildStaticProviders(\n Object.freeze({\n connection: resolveBullMqConnection(undefined),\n autoStartWorker: false,\n }),\n );\n const filtered = baseProviders.filter(\n (p) =>\n !(\n typeof p === 'object' &&\n p !== null &&\n 'provide' in p &&\n (p as { provide: unknown }).provide === BULLMQ_MODULE_OPTIONS\n ),\n );\n\n return {\n name: 'bullmq',\n module: buildBullmqDynamicModule({\n providers: [factoryProvider, mergedOptionsProvider, ...filtered],\n imports: asyncOptions.imports,\n }),\n };\n }\n}\n\n/**\n * Build the static provider list shared by `forRoot()` and\n * `forRootAsync()`.\n *\n * Centralised so the sync and async paths declare the same set of\n * providers (and any future addition — e.g. a per-role client\n * builder — only needs to be added here).\n *\n * The async path then filters the `BULLMQ_MODULE_OPTIONS` entry\n * out of the returned array and replaces it with the factory\n * pair. Everything else is shared.\n */\nfunction buildStaticProviders(\n resolved: ResolvedBullMqModuleOptions,\n): Provider[] {\n return [\n BullMqExecutionStrategy,\n BullmqRuntimeService,\n BullmqScheduleService,\n {\n provide: EXECUTION_STRATEGY,\n useExisting: BullMqExecutionStrategy,\n },\n {\n provide: BULLMQ_MODULE_OPTIONS,\n useValue: resolved,\n },\n ];\n}\n\n/**\n * Build the `DynamicModule` payload for the BullMQ adapter.\n *\n * Extracted from the two factory methods so the provider /\n * export / global-true shape lives in one place. NestJS's\n * `validateExportedProvider` check rejects an `exports` entry\n * that is not in `providers` (or imported), so adding to one\n * without the other is a silent runtime failure — keeping the\n * two arrays synchronised by construction is the safest\n * pattern.\n *\n * `imports` is optional: `forRoot` does not need any (it has no\n * async providers), `forRootAsync` forwards the user's\n * `imports` (typically `ConfigModule`) so the factory's\n * `inject` targets resolve.\n */\nfunction buildBullmqDynamicModule(args: {\n providers: Provider[];\n imports?: DynamicModule['imports'];\n}): DynamicModule {\n const module: DynamicModule = {\n module: BullmqModule,\n global: true,\n providers: args.providers,\n exports: [...ADAPTER_EXPORTS],\n };\n if (args.imports !== undefined) {\n return { ...module, imports: [...args.imports] };\n }\n return module;\n}\n"],"names":["BullmqAdapter","BullmqModule","OPTIONS_FACTORY","Symbol","for","ADAPTER_EXPORTS","EXECUTION_STRATEGY","BULLMQ_MODULE_OPTIONS","BullMqExecutionStrategy","BullmqRuntimeService","BullmqScheduleService","forRoot","options","resolved","Object","freeze","connection","resolveBullMqConnection","autoStartWorker","name","module","buildBullmqDynamicModule","providers","buildStaticProviders","forRootAsync","asyncOptions","factoryProvider","provide","useFactory","inject","mergedOptionsProvider","fromFactory","baseProviders","undefined","filtered","filter","p","imports","useExisting","useValue","args","global","exports"],"mappings":";;;;;;;;;;;QAkKaA;eAAAA;;QAzIAC;eAAAA;;;wBAzB6C;sBACJ;yCAEd;sCACH;uCACC;4BACE;+BAKjC;;;;;;;AAcA,IAAA,AAAMA,eAAN,MAAMA;AAAc;;;;AAE3B;;;;;;;;;;;;;;;CAeC,GACD,MAAMC,kBAA0BC,OAAOC,GAAG,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;;CAyBC,GACD,MAAMC,kBAAuI;IAC3IC,wBAAkB;IAClBC,oCAAqB;IACrBC,gDAAuB;IACvBC,0CAAoB;IACpBC,4CAAqB;CACtB;AAqFM,IAAA,AAAMV,gBAAN,MAAMA;IACX;;;;;;;;;;;;;;;;;;GAkBC,GACD,OAAOW,QAAQC,UAA+B,CAAC,CAAC,EAAgB;QAC9D,MAAMC,WAAwCC,OAAOC,MAAM,CAAC;YAC1DC,YAAYC,IAAAA,mCAAuB,EAACL,QAAQI,UAAU;YACtDE,iBAAiBN,QAAQM,eAAe,IAAI;QAC9C;QACA,OAAO;YACLC,MAAM;YACNC,QAAQC,yBAAyB;gBAC/BC,WAAWC,qBAAqBV;YAClC;QACF;IACF;IAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BC,GACD,OAAOW,aAAaC,YAMnB,EAAgB;QACf,MAAMC,kBAA4B;YAChCC,SAASzB;YACT0B,YAAYH,aAAaG,UAAU;YACnCC,QAAQ;mBAAKJ,aAAaI,MAAM,IAAI,EAAE;aAAE;QAC1C;QAEA,MAAMC,wBAAkC;YACtCH,SAASpB,oCAAqB;YAC9BqB,YAAY,CACVG;gBAEA,OAAOjB,OAAOC,MAAM,CAAC;oBACnBC,YAAYC,IAAAA,mCAAuB,EAACc,aAAaf;oBACjDE,iBAAiBa,aAAab,mBAAmB;gBACnD;YACF;YACAW,QAAQ;gBAAC3B;aAAgB;QAC3B;QAEA,2DAA2D;QAC3D,6DAA6D;QAC7D,4DAA4D;QAC5D,0DAA0D;QAC1D,0DAA0D;QAC1D,2DAA2D;QAC3D,wDAAwD;QACxD,iBAAiB;QACjB,MAAM8B,gBAAgBT,qBACpBT,OAAOC,MAAM,CAAC;YACZC,YAAYC,IAAAA,mCAAuB,EAACgB;YACpCf,iBAAiB;QACnB;QAEF,MAAMgB,WAAWF,cAAcG,MAAM,CACnC,CAACC,IACC,CACE,CAAA,OAAOA,MAAM,YACbA,MAAM,QACN,aAAaA,KACb,AAACA,EAA2BT,OAAO,KAAKpB,oCAAqB,AAAD;QAIlE,OAAO;YACLY,MAAM;YACNC,QAAQC,yBAAyB;gBAC/BC,WAAW;oBAACI;oBAAiBI;uBAA0BI;iBAAS;gBAChEG,SAASZ,aAAaY,OAAO;YAC/B;QACF;IACF;AACF;AAEA;;;;;;;;;;;CAWC,GACD,SAASd,qBACPV,QAAqC;IAErC,OAAO;QACLL,gDAAuB;QACvBC,0CAAoB;QACpBC,4CAAqB;QACrB;YACEiB,SAASrB,wBAAkB;YAC3BgC,aAAa9B,gDAAuB;QACtC;QACA;YACEmB,SAASpB,oCAAqB;YAC9BgC,UAAU1B;QACZ;KACD;AACH;AAEA;;;;;;;;;;;;;;;CAeC,GACD,SAASQ,yBAAyBmB,IAGjC;IACC,MAAMpB,SAAwB;QAC5BA,QAAQnB;QACRwC,QAAQ;QACRnB,WAAWkB,KAAKlB,SAAS;QACzBoB,SAAS;eAAIrC;SAAgB;IAC/B;IACA,IAAImC,KAAKH,OAAO,KAAKJ,WAAW;QAC9B,OAAO;YAAE,GAAGb,MAAM;YAAEiB,SAAS;mBAAIG,KAAKH,OAAO;aAAC;QAAC;IACjD;IACA,OAAOjB;AACT"}
1
+ {"version":3,"sources":["../../../src/adapters/bullmq.adapter.ts"],"sourcesContent":["import { Module, type DynamicModule, type Provider } from '@nestjs/common';\nimport { EXECUTION_STRATEGY, type BatchAdapter } from '@nest-batch/core';\n\nimport { BullMqExecutionStrategy } from '../bullmq-execution-strategy';\nimport { BullmqRuntime } from '../bullmq-runtime';\nimport { BullmqSchedule } from '../bullmq-schedule';\nimport { resolveBullMqConnection } from '../connection';\nimport {\n BULLMQ_MODULE_OPTIONS,\n type BullMqModuleOptions,\n type ResolvedBullMqModuleOptions,\n} from '../module-options';\n\n/**\n * Empty Nest module class that owns the BullMQ transport's\n * provider graph.\n *\n * Mirrors `InProcessModule` in `@nest-batch/core/src/adapters/\n * in-process.adapter.ts`: the class has no body on purpose. It is\n * purely a `DynamicModule` carrier — Nest's module system requires\n * *some* class to identify the module, and the empty class is the\n * minimum possible surface (no decorators, no lifecycle hooks, no\n * metadata). All real behaviour lives on the providers.\n */\n@Module({})\nexport class BullmqModule {}\n\n/**\n * Sentinel token for the async-options factory chain.\n *\n * `forRootAsync` registers a `useFactory` provider under this token\n * that runs the user's factory, then a second provider\n * (`BULLMQ_MODULE_OPTIONS`) that depends on it and freezes the\n * resolved options. A duplicate `provide` for\n * `BULLMQ_MODULE_OPTIONS` would crash Nest's container, so the\n * chain uses this private symbol as the intermediate step.\n *\n * Mirrors the `Symbol.for('@nest-batch/bullmq/OPTIONS_FACTORY')`\n * used by the legacy `BullmqBatchModule.forRootAsync()` — the\n * `Symbol.for` key is process-scoped and stable across module\n * versions, so any host still wiring up the legacy class is not\n * affected.\n */\nconst OPTIONS_FACTORY: symbol = Symbol.for('@nest-batch/bullmq/OPTIONS_FACTORY');\n\n/**\n * The list of exports the BullMQ adapter's `DynamicModule` exposes\n * to the host application.\n *\n * Centralised so the sync and async paths stay in lockstep — any\n * future addition (e.g. a `BullmqScheduler` controller) only needs\n * to be added here.\n *\n * The set mirrors the legacy `BullmqBatchModule.forRoot()` exports\n * (the `forRootAsync()` legacy path was missing\n * `BullmqRuntime` from `exports` — that omission is fixed\n * here, both paths now export the same five entries).\n *\n * - `EXECUTION_STRATEGY` — the DI token, so host code (e.g. a\n * `/healthz` endpoint) can resolve the strategy class via\n * `moduleRef.get(EXECUTION_STRATEGY)`.\n * - `BULLMQ_MODULE_OPTIONS` — the resolved connection / worker\n * config bag, for inspection and (future) for per-role client\n * builders.\n * - `BullMqExecutionStrategy` — the concrete class, for type-\n * strict consumers that prefer class injection.\n * - `BullmqRuntime` — the runtime that owns the\n * `Queue` / `Worker` / `QueueEvents` lifecycle.\n * - `BullmqSchedule` — the runtime that owns the\n * `@BatchScheduled` cron-to-BullMQ translation.\n */\nconst ADAPTER_EXPORTS: ReadonlyArray<\n symbol | typeof BullMqExecutionStrategy | typeof BullmqRuntime | typeof BullmqSchedule\n> = [\n EXECUTION_STRATEGY,\n BULLMQ_MODULE_OPTIONS,\n BullMqExecutionStrategy,\n BullmqRuntime,\n BullmqSchedule,\n];\n\n/**\n * `BullmqAdapter` — the transport adapter for `@nest-batch/bullmq`\n * used by the new factory-pattern\n * `NestBatchModule.forRoot({ adapters: { transport, ... } })` API.\n *\n * Overrides the default `EXECUTION_STRATEGY` token with a BullMQ-\n * backed `IExecutionStrategy` (`BullMqExecutionStrategy`) and wires\n * the runtime services that own the BullMQ client lifecycle\n * (`BullmqRuntime` for step enqueue + worker, plus\n * `BullmqSchedule` for `@BatchScheduled` cron entries).\n *\n * Two static methods:\n *\n * - `forRoot(options)` — synchronous configuration. The\n * connection options are resolved up-front and frozen under\n * the `BULLMQ_MODULE_OPTIONS` token. Use this when the Redis\n * host is known at module composition time.\n *\n * - `forRootAsync({ imports, inject, useFactory })` — async\n * configuration. The factory is registered as a sentinel\n * provider; the `BULLMQ_MODULE_OPTIONS` provider depends on\n * it. Use this when the connection comes from a config\n * service or another async source.\n *\n * The two methods share the same provider list via the\n * `buildStaticProviders` helper — the only difference is whether\n * `BULLMQ_MODULE_OPTIONS` is a value provider (sync) or a factory\n * provider that resolves the user's `useFactory` result (async).\n *\n * `globalProviders` is intentionally omitted. The recommended path\n * is to expose host-visible providers via the module's own\n * `exports` (see `ADAPTER_EXPORTS` above) — the `BatchAdapter`\n * interface's `globalProviders` field is for runtime classes the\n * adapter's own module needs but that core itself would also\n * re-export. `JobLauncher` (registered by `NestBatchModule`, not\n * by this adapter) injects the strategy by the `EXECUTION_STRATEGY`\n * token, which is already in `exports`, so the resolution chain\n * works without core having to know which adapter is active.\n *\n * @example\n * ```ts\n * // Synchronous wiring (connection known at module-build time)\n * import { Module } from '@nestjs/common';\n * import { NestBatchModule, InProcessAdapter } from '@nest-batch/core';\n * import { MikroOrmAdapter } from '@nest-batch/mikro-orm';\n * import { BullmqAdapter } from '@nest-batch/bullmq';\n *\n * @Module({\n * imports: [\n * NestBatchModule.forRoot({\n * adapters: {\n * persistence: MikroOrmAdapter,\n * transport: BullmqAdapter.forRoot({\n * connection: {\n * host: process.env.REDIS_HOST,\n * port: Number(process.env.REDIS_PORT),\n * keyPrefix: 'nest-batch:',\n * },\n * autoStartWorker: true,\n * }),\n * },\n * }),\n * ],\n * })\n * class AppModule {}\n * ```\n *\n * @example\n * ```ts\n * // Async wiring (connection sourced from ConfigService)\n * BullmqAdapter.forRootAsync({\n * imports: [ConfigModule],\n * inject: [ConfigService],\n * useFactory: (cfg: ConfigService) => ({\n * connection: {\n * host: cfg.get<string>('redis.host'),\n * port: cfg.get<number>('redis.port'),\n * password: cfg.get<string>('redis.password'),\n * },\n * }),\n * });\n * ```\n */\nexport class BullmqAdapter {\n /**\n * Synchronous configuration.\n *\n * Resolves the connection options up-front (`resolveBullMqConnection`\n * fills in defaults + freezes the bag) and emits a\n * `BatchAdapter` whose `module` is a `global: true`\n * `DynamicModule` registering the strategy class, the runtime\n * services, the `EXECUTION_STRATEGY` binding, and the resolved\n * options as a value provider under `BULLMQ_MODULE_OPTIONS`.\n *\n * No options object is required: the module accepts an empty\n * `{}` and applies all defaults (host `127.0.0.1`, port `6379`,\n * keyPrefix `nest-batch:`, no auth, no TLS, `autoStartWorker:\n * false`).\n *\n * @param options - Connection + worker config. All fields optional.\n * @returns A `BatchAdapter` with `name: 'bullmq'` and the\n * `BullmqModule` dynamic module.\n */\n static forRoot(options: BullMqModuleOptions = {}): BatchAdapter {\n const resolved: ResolvedBullMqModuleOptions = Object.freeze({\n connection: resolveBullMqConnection(options.connection),\n autoStartWorker: options.autoStartWorker ?? false,\n });\n return {\n name: 'bullmq',\n module: buildBullmqDynamicModule({\n providers: buildStaticProviders(resolved),\n }),\n };\n }\n\n /**\n * Async configuration — useful when the Redis connection comes\n * from a config service or another async provider.\n *\n * The shape mirrors `NestBatchModule.forRootAsync`:\n * - `imports` is forwarded to the resulting\n * `DynamicModule.imports` (so `ConfigModule` is available\n * when the factory runs).\n * - `inject` lists the providers the factory needs in its\n * argument list.\n * - `useFactory` resolves the options bag at module-build\n * time. The factory's return value is treated as\n * `BullMqModuleOptions` and is fed through\n * `resolveBullMqConnection` by the `BULLMQ_MODULE_OPTIONS`\n * factory provider (defaults applied, bag frozen).\n *\n * Implementation note: the factory is registered under the\n * package-private `OPTIONS_FACTORY` sentinel token; the\n * `BULLMQ_MODULE_OPTIONS` provider depends on it. This is the\n * same chain the legacy `BullmqBatchModule.forRootAsync` used\n * — the dynamic module is built off the static provider list,\n * with the static `BULLMQ_MODULE_OPTIONS` value provider\n * replaced by the async factory pair.\n *\n * @param asyncOptions - `{ imports, inject, useFactory }` bag.\n * `useFactory` is required; `imports` and `inject` are\n * optional and default to `[]`.\n * @returns A `BatchAdapter` with `name: 'bullmq'` and the\n * `BullmqModule` dynamic module (with `imports` wired).\n */\n static forRootAsync(asyncOptions: {\n imports?: DynamicModule['imports'];\n inject?: readonly unknown[];\n useFactory: (...args: unknown[]) => Promise<BullMqModuleOptions> | BullMqModuleOptions;\n }): BatchAdapter {\n const factoryProvider: Provider = {\n provide: OPTIONS_FACTORY,\n useFactory: asyncOptions.useFactory as (...args: unknown[]) => unknown,\n inject: [...(asyncOptions.inject ?? [])] as Array<string | symbol | Function>,\n };\n\n const mergedOptionsProvider: Provider = {\n provide: BULLMQ_MODULE_OPTIONS,\n useFactory: (fromFactory: BullMqModuleOptions | undefined): ResolvedBullMqModuleOptions => {\n return Object.freeze({\n connection: resolveBullMqConnection(fromFactory?.connection),\n autoStartWorker: fromFactory?.autoStartWorker ?? false,\n });\n },\n inject: [OPTIONS_FACTORY],\n };\n\n // The static provider list is the same as `forRoot` except\n // the value provider for `BULLMQ_MODULE_OPTIONS` is replaced\n // with the async factory above (a duplicate `provide` would\n // crash Nest's container). We seed `buildStaticProviders`\n // with a placeholder resolved bag (its value is discarded\n // — the async provider overrides the slot) so the function\n // can be the single source of truth for the rest of the\n // provider list.\n const baseProviders = buildStaticProviders(\n Object.freeze({\n connection: resolveBullMqConnection(undefined),\n autoStartWorker: false,\n }),\n );\n const filtered = baseProviders.filter(\n (p) =>\n !(\n typeof p === 'object' &&\n p !== null &&\n 'provide' in p &&\n (p as { provide: unknown }).provide === BULLMQ_MODULE_OPTIONS\n ),\n );\n\n return {\n name: 'bullmq',\n module: buildBullmqDynamicModule({\n providers: [factoryProvider, mergedOptionsProvider, ...filtered],\n imports: asyncOptions.imports,\n }),\n };\n }\n}\n\n/**\n * Build the static provider list shared by `forRoot()` and\n * `forRootAsync()`.\n *\n * Centralised so the sync and async paths declare the same set of\n * providers (and any future addition — e.g. a per-role client\n * builder — only needs to be added here).\n *\n * The async path then filters the `BULLMQ_MODULE_OPTIONS` entry\n * out of the returned array and replaces it with the factory\n * pair. Everything else is shared.\n */\nfunction buildStaticProviders(resolved: ResolvedBullMqModuleOptions): Provider[] {\n return [\n BullMqExecutionStrategy,\n BullmqRuntime,\n BullmqSchedule,\n {\n provide: EXECUTION_STRATEGY,\n useExisting: BullMqExecutionStrategy,\n },\n {\n provide: BULLMQ_MODULE_OPTIONS,\n useValue: resolved,\n },\n ];\n}\n\n/**\n * Build the `DynamicModule` payload for the BullMQ adapter.\n *\n * Extracted from the two factory methods so the provider /\n * export / global-true shape lives in one place. NestJS's\n * `validateExportedProvider` check rejects an `exports` entry\n * that is not in `providers` (or imported), so adding to one\n * without the other is a silent runtime failure — keeping the\n * two arrays synchronised by construction is the safest\n * pattern.\n *\n * `imports` is optional: `forRoot` does not need any (it has no\n * async providers), `forRootAsync` forwards the user's\n * `imports` (typically `ConfigModule`) so the factory's\n * `inject` targets resolve.\n */\nfunction buildBullmqDynamicModule(args: {\n providers: Provider[];\n imports?: DynamicModule['imports'];\n}): DynamicModule {\n const module: DynamicModule = {\n module: BullmqModule,\n global: true,\n providers: args.providers,\n exports: [...ADAPTER_EXPORTS],\n };\n if (args.imports !== undefined) {\n return { ...module, imports: [...args.imports] };\n }\n return module;\n}\n"],"names":["BullmqAdapter","BullmqModule","OPTIONS_FACTORY","Symbol","for","ADAPTER_EXPORTS","EXECUTION_STRATEGY","BULLMQ_MODULE_OPTIONS","BullMqExecutionStrategy","BullmqRuntime","BullmqSchedule","forRoot","options","resolved","Object","freeze","connection","resolveBullMqConnection","autoStartWorker","name","module","buildBullmqDynamicModule","providers","buildStaticProviders","forRootAsync","asyncOptions","factoryProvider","provide","useFactory","inject","mergedOptionsProvider","fromFactory","baseProviders","undefined","filtered","filter","p","imports","useExisting","useValue","args","global","exports"],"mappings":";;;;;;;;;;;QAoKaA;eAAAA;;QA3IAC;eAAAA;;;wBAzB6C;sBACJ;yCAEd;+BACV;gCACC;4BACS;+BAKjC;;;;;;;AAcA,IAAA,AAAMA,eAAN,MAAMA;AAAc;;;;AAE3B;;;;;;;;;;;;;;;CAeC,GACD,MAAMC,kBAA0BC,OAAOC,GAAG,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;;CAyBC,GACD,MAAMC,kBAEF;IACFC,wBAAkB;IAClBC,oCAAqB;IACrBC,gDAAuB;IACvBC,4BAAa;IACbC,8BAAc;CACf;AAqFM,IAAA,AAAMV,gBAAN,MAAMA;IACX;;;;;;;;;;;;;;;;;;GAkBC,GACD,OAAOW,QAAQC,UAA+B,CAAC,CAAC,EAAgB;QAC9D,MAAMC,WAAwCC,OAAOC,MAAM,CAAC;YAC1DC,YAAYC,IAAAA,mCAAuB,EAACL,QAAQI,UAAU;YACtDE,iBAAiBN,QAAQM,eAAe,IAAI;QAC9C;QACA,OAAO;YACLC,MAAM;YACNC,QAAQC,yBAAyB;gBAC/BC,WAAWC,qBAAqBV;YAClC;QACF;IACF;IAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BC,GACD,OAAOW,aAAaC,YAInB,EAAgB;QACf,MAAMC,kBAA4B;YAChCC,SAASzB;YACT0B,YAAYH,aAAaG,UAAU;YACnCC,QAAQ;mBAAKJ,aAAaI,MAAM,IAAI,EAAE;aAAE;QAC1C;QAEA,MAAMC,wBAAkC;YACtCH,SAASpB,oCAAqB;YAC9BqB,YAAY,CAACG;gBACX,OAAOjB,OAAOC,MAAM,CAAC;oBACnBC,YAAYC,IAAAA,mCAAuB,EAACc,aAAaf;oBACjDE,iBAAiBa,aAAab,mBAAmB;gBACnD;YACF;YACAW,QAAQ;gBAAC3B;aAAgB;QAC3B;QAEA,2DAA2D;QAC3D,6DAA6D;QAC7D,4DAA4D;QAC5D,0DAA0D;QAC1D,0DAA0D;QAC1D,2DAA2D;QAC3D,wDAAwD;QACxD,iBAAiB;QACjB,MAAM8B,gBAAgBT,qBACpBT,OAAOC,MAAM,CAAC;YACZC,YAAYC,IAAAA,mCAAuB,EAACgB;YACpCf,iBAAiB;QACnB;QAEF,MAAMgB,WAAWF,cAAcG,MAAM,CACnC,CAACC,IACC,CACE,CAAA,OAAOA,MAAM,YACbA,MAAM,QACN,aAAaA,KACb,AAACA,EAA2BT,OAAO,KAAKpB,oCAAqB,AAAD;QAIlE,OAAO;YACLY,MAAM;YACNC,QAAQC,yBAAyB;gBAC/BC,WAAW;oBAACI;oBAAiBI;uBAA0BI;iBAAS;gBAChEG,SAASZ,aAAaY,OAAO;YAC/B;QACF;IACF;AACF;AAEA;;;;;;;;;;;CAWC,GACD,SAASd,qBAAqBV,QAAqC;IACjE,OAAO;QACLL,gDAAuB;QACvBC,4BAAa;QACbC,8BAAc;QACd;YACEiB,SAASrB,wBAAkB;YAC3BgC,aAAa9B,gDAAuB;QACtC;QACA;YACEmB,SAASpB,oCAAqB;YAC9BgC,UAAU1B;QACZ;KACD;AACH;AAEA;;;;;;;;;;;;;;;CAeC,GACD,SAASQ,yBAAyBmB,IAGjC;IACC,MAAMpB,SAAwB;QAC5BA,QAAQnB;QACRwC,QAAQ;QACRnB,WAAWkB,KAAKlB,SAAS;QACzBoB,SAAS;eAAIrC;SAAgB;IAC/B;IACA,IAAImC,KAAKH,OAAO,KAAKJ,WAAW;QAC9B,OAAO;YAAE,GAAGb,MAAM;YAAEiB,SAAS;mBAAIG,KAAKH,OAAO;aAAC;QAAC;IACjD;IACA,OAAOjB;AACT"}
@@ -1,5 +1,5 @@
1
1
  import { type ExecutionStrategyContext, type IExecutionStrategy, type JobDefinition, type JobParameters, type LaunchResult } from '@nest-batch/core';
2
- import { BullmqRuntimeService, BULLMQ_STRATEGY_NAME } from './bullmq-runtime.service';
2
+ import { BullmqRuntime, BULLMQ_STRATEGY_NAME } from './bullmq-runtime';
3
3
  /**
4
4
  * BullMQ execution strategy — the `@nest-batch/core`-facing
5
5
  * transport that hands a `JobExecution` off to a BullMQ `Queue`
@@ -8,7 +8,7 @@ import { BullmqRuntimeService, BULLMQ_STRATEGY_NAME } from './bullmq-runtime.ser
8
8
  * Design (T18):
9
9
  * - The actual BullMQ resource ownership (queue / worker /
10
10
  * queue-events lifecycle, connection tuning, event bridge)
11
- * lives in `BullmqRuntimeService`. This class is a thin
11
+ * lives in `BullmqRuntime`. This class is a thin
12
12
  * adapter that maps the `IExecutionStrategy` contract to
13
13
  * the runtime service's `launch()` shape.
14
14
  * - Splitting the two lets the runtime service be
@@ -36,7 +36,7 @@ export declare class BullMqExecutionStrategy implements IExecutionStrategy {
36
36
  /** Strategy name. Mirrors the runtime service's name. */
37
37
  readonly name = "bullmq";
38
38
  private readonly logger;
39
- constructor(runtime: BullmqRuntimeService);
39
+ constructor(runtime: BullmqRuntime);
40
40
  /**
41
41
  * Enqueue the work and return the BullMQ job id. The DB
42
42
  * execution row was created by the launcher BEFORE this
@@ -1 +1 @@
1
- {"version":3,"file":"bullmq-execution-strategy.d.ts","sourceRoot":"","sources":["../../src/bullmq-execution-strategy.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACrB,MAAM,0BAA0B,CAAC;AAElC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBACa,uBAAwB,YAAW,kBAAkB;IAMpD,OAAO,CAAC,QAAQ,CAAC,OAAO;IALpC,yDAAyD;IACzD,QAAQ,CAAC,IAAI,YAAwB;IAErC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4C;gBAEtC,OAAO,EAAE,oBAAoB;IAE1D;;;;;;;;;;;OAWG;IACG,MAAM,CACV,GAAG,EAAE,aAAa,EAClB,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,wBAAwB,GAC5B,OAAO,CAAC,YAAY,CAAC;CAGzB;AAED;;;GAGG;AACH,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
1
+ {"version":3,"file":"bullmq-execution-strategy.d.ts","sourceRoot":"","sources":["../../src/bullmq-execution-strategy.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAEvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBACa,uBAAwB,YAAW,kBAAkB;IAMpD,OAAO,CAAC,QAAQ,CAAC,OAAO;IALpC,yDAAyD;IACzD,QAAQ,CAAC,IAAI,YAAwB;IAErC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4C;gBAEtC,OAAO,EAAE,aAAa;IAEnD;;;;;;;;;;;OAWG;IACG,MAAM,CACV,GAAG,EAAE,aAAa,EAClB,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,wBAAwB,GAC5B,OAAO,CAAC,YAAY,CAAC;CAGzB;AAED;;;GAGG;AACH,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
@@ -10,14 +10,14 @@ function _export(target, all) {
10
10
  }
11
11
  _export(exports, {
12
12
  get BULLMQ_STRATEGY_NAME () {
13
- return _bullmqruntimeservice.BULLMQ_STRATEGY_NAME;
13
+ return _bullmqruntime.BULLMQ_STRATEGY_NAME;
14
14
  },
15
15
  get BullMqExecutionStrategy () {
16
16
  return BullMqExecutionStrategy;
17
17
  }
18
18
  });
19
19
  const _common = require("@nestjs/common");
20
- const _bullmqruntimeservice = require("./bullmq-runtime.service");
20
+ const _bullmqruntime = require("./bullmq-runtime");
21
21
  function _ts_decorate(decorators, target, key, desc) {
22
22
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
23
23
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -29,7 +29,7 @@ function _ts_metadata(k, v) {
29
29
  }
30
30
  let BullMqExecutionStrategy = class BullMqExecutionStrategy {
31
31
  runtime;
32
- /** Strategy name. Mirrors the runtime service's name. */ name = _bullmqruntimeservice.BULLMQ_STRATEGY_NAME;
32
+ /** Strategy name. Mirrors the runtime service's name. */ name = _bullmqruntime.BULLMQ_STRATEGY_NAME;
33
33
  logger = new _common.Logger(BullMqExecutionStrategy.name);
34
34
  constructor(runtime){
35
35
  this.runtime = runtime;
@@ -53,7 +53,7 @@ BullMqExecutionStrategy = _ts_decorate([
53
53
  (0, _common.Injectable)(),
54
54
  _ts_metadata("design:type", Function),
55
55
  _ts_metadata("design:paramtypes", [
56
- typeof _bullmqruntimeservice.BullmqRuntimeService === "undefined" ? Object : _bullmqruntimeservice.BullmqRuntimeService
56
+ typeof _bullmqruntime.BullmqRuntime === "undefined" ? Object : _bullmqruntime.BullmqRuntime
57
57
  ])
58
58
  ], BullMqExecutionStrategy);
59
59
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/bullmq-execution-strategy.ts"],"sourcesContent":["import { Injectable, Logger } from '@nestjs/common';\n\nimport {\n type ExecutionStrategyContext,\n type IExecutionStrategy,\n type JobDefinition,\n type JobParameters,\n type LaunchResult,\n} from '@nest-batch/core';\n\nimport {\n BullmqRuntimeService,\n BULLMQ_STRATEGY_NAME,\n} from './bullmq-runtime.service';\n\n/**\n * BullMQ execution strategy — the `@nest-batch/core`-facing\n * transport that hands a `JobExecution` off to a BullMQ `Queue`\n * and lets a `Worker` process the work.\n *\n * Design (T18):\n * - The actual BullMQ resource ownership (queue / worker /\n * queue-events lifecycle, connection tuning, event bridge)\n * lives in `BullmqRuntimeService`. This class is a thin\n * adapter that maps the `IExecutionStrategy` contract to\n * the runtime service's `launch()` shape.\n * - Splitting the two lets the runtime service be\n * independently testable (e.g. a test that wants to drive\n * the worker without going through the launcher can\n * instantiate the runtime service alone), and lets the\n * strategy class stay as a stable public surface for\n * `EXECUTION_STRATEGY` consumers.\n * - The strategy inherits the runtime service's\n * `name` (`'bullmq'`) — the runtime service is the\n * single source of truth for the strategy name.\n *\n * `name` and `launch()` together comprise the T18 contract:\n * - `name = 'bullmq'` — replaces the T17 stub's\n * `'bullmq-stub'` so log lines and boundary reports can\n * tell the real implementation from the skeleton.\n * - `launch()` enqueues exactly one BullMQ job per step\n * (one job per step, NEVER one job per row/chunk) and\n * returns `{ kind: 'enqueued', queueJobId }`. The launch\n * is fire-and-forget; the launcher re-resolves the\n * canonical `JobExecution` from the repository.\n */\n@Injectable()\nexport class BullMqExecutionStrategy implements IExecutionStrategy {\n /** Strategy name. Mirrors the runtime service's name. */\n readonly name = BULLMQ_STRATEGY_NAME;\n\n private readonly logger = new Logger(BullMqExecutionStrategy.name);\n\n constructor(private readonly runtime: BullmqRuntimeService) {}\n\n /**\n * Enqueue the work and return the BullMQ job id. The DB\n * execution row was created by the launcher BEFORE this\n * method was called — this method MUST NOT re-create it\n * (the launcher's atomic create-or-lock would race with us).\n *\n * Throws on producer failure. The launcher propagates the\n * error to its caller; the canonical `JobExecution` row\n * stays in `STARTING` and the host's recovery path is\n * responsible for transitioning it (a future task will\n * wire a \"dead letter\" cleanup).\n */\n async launch(\n job: JobDefinition,\n params: JobParameters,\n ctx: ExecutionStrategyContext,\n ): Promise<LaunchResult> {\n return this.runtime.launch(job, params, ctx);\n }\n}\n\n/**\n * Re-export the canonical `name` for tests that want to assert\n * on it without importing the runtime service directly.\n */\nexport { BULLMQ_STRATEGY_NAME };\n"],"names":["BULLMQ_STRATEGY_NAME","BullMqExecutionStrategy","name","logger","Logger","runtime","launch","job","params","ctx"],"mappings":";;;;;;;;;;;QAgFSA;eAAAA,0CAAoB;;QAjChBC;eAAAA;;;wBA/CsB;sCAa5B;;;;;;;;;;AAkCA,IAAA,AAAMA,0BAAN,MAAMA;;IACX,uDAAuD,GACvD,AAASC,OAAOF,0CAAoB,CAAC;IAEpBG,SAAS,IAAIC,cAAM,CAACH,wBAAwBC,IAAI,EAAE;IAEnE,YAAY,AAAiBG,OAA6B,CAAE;aAA/BA,UAAAA;IAAgC;IAE7D;;;;;;;;;;;GAWC,GACD,MAAMC,OACJC,GAAkB,EAClBC,MAAqB,EACrBC,GAA6B,EACN;QACvB,OAAO,IAAI,CAACJ,OAAO,CAACC,MAAM,CAACC,KAAKC,QAAQC;IAC1C;AACF"}
1
+ {"version":3,"sources":["../../src/bullmq-execution-strategy.ts"],"sourcesContent":["import { Injectable, Logger } from '@nestjs/common';\n\nimport {\n type ExecutionStrategyContext,\n type IExecutionStrategy,\n type JobDefinition,\n type JobParameters,\n type LaunchResult,\n} from '@nest-batch/core';\n\nimport { BullmqRuntime, BULLMQ_STRATEGY_NAME } from './bullmq-runtime';\n\n/**\n * BullMQ execution strategy — the `@nest-batch/core`-facing\n * transport that hands a `JobExecution` off to a BullMQ `Queue`\n * and lets a `Worker` process the work.\n *\n * Design (T18):\n * - The actual BullMQ resource ownership (queue / worker /\n * queue-events lifecycle, connection tuning, event bridge)\n * lives in `BullmqRuntime`. This class is a thin\n * adapter that maps the `IExecutionStrategy` contract to\n * the runtime service's `launch()` shape.\n * - Splitting the two lets the runtime service be\n * independently testable (e.g. a test that wants to drive\n * the worker without going through the launcher can\n * instantiate the runtime service alone), and lets the\n * strategy class stay as a stable public surface for\n * `EXECUTION_STRATEGY` consumers.\n * - The strategy inherits the runtime service's\n * `name` (`'bullmq'`) — the runtime service is the\n * single source of truth for the strategy name.\n *\n * `name` and `launch()` together comprise the T18 contract:\n * - `name = 'bullmq'` — replaces the T17 stub's\n * `'bullmq-stub'` so log lines and boundary reports can\n * tell the real implementation from the skeleton.\n * - `launch()` enqueues exactly one BullMQ job per step\n * (one job per step, NEVER one job per row/chunk) and\n * returns `{ kind: 'enqueued', queueJobId }`. The launch\n * is fire-and-forget; the launcher re-resolves the\n * canonical `JobExecution` from the repository.\n */\n@Injectable()\nexport class BullMqExecutionStrategy implements IExecutionStrategy {\n /** Strategy name. Mirrors the runtime service's name. */\n readonly name = BULLMQ_STRATEGY_NAME;\n\n private readonly logger = new Logger(BullMqExecutionStrategy.name);\n\n constructor(private readonly runtime: BullmqRuntime) {}\n\n /**\n * Enqueue the work and return the BullMQ job id. The DB\n * execution row was created by the launcher BEFORE this\n * method was called — this method MUST NOT re-create it\n * (the launcher's atomic create-or-lock would race with us).\n *\n * Throws on producer failure. The launcher propagates the\n * error to its caller; the canonical `JobExecution` row\n * stays in `STARTING` and the host's recovery path is\n * responsible for transitioning it (a future task will\n * wire a \"dead letter\" cleanup).\n */\n async launch(\n job: JobDefinition,\n params: JobParameters,\n ctx: ExecutionStrategyContext,\n ): Promise<LaunchResult> {\n return this.runtime.launch(job, params, ctx);\n }\n}\n\n/**\n * Re-export the canonical `name` for tests that want to assert\n * on it without importing the runtime service directly.\n */\nexport { BULLMQ_STRATEGY_NAME };\n"],"names":["BULLMQ_STRATEGY_NAME","BullMqExecutionStrategy","name","logger","Logger","runtime","launch","job","params","ctx"],"mappings":";;;;;;;;;;;QA6ESA;eAAAA,mCAAoB;;QAjChBC;eAAAA;;;wBA5CsB;+BAUiB;;;;;;;;;;AAkC7C,IAAA,AAAMA,0BAAN,MAAMA;;IACX,uDAAuD,GACvD,AAASC,OAAOF,mCAAoB,CAAC;IAEpBG,SAAS,IAAIC,cAAM,CAACH,wBAAwBC,IAAI,EAAE;IAEnE,YAAY,AAAiBG,OAAsB,CAAE;aAAxBA,UAAAA;IAAyB;IAEtD;;;;;;;;;;;GAWC,GACD,MAAMC,OACJC,GAAkB,EAClBC,MAAqB,EACrBC,GAA6B,EACN;QACvB,OAAO,IAAI,CAACJ,OAAO,CAACC,MAAM,CAACC,KAAKC,QAAQC;IAC1C;AACF"}
@@ -0,0 +1,237 @@
1
+ import { OnApplicationBootstrap, OnApplicationShutdown } from '@nestjs/common';
2
+ import { type IExecutionStrategy, type JobDefinition, type BatchObserver, type JobRepository } from '@nest-batch/core';
3
+ import { JobExecutor, JobRegistry } from '@nest-batch/core';
4
+ import { type ResolvedBullMqModuleOptions } from './module-options';
5
+ /**
6
+ * Payload shape stored in a BullMQ job's `data` field.
7
+ *
8
+ * The strategy enqueues one BullMQ job per step (or per partition,
9
+ * in a future enhancement). The worker reconstructs the
10
+ * `JobExecution` from the repository via `executionId` and the
11
+ * `JobDefinition` from the registry via `jobId`.
12
+ *
13
+ * Why not store the full `JobDefinition` in the payload?
14
+ * - IR is mutable across the host process (decorators / builders
15
+ * may swap providers in tests, hot-reload, etc.). The
16
+ * repository + registry are the canonical sources; the
17
+ * payload carries only the keys needed to look them up.
18
+ * - Storage size — IRs can be large (listeners, resolvers).
19
+ * Redis is transport, not cache; small payloads are cheaper.
20
+ */
21
+ export interface BullmqJobPayload {
22
+ /** JobExecution id, used to load the canonical execution row. */
23
+ readonly executionId: string;
24
+ /** Mirrors `executionId` today; kept distinct for forward compat. */
25
+ readonly jobExecutionId: string;
26
+ /** JobDefinition id, used to look up the IR from the registry. */
27
+ readonly jobId: string;
28
+ /** Step id (the `name` field of the BullMQ job). */
29
+ readonly stepId: string;
30
+ /**
31
+ * Partition index. Reserved for a future enhancement where a
32
+ * chunk step is split into N partitions and enqueued as N
33
+ * BullMQ jobs. Today the strategy always enqueues one job
34
+ * per step (regardless of chunk size), so the field is
35
+ * `undefined`. Kept in the payload shape so the worker
36
+ * can distinguish "this is a step" from "this is a partition"
37
+ * without a separate discriminator.
38
+ */
39
+ readonly partitionIndex?: number;
40
+ }
41
+ /**
42
+ * The single BullMQ queue name used by the strategy + worker +
43
+ * queue-events. We deliberately do not fan out into per-step
44
+ * queues — that would force the host to pre-declare every step
45
+ * name at compile time, which is at odds with the decorator /
46
+ * builder APIs that discover steps at runtime. A single queue
47
+ * keyed by the step's `name` field is the standard BullMQ pattern
48
+ * (the `name` field discriminates the work).
49
+ *
50
+ * BullMQ 5 rejects queue names that contain a colon (`:`) because
51
+ * it is the path separator in the Redis key layout. We use a
52
+ * hyphen-separated name accordingly.
53
+ */
54
+ export declare const BULLMQ_QUEUE_NAME = "nest-batch-work";
55
+ /**
56
+ * Name of the BullMQ strategy. Logged by the bridge for diagnostic
57
+ * purposes and asserted by tests that need to distinguish the
58
+ * real implementation from the T17 stub.
59
+ */
60
+ export declare const BULLMQ_STRATEGY_NAME = "bullmq";
61
+ /**
62
+ * Bridge between the BullMQ `Queue` / `Worker` / `QueueEvents` and
63
+ * the `@nest-batch/core` execution pipeline.
64
+ *
65
+ * Responsibilities (T18 contract):
66
+ * 1. Own the producer / worker connection clients with the
67
+ * role-specific tuning (fail-fast producer, blocking worker).
68
+ * 2. Implement the `IExecutionStrategy` contract: `launch()`
69
+ * enqueues a single BullMQ job per step, returns
70
+ * `{ kind: 'enqueued', queueJobId }`. The launch is
71
+ * fire-and-forget — the strategy does NOT block on the
72
+ * worker.
73
+ * 3. Drive the worker lifecycle (`OnApplicationBootstrap` /
74
+ * `OnApplicationShutdown`).
75
+ * 4. Bridge `QueueEvents` `completed` / `failed` / `stalled`
76
+ * into the `BatchObserver` (defaulting to `NoopBatchObserver`).
77
+ * 5. Hand off to `JobExecutor.execute(execution, jobDef)` from
78
+ * inside the worker — Batch Core remains the source of truth
79
+ * for state transitions, skip/retry, checkpoint, restart.
80
+ *
81
+ * Why a single class (not separate `Queue` / `Worker` providers)?
82
+ * - The producer and worker share a `connection` record but
83
+ * carry *different* `ConnectionOptions` (different
84
+ * `maxRetriesPerRequest`, `enableReadyCheck`, ...). Splitting
85
+ * them across providers would force the connection-tuning
86
+ * logic into two places and risk the worker accidentally
87
+ * inheriting the producer's fail-fast config (or vice versa).
88
+ * - Lifecycle is a unit: open producer + worker + events
89
+ * together, close them together in the documented order
90
+ * (workers first, then events, then queues). Centralising
91
+ * this in one class makes the close-order a single source
92
+ * of truth and a single method (`close()`).
93
+ */
94
+ export declare class BullmqRuntime implements IExecutionStrategy, OnApplicationBootstrap, OnApplicationShutdown {
95
+ private readonly options;
96
+ private readonly repository;
97
+ private readonly registry;
98
+ private readonly jobExecutor;
99
+ private readonly observer;
100
+ /**
101
+ * Strategy name. Distinct from the T17 stub's `'bullmq-stub'`
102
+ * so log lines and boundary reports can tell them apart.
103
+ */
104
+ readonly name = "bullmq";
105
+ private readonly logger;
106
+ /** BullMQ queue (producer side). */
107
+ private queue;
108
+ /** BullMQ worker (consumer side). */
109
+ private worker;
110
+ /** BullMQ QueueEvents stream listener. */
111
+ private queueEvents;
112
+ /**
113
+ * Promise-chain lock for the close path. We capture the first
114
+ * `close()` invocation and short-circuit subsequent ones so a
115
+ * stray double-shutdown (Nest calls `OnApplicationShutdown`
116
+ * once, but tests sometimes do their own) does not race the
117
+ * in-flight close.
118
+ */
119
+ private closePromise;
120
+ constructor(options: ResolvedBullMqModuleOptions, repository: JobRepository, registry: JobRegistry, jobExecutor: JobExecutor, observer?: BatchObserver);
121
+ /**
122
+ * Nest lifecycle: spin up the queue, worker, and queue-events
123
+ * after the DI container is fully wired. We do this in
124
+ * `onApplicationBootstrap` (not `onModuleInit`) so every other
125
+ * provider — including user-supplied `JobRepository` overrides —
126
+ * is already instantiated and injectable.
127
+ *
128
+ * Worker startup is gated on `options.autoStartWorker`. The
129
+ * flag exists for launcher-only deployments (e.g. an API
130
+ * service that only enqueues) and for tests that want to
131
+ * exercise the producer side in isolation. When the flag is
132
+ * `false` the queue is still created (so `launch()` can
133
+ * enqueue), but the worker is not started (no consumer means
134
+ * the jobs sit in the queue indefinitely).
135
+ */
136
+ onApplicationBootstrap(): void;
137
+ /**
138
+ * Nest lifecycle: close every BullMQ resource in the documented
139
+ * order — workers first (let in-flight jobs finish or be
140
+ * returned to the queue), then events (no new events can
141
+ * arrive once the worker is closed), then queues (the producer
142
+ * is closed last so any pending `add()` calls had a chance to
143
+ * land).
144
+ *
145
+ * Idempotent: a second call to `onApplicationShutdown` (which
146
+ * can happen in tests) short-circuits to the first close's
147
+ * promise rather than racing.
148
+ */
149
+ onApplicationShutdown(): Promise<void>;
150
+ /**
151
+ * Enqueue a single BullMQ job per step. Returns
152
+ * `{ kind: 'enqueued', queueJobId }` after the producer has
153
+ * acknowledged the enqueue. The execution is fire-and-forget:
154
+ * the launcher resolves the latest persisted `JobExecution`
155
+ * (which is still in `STARTING`/`STARTED` because the executor
156
+ * has not run yet).
157
+ *
158
+ * The canonical `JobExecution` row is created by the launcher
159
+ * via `repository.createExecutionAtomic` BEFORE this method is
160
+ * called (the `executionId` in `ctx` is the result). This
161
+ * strategy does NOT re-create it; doing so would race the
162
+ * launcher's atomic create and break the `SELECT ... FOR
163
+ * UPDATE SKIP LOCKED` invariant.
164
+ *
165
+ * Throws if the producer cannot enqueue (Redis down, key
166
+ * collision, etc.). The launcher re-throws the error to its
167
+ * caller; the `JobExecution` row remains in `STARTING` —
168
+ * the host's recovery path (or a manual cleanup) is
169
+ * responsible for transitioning it.
170
+ */
171
+ launch(job: JobDefinition, _params: Record<string, unknown>, ctx: {
172
+ executionId: string;
173
+ jobExecutionId: string;
174
+ }): Promise<{
175
+ kind: 'enqueued';
176
+ queueJobId: string;
177
+ }>;
178
+ private buildQueue;
179
+ private buildWorker;
180
+ private buildQueueEvents;
181
+ /**
182
+ * Wire the `QueueEvents` listeners to the configured
183
+ * `BatchObserver`. Each listener swallows observer errors so
184
+ * a slow / failing observer cannot poison the BullMQ event
185
+ * stream.
186
+ */
187
+ private attachQueueEventsBridge;
188
+ private bridgeEvent;
189
+ /**
190
+ * Worker entry point. Loads the canonical `JobExecution` from
191
+ * the repository and the `JobDefinition` from the registry, then
192
+ * hands the work to `JobExecutor.execute`. All batch semantics
193
+ * (step dispatch, chunk loop, skip/retry, checkpoint) live in
194
+ * the executor — this method is a thin bridge.
195
+ */
196
+ private processJob;
197
+ /**
198
+ * Producer-side connection tuning. The two flags below are
199
+ * the contract the T18 "Redis-down" test depends on:
200
+ *
201
+ * - `enableOfflineQueue: false` — a `Queue.add()` against a
202
+ * dead Redis MUST throw synchronously rather than buffer
203
+ * the command. Without this, BullMQ keeps the command in
204
+ * memory and `add()` returns success, breaking the
205
+ * "fail fast" guarantee.
206
+ * - `maxRetriesPerRequest: 1` — keep the first `add`
207
+ * fast; subsequent reconnects are handled by ioredis
208
+ * itself (we do not want BullMQ to block on retries
209
+ * during the launcher call).
210
+ *
211
+ * BullMQ specifically warns against `maxRetriesPerRequest: null`
212
+ * on the producer, because the producer does not use blocking
213
+ * commands. We use `1` for the same reason.
214
+ */
215
+ private producerConnectionOptions;
216
+ /**
217
+ * Worker-side connection tuning. Two flags that BullMQ
218
+ * *requires* for blocking workers (per the BullMQ docs):
219
+ *
220
+ * - `maxRetriesPerRequest: null` — the worker's
221
+ * `BLPOP` / `BRPOPLPUSH` / `XREADGROUP` commands MUST NOT
222
+ * retry per request. A stalled worker surfaces as a
223
+ * stall, not a connection error.
224
+ * - `enableReadyCheck: false` — the worker should not
225
+ * refuse to start when Redis is in the middle of a
226
+ * failover; ioredis reconnects on its own.
227
+ */
228
+ private workerConnectionOptions;
229
+ /**
230
+ * Close all BullMQ resources in the documented order:
231
+ * worker → events → queue. Each step is best-effort: a close
232
+ * error on one resource does not prevent the others from
233
+ * being closed.
234
+ */
235
+ private close;
236
+ }
237
+ //# sourceMappingURL=bullmq-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bullmq-runtime.d.ts","sourceRoot":"","sources":["../../src/bullmq-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,sBAAsB,EACtB,qBAAqB,EAEtB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,aAAa,EAElB,KAAK,aAAa,EAInB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,WAAW,EAAE,WAAW,EAAkC,MAAM,kBAAkB,CAAC;AAE5F,OAAO,EAAyB,KAAK,2BAA2B,EAAE,MAAM,kBAAkB,CAAC;AAE3F;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,gBAAgB;IAC/B,iEAAiE;IACjE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,qEAAqE;IACrE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,oDAAoD;IACpD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;;;;;OAQG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,iBAAiB,oBAAoB,CAAC;AAEnD;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,WAAW,CAAC;AAE7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,qBACa,aACX,YAAW,kBAAkB,EAAE,sBAAsB,EAAE,qBAAqB;IA2B1E,OAAO,CAAC,QAAQ,CAAC,OAAO;IAExB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAE5B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IA/B3B;;;OAGG;IACH,QAAQ,CAAC,IAAI,YAAwB;IAErC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;IAEzD,oCAAoC;IACpC,OAAO,CAAC,KAAK,CAAsB;IACnC,qCAAqC;IACrC,OAAO,CAAC,MAAM,CAAyC;IACvD,0CAA0C;IAC1C,OAAO,CAAC,WAAW,CAA4B;IAC/C;;;;;;OAMG;IACH,OAAO,CAAC,YAAY,CAA8B;gBAI/B,OAAO,EAAE,2BAA2B,EAEpC,UAAU,EAAE,aAAa,EACzB,QAAQ,EAAE,WAAW,EACrB,WAAW,EAAE,WAAW,EAExB,QAAQ,GAAE,aAAwD;IAGrF;;;;;;;;;;;;;;OAcG;IACH,sBAAsB,IAAI,IAAI;IAmB9B;;;;;;;;;;;OAWG;IACG,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAY5C;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,MAAM,CACV,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,GAAG,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,GACnD,OAAO,CAAC;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAsEpD,OAAO,CAAC,UAAU;IAiClB,OAAO,CAAC,WAAW;IAYnB,OAAO,CAAC,gBAAgB;IAOxB;;;;;OAKG;IACH,OAAO,CAAC,uBAAuB;YAiBjB,WAAW;IAsBzB;;;;;;OAMG;YACW,UAAU;IAyBxB;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,yBAAyB;IAajC;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,uBAAuB;IAiB/B;;;;;OAKG;YACW,KAAK;CA8BpB"}