@pattern-stack/codegen 0.4.3 → 0.4.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pattern-stack/codegen",
3
- "version": "0.4.3",
3
+ "version": "0.4.4",
4
4
  "description": "Entity-driven code generation for full-stack TypeScript applications",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -596,10 +596,14 @@ export class MemoryJobOrchestrator implements IJobOrchestrator {
596
596
  // ModuleRef so `@Inject` constructor params work. ModuleRef is
597
597
  // @Optional() — zero-dep test stubs that construct this orchestrator
598
598
  // manually still hit the legacy `new HandlerClass()` path.
599
+ // `get({ strict: false })` (not `create()`) — the handler must be a
600
+ // provider in its owning module so cross-module @Inject dependencies
601
+ // resolve. See job-worker.ts for the full rationale.
599
602
  const handler = this.moduleRef
600
- ? ((await this.moduleRef.create(
603
+ ? (this.moduleRef.get(
601
604
  HandlerClass as unknown as new (...args: unknown[]) => unknown,
602
- )) as JobHandlerBase<unknown>)
605
+ { strict: false },
606
+ ) as JobHandlerBase<unknown>)
603
607
  : new HandlerClass();
604
608
 
605
609
  const ctx: JobContext<unknown> = {
@@ -177,8 +177,16 @@ export class JobWorkerOrchestrator implements OnModuleInit, OnModuleDestroy {
177
177
  `the resolved pool config. Configured pools: [${[...poolConfig.keys()].join(', ')}].`,
178
178
  );
179
179
  }
180
+ // `pool` here is the logical pool name (e.g. 'crm_sync') — the same
181
+ // value the orchestrator persists into `job_run.pool` from
182
+ // `@JobHandler.meta.pool`, and therefore the value the worker's
183
+ // claim query filters on. `def.queue` is a display/routing alias
184
+ // (e.g. 'jobs-crm-sync') used by BullMQ-style backends for queue
185
+ // naming; it MUST NOT be passed as the claim-filter pool, or the
186
+ // worker will never match any row and the pool silently never
187
+ // drains. See v0.4.4 fix notes.
180
188
  const workerOptions: JobWorkerOptions = {
181
- pool: def.queue,
189
+ pool: poolName,
182
190
  concurrency: def.concurrency,
183
191
  shutdownTimeoutMs:
184
192
  this.options.shutdownTimeoutMs ?? DEFAULT_SHUTDOWN_TIMEOUT_MS,
@@ -192,7 +200,7 @@ export class JobWorkerOrchestrator implements OnModuleInit, OnModuleDestroy {
192
200
  worker.onModuleInit();
193
201
  this.workers.push(worker);
194
202
  this.logger.log(
195
- `JobWorker started: pool='${def.queue}' concurrency=${def.concurrency}`,
203
+ `JobWorker started: pool='${poolName}' (queue='${def.queue}') concurrency=${def.concurrency}`,
196
204
  );
197
205
  }
198
206
  }
@@ -421,16 +421,22 @@ export class JobWorker implements OnModuleInit, OnModuleDestroy {
421
421
  const meta = registryEntry.meta as JobHandlerMeta<unknown>;
422
422
  const HandlerClass = registryEntry.handlerClass;
423
423
 
424
- // (c) Build JobContext. Instantiate handler via Nest's ModuleRef so
425
- // `@Inject` constructor params resolve. `create({ strict: false })`
426
- // walks the whole module graph for providers (handlers don't need to
427
- // be registered as providers themselves; the @JobHandler decorator
428
- // is the only registration required). A fresh instance per run
429
- // mirrors the contract handlers were authored against and keeps
430
- // run-scoped state from leaking across claims.
431
- const handler = (await this.moduleRef.create(
424
+ // (c) Build JobContext. Resolve the handler instance from Nest's DI
425
+ // graph so its `@Inject` constructor params (which may come from
426
+ // any module in the app graph) are satisfied. `moduleRef.create()`
427
+ // would otherwise instantiate a fresh class within JobWorkerModule's
428
+ // scope only which blows up with "not a provider of the current
429
+ // module" for any handler that consumes a service from a peer
430
+ // module (e.g. CrmSyncJob injecting CrmSyncFactory from CrmModule).
431
+ // Consequence: handlers MUST be registered as providers in their
432
+ // owning module (@Injectable + `providers: [HandlerClass]`). The
433
+ // @JobHandler decorator handles registry registration only, not DI.
434
+ // See the jobs skill's handler-authoring.md for the registration
435
+ // rule.
436
+ const handler = this.moduleRef.get(
432
437
  HandlerClass as unknown as new (...args: unknown[]) => unknown,
433
- )) as JobHandlerBase<unknown>;
438
+ { strict: false },
439
+ ) as JobHandlerBase<unknown>;
434
440
  const ctx: JobContext<unknown> = {
435
441
  input: claimed.input,
436
442
  run: claimed as JobRun,