atomic-queues 1.5.2 → 1.6.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.
Files changed (216) hide show
  1. package/README.md +59 -35
  2. package/dist/decorators/constants.d.ts +17 -0
  3. package/dist/decorators/constants.d.ts.map +1 -0
  4. package/dist/decorators/constants.js +23 -0
  5. package/dist/decorators/constants.js.map +1 -0
  6. package/dist/decorators/entity.decorators.d.ts +88 -0
  7. package/dist/decorators/entity.decorators.d.ts.map +1 -0
  8. package/dist/decorators/entity.decorators.js +150 -0
  9. package/dist/decorators/entity.decorators.js.map +1 -0
  10. package/dist/decorators/index.d.ts +9 -1
  11. package/dist/decorators/index.d.ts.map +1 -1
  12. package/dist/decorators/index.js +9 -1
  13. package/dist/decorators/index.js.map +1 -1
  14. package/dist/decorators/interfaces.d.ts +130 -0
  15. package/dist/decorators/interfaces.d.ts.map +1 -0
  16. package/dist/decorators/interfaces.js +3 -0
  17. package/dist/decorators/interfaces.js.map +1 -0
  18. package/dist/decorators/job.decorators.d.ts +60 -0
  19. package/dist/decorators/job.decorators.d.ts.map +1 -0
  20. package/dist/decorators/job.decorators.js +97 -0
  21. package/dist/decorators/job.decorators.js.map +1 -0
  22. package/dist/decorators/legacy.decorators.d.ts +36 -0
  23. package/dist/decorators/legacy.decorators.d.ts.map +1 -0
  24. package/dist/decorators/legacy.decorators.js +61 -0
  25. package/dist/decorators/legacy.decorators.js.map +1 -0
  26. package/dist/decorators/metadata-readers.d.ts +31 -0
  27. package/dist/decorators/metadata-readers.d.ts.map +1 -0
  28. package/dist/decorators/metadata-readers.js +53 -0
  29. package/dist/decorators/metadata-readers.js.map +1 -0
  30. package/dist/decorators/registry.d.ts +2 -0
  31. package/dist/decorators/registry.d.ts.map +1 -0
  32. package/dist/decorators/registry.js +6 -0
  33. package/dist/decorators/registry.js.map +1 -0
  34. package/dist/decorators/scaler.decorators.d.ts +65 -0
  35. package/dist/decorators/scaler.decorators.d.ts.map +1 -0
  36. package/dist/decorators/scaler.decorators.js +103 -0
  37. package/dist/decorators/scaler.decorators.js.map +1 -0
  38. package/dist/decorators/type-guards.d.ts +18 -0
  39. package/dist/decorators/type-guards.d.ts.map +1 -0
  40. package/dist/decorators/type-guards.js +32 -0
  41. package/dist/decorators/type-guards.js.map +1 -0
  42. package/dist/decorators/utils.d.ts +20 -0
  43. package/dist/decorators/utils.d.ts.map +1 -0
  44. package/dist/decorators/utils.js +98 -0
  45. package/dist/decorators/utils.js.map +1 -0
  46. package/dist/decorators/worker.decorators.d.ts +58 -0
  47. package/dist/decorators/worker.decorators.d.ts.map +1 -0
  48. package/dist/decorators/worker.decorators.js +92 -0
  49. package/dist/decorators/worker.decorators.js.map +1 -0
  50. package/dist/domain/interfaces/config.interfaces.d.ts +188 -0
  51. package/dist/domain/interfaces/config.interfaces.d.ts.map +1 -0
  52. package/dist/domain/interfaces/config.interfaces.js +3 -0
  53. package/dist/domain/interfaces/config.interfaces.js.map +1 -0
  54. package/dist/domain/interfaces/cqrs.interfaces.d.ts +7 -0
  55. package/dist/domain/interfaces/cqrs.interfaces.d.ts.map +1 -0
  56. package/dist/domain/interfaces/cqrs.interfaces.js +3 -0
  57. package/dist/domain/interfaces/cqrs.interfaces.js.map +1 -0
  58. package/dist/domain/interfaces/event.interfaces.d.ts +71 -0
  59. package/dist/domain/interfaces/event.interfaces.d.ts.map +1 -0
  60. package/dist/domain/interfaces/event.interfaces.js +3 -0
  61. package/dist/domain/interfaces/event.interfaces.js.map +1 -0
  62. package/dist/domain/interfaces/index-tracking.interfaces.d.ts +69 -0
  63. package/dist/domain/interfaces/index-tracking.interfaces.d.ts.map +1 -0
  64. package/dist/domain/interfaces/index-tracking.interfaces.js +3 -0
  65. package/dist/domain/interfaces/index-tracking.interfaces.js.map +1 -0
  66. package/dist/domain/interfaces/index.d.ts +12 -0
  67. package/dist/domain/interfaces/index.d.ts.map +1 -0
  68. package/dist/domain/interfaces/index.js +28 -0
  69. package/dist/domain/interfaces/index.js.map +1 -0
  70. package/dist/domain/interfaces/job.interfaces.d.ts +76 -0
  71. package/dist/domain/interfaces/job.interfaces.d.ts.map +1 -0
  72. package/dist/domain/interfaces/job.interfaces.js +3 -0
  73. package/dist/domain/interfaces/job.interfaces.js.map +1 -0
  74. package/dist/domain/interfaces/lock.interfaces.d.ts +54 -0
  75. package/dist/domain/interfaces/lock.interfaces.d.ts.map +1 -0
  76. package/dist/domain/interfaces/lock.interfaces.js +3 -0
  77. package/dist/domain/interfaces/lock.interfaces.js.map +1 -0
  78. package/dist/domain/interfaces/process.interfaces.d.ts +44 -0
  79. package/dist/domain/interfaces/process.interfaces.d.ts.map +1 -0
  80. package/dist/domain/interfaces/process.interfaces.js +3 -0
  81. package/dist/domain/interfaces/process.interfaces.js.map +1 -0
  82. package/dist/domain/interfaces/queue.interfaces.d.ts +46 -0
  83. package/dist/domain/interfaces/queue.interfaces.d.ts.map +1 -0
  84. package/dist/domain/interfaces/queue.interfaces.js +3 -0
  85. package/dist/domain/interfaces/queue.interfaces.js.map +1 -0
  86. package/dist/domain/interfaces/scaling.interfaces.d.ts +62 -0
  87. package/dist/domain/interfaces/scaling.interfaces.d.ts.map +1 -0
  88. package/dist/domain/interfaces/scaling.interfaces.js +3 -0
  89. package/dist/domain/interfaces/scaling.interfaces.js.map +1 -0
  90. package/dist/domain/interfaces/utility.types.d.ts +15 -0
  91. package/dist/domain/interfaces/utility.types.d.ts.map +1 -0
  92. package/dist/domain/interfaces/utility.types.js +3 -0
  93. package/dist/domain/interfaces/utility.types.js.map +1 -0
  94. package/dist/domain/interfaces/worker.interfaces.d.ts +120 -0
  95. package/dist/domain/interfaces/worker.interfaces.d.ts.map +1 -0
  96. package/dist/domain/interfaces/worker.interfaces.js +3 -0
  97. package/dist/domain/interfaces/worker.interfaces.js.map +1 -0
  98. package/dist/module/atomic-queues.module.d.ts.map +1 -1
  99. package/dist/module/atomic-queues.module.js +4 -0
  100. package/dist/module/atomic-queues.module.js.map +1 -1
  101. package/dist/services/cron-manager/cron-manager.service.d.ts +5 -4
  102. package/dist/services/cron-manager/cron-manager.service.d.ts.map +1 -1
  103. package/dist/services/cron-manager/cron-manager.service.js +26 -57
  104. package/dist/services/cron-manager/cron-manager.service.js.map +1 -1
  105. package/dist/services/index-manager/index-manager.service.d.ts +0 -4
  106. package/dist/services/index-manager/index-manager.service.d.ts.map +1 -1
  107. package/dist/services/index-manager/index-manager.service.js +4 -16
  108. package/dist/services/index-manager/index-manager.service.js.map +1 -1
  109. package/dist/services/processor-discovery/decorator-discovery.service.d.ts +40 -0
  110. package/dist/services/processor-discovery/decorator-discovery.service.d.ts.map +1 -0
  111. package/dist/services/processor-discovery/decorator-discovery.service.js +191 -0
  112. package/dist/services/processor-discovery/decorator-discovery.service.js.map +1 -0
  113. package/dist/services/processor-discovery/index.d.ts +4 -0
  114. package/dist/services/processor-discovery/index.d.ts.map +1 -1
  115. package/dist/services/processor-discovery/index.js +4 -0
  116. package/dist/services/processor-discovery/index.js.map +1 -1
  117. package/dist/services/processor-discovery/processor-discovery.service.d.ts +28 -156
  118. package/dist/services/processor-discovery/processor-discovery.service.d.ts.map +1 -1
  119. package/dist/services/processor-discovery/processor-discovery.service.js +121 -592
  120. package/dist/services/processor-discovery/processor-discovery.service.js.map +1 -1
  121. package/dist/services/processor-discovery/processor-registry.d.ts +58 -0
  122. package/dist/services/processor-discovery/processor-registry.d.ts.map +1 -0
  123. package/dist/services/processor-discovery/processor-registry.js +74 -0
  124. package/dist/services/processor-discovery/processor-registry.js.map +1 -0
  125. package/dist/services/processor-discovery/scaling-registration.service.d.ts +60 -0
  126. package/dist/services/processor-discovery/scaling-registration.service.d.ts.map +1 -0
  127. package/dist/services/processor-discovery/scaling-registration.service.js +261 -0
  128. package/dist/services/processor-discovery/scaling-registration.service.js.map +1 -0
  129. package/dist/services/processor-discovery/worker-factory.service.d.ts +54 -0
  130. package/dist/services/processor-discovery/worker-factory.service.d.ts.map +1 -0
  131. package/dist/services/processor-discovery/worker-factory.service.js +185 -0
  132. package/dist/services/processor-discovery/worker-factory.service.js.map +1 -0
  133. package/dist/services/queue-bus/entity-target.d.ts +58 -0
  134. package/dist/services/queue-bus/entity-target.d.ts.map +1 -0
  135. package/dist/services/queue-bus/entity-target.js +109 -0
  136. package/dist/services/queue-bus/entity-target.js.map +1 -0
  137. package/dist/services/queue-bus/index.d.ts +4 -0
  138. package/dist/services/queue-bus/index.d.ts.map +1 -1
  139. package/dist/services/queue-bus/index.js +4 -0
  140. package/dist/services/queue-bus/index.js.map +1 -1
  141. package/dist/services/queue-bus/queue-bus.service.d.ts +9 -145
  142. package/dist/services/queue-bus/queue-bus.service.d.ts.map +1 -1
  143. package/dist/services/queue-bus/queue-bus.service.js +23 -311
  144. package/dist/services/queue-bus/queue-bus.service.js.map +1 -1
  145. package/dist/services/queue-bus/queue-bus.types.d.ts +40 -0
  146. package/dist/services/queue-bus/queue-bus.types.d.ts.map +1 -0
  147. package/dist/services/queue-bus/queue-bus.types.js +3 -0
  148. package/dist/services/queue-bus/queue-bus.types.js.map +1 -0
  149. package/dist/services/queue-bus/queue-bus.utils.d.ts +34 -0
  150. package/dist/services/queue-bus/queue-bus.utils.d.ts.map +1 -0
  151. package/dist/services/queue-bus/queue-bus.utils.js +82 -0
  152. package/dist/services/queue-bus/queue-bus.utils.js.map +1 -0
  153. package/dist/services/queue-bus/queue-target.d.ts +61 -0
  154. package/dist/services/queue-bus/queue-target.d.ts.map +1 -0
  155. package/dist/services/queue-bus/queue-target.js +123 -0
  156. package/dist/services/queue-bus/queue-target.js.map +1 -0
  157. package/dist/services/queue-events-manager/queue-events-manager.service.d.ts +0 -4
  158. package/dist/services/queue-events-manager/queue-events-manager.service.d.ts.map +1 -1
  159. package/dist/services/queue-events-manager/queue-events-manager.service.js +3 -15
  160. package/dist/services/queue-events-manager/queue-events-manager.service.js.map +1 -1
  161. package/dist/services/resource-lock/resource-lock.service.d.ts +0 -4
  162. package/dist/services/resource-lock/resource-lock.service.d.ts.map +1 -1
  163. package/dist/services/resource-lock/resource-lock.service.js +4 -16
  164. package/dist/services/resource-lock/resource-lock.service.js.map +1 -1
  165. package/dist/services/service-queue/index.d.ts +1 -0
  166. package/dist/services/service-queue/index.d.ts.map +1 -1
  167. package/dist/services/service-queue/index.js +1 -0
  168. package/dist/services/service-queue/index.js.map +1 -1
  169. package/dist/services/service-queue/service-queue.service.d.ts +2 -35
  170. package/dist/services/service-queue/service-queue.service.d.ts.map +1 -1
  171. package/dist/services/service-queue/service-queue.service.js +17 -49
  172. package/dist/services/service-queue/service-queue.service.js.map +1 -1
  173. package/dist/services/service-queue/service-queue.types.d.ts +32 -0
  174. package/dist/services/service-queue/service-queue.types.d.ts.map +1 -0
  175. package/dist/services/service-queue/service-queue.types.js +27 -0
  176. package/dist/services/service-queue/service-queue.types.js.map +1 -0
  177. package/dist/services/worker-manager/worker-manager.service.d.ts.map +1 -1
  178. package/dist/services/worker-manager/worker-manager.service.js +2 -1
  179. package/dist/services/worker-manager/worker-manager.service.js.map +1 -1
  180. package/dist/utils/async.utils.d.ts +51 -0
  181. package/dist/utils/async.utils.d.ts.map +1 -0
  182. package/dist/utils/async.utils.js +87 -0
  183. package/dist/utils/async.utils.js.map +1 -0
  184. package/dist/utils/helpers.d.ts +4 -123
  185. package/dist/utils/helpers.d.ts.map +1 -1
  186. package/dist/utils/helpers.js +18 -226
  187. package/dist/utils/helpers.js.map +1 -1
  188. package/dist/utils/index.d.ts +1 -0
  189. package/dist/utils/index.d.ts.map +1 -1
  190. package/dist/utils/index.js +1 -0
  191. package/dist/utils/index.js.map +1 -1
  192. package/dist/utils/job.utils.d.ts +50 -0
  193. package/dist/utils/job.utils.d.ts.map +1 -0
  194. package/dist/utils/job.utils.js +89 -0
  195. package/dist/utils/job.utils.js.map +1 -0
  196. package/dist/utils/naming.utils.d.ts +21 -0
  197. package/dist/utils/naming.utils.d.ts.map +1 -0
  198. package/dist/utils/naming.utils.js +38 -0
  199. package/dist/utils/naming.utils.js.map +1 -0
  200. package/dist/utils/rate-limit.utils.d.ts +9 -0
  201. package/dist/utils/rate-limit.utils.d.ts.map +1 -0
  202. package/dist/utils/rate-limit.utils.js +30 -0
  203. package/dist/utils/rate-limit.utils.js.map +1 -0
  204. package/dist/utils/redis.utils.d.ts +3 -0
  205. package/dist/utils/redis.utils.d.ts.map +1 -0
  206. package/dist/utils/redis.utils.js +14 -0
  207. package/dist/utils/redis.utils.js.map +1 -0
  208. package/package.json +17 -17
  209. package/dist/decorators/decorators.d.ts +0 -489
  210. package/dist/decorators/decorators.d.ts.map +0 -1
  211. package/dist/decorators/decorators.js +0 -680
  212. package/dist/decorators/decorators.js.map +0 -1
  213. package/dist/domain/interfaces.d.ts +0 -748
  214. package/dist/domain/interfaces.d.ts.map +0 -1
  215. package/dist/domain/interfaces.js +0 -19
  216. package/dist/domain/interfaces.js.map +0 -1
package/README.md CHANGED
@@ -27,11 +27,10 @@ Distributed locks (Redlock, advisory locks, optimistic locking) all share the sa
27
27
  |---|---|---|
28
28
  | **Architecture** | Distributed mutex (quorum-based) | Per-entity queue (sequential) |
29
29
  | **Under contention** | Degrades — retry storms, backoff delays | **Constant** — jobs queue up, execute instantly |
30
- | **Per-entity throughput** | ~20-50 ops/s (heavy contention) | **~200-300 ops/s** (queue-bound, no contention) |
31
30
  | **Failure mode** | Silent double-execution (clock drift) | Job stuck in queue (visible, retryable) |
32
31
  | **Split-brain risk** | Yes (timing assumptions) | **Impossible** (serial queue) |
33
- | **Warm-path overhead** | 5-7ms per op (acquire + release) | **0ms** (in-memory hot cache) |
34
- | **Cold-start** | None | ~2-3ms one-time per entity |
32
+ | **Warm-path overhead** | Acquire + release per op | **0 Redis calls** (in-memory hot cache) |
33
+ | **Cold-start** | None | One-time per entity |
35
34
  | **Multi-pod scaling** | Contention increases with pods | **Throughput increases with pods** |
36
35
 
37
36
  ---
@@ -105,17 +104,12 @@ atomic-queues routes operations through per-entity queues. Same entity → same
105
104
  ## Installation
106
105
 
107
106
  ```bash
108
- # npm
109
- npm install atomic-queues bullmq ioredis
110
-
111
- # pnpm
112
- pnpm add atomic-queues bullmq ioredis
113
-
114
- # yarn
115
- yarn add atomic-queues bullmq ioredis
107
+ npm install atomic-queues
116
108
  ```
117
109
 
118
- **Peer dependencies:** NestJS 10+, `@nestjs/cqrs` (optionalfor auto-routing commands/queries)
110
+ BullMQ, ioredis, and `@nestjs/bullmq` are bundled no extra installs needed.
111
+
112
+ **Peer dependencies** (provided by your NestJS app): `@nestjs/common` 10+, `@nestjs/core` 10+, `reflect-metadata`, `rxjs` 7+. Optional: `@nestjs/cqrs` (for auto-routing commands/queries).
119
113
 
120
114
  ---
121
115
 
@@ -150,6 +144,28 @@ export class AppModule {}
150
144
 
151
145
  > **Tip:** The `entities` config is optional. Without it, default naming applies: `{keyPrefix}:{entityType}:{entityId}:queue`.
152
146
 
147
+ <details>
148
+ <summary><strong>Async configuration (ConfigService)</strong></summary>
149
+
150
+ ```typescript
151
+ AtomicQueuesModule.forRootAsync({
152
+ imports: [ConfigModule],
153
+ useFactory: (config: ConfigService) => ({
154
+ redis: { url: config.get('REDIS_URL') },
155
+ keyPrefix: 'myapp',
156
+ entities: {
157
+ account: {
158
+ queueName: (id) => `account-${id}-queue`,
159
+ workerName: (id) => `account-${id}-worker`,
160
+ },
161
+ },
162
+ }),
163
+ inject: [ConfigService],
164
+ }),
165
+ ```
166
+
167
+ </details>
168
+
153
169
  ### 2. Define Commands
154
170
 
155
171
  ```typescript
@@ -222,18 +238,34 @@ export class AccountService {
222
238
 
223
239
  ## Commands & Decorators
224
240
 
225
- ### `@QueueEntity(entityType)`
241
+ ### `@QueueEntity(entityType, entityIdProperty?)`
226
242
 
227
- Marks a command/query class for queue routing.
243
+ Marks a command/query class for queue routing. The optional second argument specifies which property holds the entity ID — this is the simplest approach when you don't want to decorate individual properties.
228
244
 
229
245
  ```typescript
246
+ // Option 1: Explicit property name (no @QueueEntityId needed)
247
+ @QueueEntity('account', 'accountId')
248
+ export class TransferCommand {
249
+ constructor(
250
+ public readonly accountId: string,
251
+ public readonly toAccountId: string,
252
+ public readonly amount: number,
253
+ ) {}
254
+ }
255
+
256
+ // Option 2: Rely on module-level defaultEntityId from entities config
230
257
  @QueueEntity('account')
231
- export class TransferCommand { ... }
258
+ export class DepositCommand {
259
+ constructor(
260
+ public readonly accountId: string, // Matched by entities.account.defaultEntityId
261
+ public readonly amount: number,
262
+ ) {}
263
+ }
232
264
  ```
233
265
 
234
266
  ### `@QueueEntityId()`
235
267
 
236
- Marks the property that contains the entity ID. One per class.
268
+ Marks the property that contains the entity ID. One per class. Use this when you need per-command control over which property is the entity ID, or when you can't use the two-argument `@QueueEntity` shorthand.
237
269
 
238
270
  ```typescript
239
271
  @QueueEntity('account')
@@ -246,6 +278,8 @@ export class TransferCommand {
246
278
  }
247
279
  ```
248
280
 
281
+ > **Entity ID resolution order:** `@QueueEntityId()` decorator > `@QueueEntity('type', 'prop')` second argument > `@WorkerProcessor({ defaultEntityId })` > `entities[type].defaultEntityId` in module config.
282
+
249
283
  ### `@WorkerProcessor(options)`
250
284
 
251
285
  Optional. Define a processor class for custom job handling on top of CQRS auto-routing.
@@ -302,7 +336,12 @@ AtomicQueuesModule.forRoot({
302
336
  workerName: (id) => `account-${id}-worker`,
303
337
  maxWorkersPerEntity: 1,
304
338
  idleTimeoutSeconds: 15,
339
+
340
+ // Fallback property name for entity ID extraction.
341
+ // Used when a command has no @QueueEntityId() decorator
342
+ // and no second argument to @QueueEntity().
305
343
  defaultEntityId: 'accountId',
344
+
306
345
  workerConfig: { // Override workerDefaults per entity
307
346
  concurrency: 1,
308
347
  lockDuration: 60000,
@@ -345,7 +384,7 @@ Workers in atomic-queues have a fully automated lifecycle, distributed across al
345
384
  └──────────────┘
346
385
  ```
347
386
 
348
- ### Hot Cache (v1.5.0+)
387
+ ### Hot Cache
349
388
 
350
389
  After a worker is confirmed alive, subsequent job arrivals for that entity hit an **in-memory cache** — zero Redis calls on the warm path. This eliminates the per-job Redis overhead that plagues lock-based approaches.
351
390
 
@@ -355,9 +394,9 @@ After a worker is confirmed alive, subsequent job arrivals for that entity hit a
355
394
  | **Warm** (cache miss) | 1 (`EXISTS`) | First time seeing entity |
356
395
  | **Cold** (no worker) | 1 (`SET NX`) | Worker needs creation |
357
396
 
358
- ### SpawnQueueService (v1.4.2+)
397
+ ### SpawnQueueService
359
398
 
360
- For multi-pod deployments, the `SpawnQueueService` distributes worker creation across all pods via a shared BullMQ spawn queue. In v1.5.0, the **direct local spawn** path bypasses this queue entirely — the pod that first sees a job for a new entity claims it with an atomic `SET NX` and spawns the worker locally, saving hundreds of milliseconds.
399
+ For multi-pod deployments, the `SpawnQueueService` distributes worker creation across all pods via a shared BullMQ spawn queue. The **direct local spawn** path bypasses this queue entirely — the pod that first sees a job for a new entity claims it with an atomic `SET NX` and spawns the worker locally.
361
400
 
362
401
  ---
363
402
 
@@ -526,21 +565,6 @@ export class AccountProcessor {
526
565
 
527
566
  ## Performance
528
567
 
529
- ### Throughput (measured — not estimated)
530
-
531
- Tested on a 5-pod Kubernetes cluster (OrbStack), 20 concurrent entities, 12,300 orders:
532
-
533
- | Metric | Result |
534
- |---|---|
535
- | **Phase 1** — 10,000 orders (50 waves × 200 concurrent) | 167 orders/sec |
536
- | **Phase 2** — 1,000 orders (workers still draining) | 140 orders/sec |
537
- | **Phase 4** — 1,000 orders (cold start from zero workers) | 176 orders/sec |
538
- | **Total deductions processed** | 104,004 |
539
- | **Stock drift** | **0** (all 20 entities) |
540
- | **Pod distribution** | 5/5 pods actively creating workers |
541
- | **Worker creates** | 120 |
542
- | **Idle closures** | 180 |
543
-
544
568
  ### Why it's fast
545
569
 
546
570
  1. **Zero contention** — no locks, no retries, no backoff. Jobs queue and execute.
@@ -553,7 +577,7 @@ Tested on a 5-pod Kubernetes cluster (OrbStack), 20 concurrent entities, 12,300
553
577
 
554
578
  | Use case | Recommendation |
555
579
  |---|---|
556
- | High-throughput entity operations (payments, inventory, game state) | **atomic-queues** |
580
+ | Per-entity operations that must be serialized (payments, inventory, game state) | **atomic-queues** |
557
581
  | Rare, low-frequency mutual exclusion (config updates, migrations) | Redlock / advisory locks |
558
582
  | Exactly-once semantics with audit trail | **atomic-queues** (BullMQ job IDs) |
559
583
  | Sub-millisecond synchronous response required | Redlock (synchronous acquire) |
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Metadata keys for decorators
3
+ */
4
+ export declare const ATOMIC_PROCESSOR_METADATA = "atomic:processor";
5
+ export declare const ENTITY_TYPE_METADATA = "atomic:entity-type";
6
+ export declare const ENTITY_ID_METADATA = "atomic:entity-id";
7
+ export declare const JOB_TYPE_METADATA = "atomic:job-type";
8
+ export declare const WORKER_PROCESSOR_METADATA = "atomic:worker-processor";
9
+ export declare const JOB_HANDLER_METADATA = "atomic:job-handler";
10
+ export declare const ENTITY_SCALER_METADATA = "atomic:entity-scaler";
11
+ export declare const GET_ACTIVE_ENTITIES_METADATA = "atomic:get-active-entities";
12
+ export declare const GET_DESIRED_WORKER_COUNT_METADATA = "atomic:get-desired-worker-count";
13
+ export declare const ON_SPAWN_WORKER_METADATA = "atomic:on-spawn-worker";
14
+ export declare const ON_TERMINATE_WORKER_METADATA = "atomic:on-terminate-worker";
15
+ export declare const JOB_COMMAND_METADATA = "atomic:job-command";
16
+ export declare const JOB_QUERY_METADATA = "atomic:job-query";
17
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/decorators/constants.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,eAAO,MAAM,yBAAyB,qBAAqB,CAAC;AAC5D,eAAO,MAAM,oBAAoB,uBAAuB,CAAC;AACzD,eAAO,MAAM,kBAAkB,qBAAqB,CAAC;AACrD,eAAO,MAAM,iBAAiB,oBAAoB,CAAC;AACnD,eAAO,MAAM,yBAAyB,4BAA4B,CAAC;AACnE,eAAO,MAAM,oBAAoB,uBAAuB,CAAC;AACzD,eAAO,MAAM,sBAAsB,yBAAyB,CAAC;AAC7D,eAAO,MAAM,4BAA4B,+BAA+B,CAAC;AACzE,eAAO,MAAM,iCAAiC,oCAAoC,CAAC;AACnF,eAAO,MAAM,wBAAwB,2BAA2B,CAAC;AACjE,eAAO,MAAM,4BAA4B,+BAA+B,CAAC;AACzE,eAAO,MAAM,oBAAoB,uBAAuB,CAAC;AACzD,eAAO,MAAM,kBAAkB,qBAAqB,CAAC"}
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ // =============================================================================
3
+ // METADATA KEYS
4
+ // =============================================================================
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.JOB_QUERY_METADATA = exports.JOB_COMMAND_METADATA = exports.ON_TERMINATE_WORKER_METADATA = exports.ON_SPAWN_WORKER_METADATA = exports.GET_DESIRED_WORKER_COUNT_METADATA = exports.GET_ACTIVE_ENTITIES_METADATA = exports.ENTITY_SCALER_METADATA = exports.JOB_HANDLER_METADATA = exports.WORKER_PROCESSOR_METADATA = exports.JOB_TYPE_METADATA = exports.ENTITY_ID_METADATA = exports.ENTITY_TYPE_METADATA = exports.ATOMIC_PROCESSOR_METADATA = void 0;
7
+ /**
8
+ * Metadata keys for decorators
9
+ */
10
+ exports.ATOMIC_PROCESSOR_METADATA = 'atomic:processor';
11
+ exports.ENTITY_TYPE_METADATA = 'atomic:entity-type';
12
+ exports.ENTITY_ID_METADATA = 'atomic:entity-id';
13
+ exports.JOB_TYPE_METADATA = 'atomic:job-type';
14
+ exports.WORKER_PROCESSOR_METADATA = 'atomic:worker-processor';
15
+ exports.JOB_HANDLER_METADATA = 'atomic:job-handler';
16
+ exports.ENTITY_SCALER_METADATA = 'atomic:entity-scaler';
17
+ exports.GET_ACTIVE_ENTITIES_METADATA = 'atomic:get-active-entities';
18
+ exports.GET_DESIRED_WORKER_COUNT_METADATA = 'atomic:get-desired-worker-count';
19
+ exports.ON_SPAWN_WORKER_METADATA = 'atomic:on-spawn-worker';
20
+ exports.ON_TERMINATE_WORKER_METADATA = 'atomic:on-terminate-worker';
21
+ exports.JOB_COMMAND_METADATA = 'atomic:job-command';
22
+ exports.JOB_QUERY_METADATA = 'atomic:job-query';
23
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/decorators/constants.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,gBAAgB;AAChB,gFAAgF;;;AAEhF;;GAEG;AACU,QAAA,yBAAyB,GAAG,kBAAkB,CAAC;AAC/C,QAAA,oBAAoB,GAAG,oBAAoB,CAAC;AAC5C,QAAA,kBAAkB,GAAG,kBAAkB,CAAC;AACxC,QAAA,iBAAiB,GAAG,iBAAiB,CAAC;AACtC,QAAA,yBAAyB,GAAG,yBAAyB,CAAC;AACtD,QAAA,oBAAoB,GAAG,oBAAoB,CAAC;AAC5C,QAAA,sBAAsB,GAAG,sBAAsB,CAAC;AAChD,QAAA,4BAA4B,GAAG,4BAA4B,CAAC;AAC5D,QAAA,iCAAiC,GAAG,iCAAiC,CAAC;AACtE,QAAA,wBAAwB,GAAG,wBAAwB,CAAC;AACpD,QAAA,4BAA4B,GAAG,4BAA4B,CAAC;AAC5D,QAAA,oBAAoB,GAAG,oBAAoB,CAAC;AAC5C,QAAA,kBAAkB,GAAG,kBAAkB,CAAC"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * @EntityType decorator
3
+ *
4
+ * Marks a command/query class with its entity type for automatic routing.
5
+ * When present, queueBus.enqueue(cmd) can auto-route without forEntity().
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * @EntityType('account')
10
+ * export class WithdrawCommand {
11
+ * @QueueEntityId()
12
+ * public readonly accountId: string;
13
+ * public readonly amount: number;
14
+ * }
15
+ *
16
+ * // Can now use direct enqueue:
17
+ * await queueBus.enqueue(new WithdrawCommand(accountId, amount));
18
+ * ```
19
+ */
20
+ export declare function EntityType(entityType: string): ClassDecorator;
21
+ /**
22
+ * @QueueEntityId decorator
23
+ *
24
+ * Marks a property OR constructor parameter as the entity ID for queue routing.
25
+ * Only ONE @QueueEntityId() allowed per class (enforced at decoration time).
26
+ * Overrides module-level defaultEntityId configuration.
27
+ *
28
+ * @example Property decorator:
29
+ * ```typescript
30
+ * export class TransferCommand {
31
+ * @QueueEntityId()
32
+ * public readonly sourceAccountId: string;
33
+ * public readonly amount: number;
34
+ * }
35
+ * ```
36
+ *
37
+ * @example Parameter decorator (recommended):
38
+ * ```typescript
39
+ * @QueueEntity('account')
40
+ * export class TransferCommand {
41
+ * constructor(
42
+ * @QueueEntityId() public readonly sourceAccountId: string,
43
+ * public readonly amount: number,
44
+ * ) {}
45
+ * }
46
+ * ```
47
+ */
48
+ export declare function QueueEntityId(): PropertyDecorator & ParameterDecorator;
49
+ /**
50
+ * @deprecated Use @QueueEntityId() instead. This alias is provided for backwards compatibility.
51
+ */
52
+ export declare const EntityId: typeof QueueEntityId;
53
+ /**
54
+ * @QueueEntity decorator
55
+ *
56
+ * Single decorator that combines @EntityType and @QueueEntityId into one.
57
+ * This is the recommended way to mark commands/queries for queue routing.
58
+ *
59
+ * @param entityType - The entity type for routing (e.g., 'table', 'account')
60
+ * @param entityIdProperty - Optional property name containing the entity ID.
61
+ * If omitted, uses module-level defaultEntityId from entities config.
62
+ *
63
+ * @example
64
+ * // With explicit property name:
65
+ * @QueueEntity('table', 'tableId')
66
+ * export class MakeBetCommand {
67
+ * constructor(
68
+ * public readonly tableId: string, // <- unchanged!
69
+ * public readonly amount: number,
70
+ * ) {}
71
+ * }
72
+ *
73
+ * @example
74
+ * // Using module default (entities config has defaultEntityId: 'tableId'):
75
+ * @QueueEntity('table')
76
+ * export class DealCommand {
77
+ * constructor(
78
+ * public readonly tableId: string,
79
+ * public readonly card: string,
80
+ * ) {}
81
+ * }
82
+ *
83
+ * @example
84
+ * // Then just enqueue directly:
85
+ * await queueBus.enqueue(new MakeBetCommand(tableId, 100));
86
+ */
87
+ export declare function QueueEntity(entityType: string, entityIdProperty?: string): ClassDecorator;
88
+ //# sourceMappingURL=entity.decorators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity.decorators.d.ts","sourceRoot":"","sources":["../../src/decorators/entity.decorators.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,CAI7D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,aAAa,IAAI,iBAAiB,GAAG,kBAAkB,CAqDtE;AAED;;GAEG;AACH,eAAO,MAAM,QAAQ,sBAAgB,CAAC;AAMtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,cAAc,CAUzF"}
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EntityId = void 0;
4
+ exports.EntityType = EntityType;
5
+ exports.QueueEntityId = QueueEntityId;
6
+ exports.QueueEntity = QueueEntity;
7
+ const constants_1 = require("./constants");
8
+ const registry_1 = require("./registry");
9
+ const utils_1 = require("./utils");
10
+ /**
11
+ * @EntityType decorator
12
+ *
13
+ * Marks a command/query class with its entity type for automatic routing.
14
+ * When present, queueBus.enqueue(cmd) can auto-route without forEntity().
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * @EntityType('account')
19
+ * export class WithdrawCommand {
20
+ * @QueueEntityId()
21
+ * public readonly accountId: string;
22
+ * public readonly amount: number;
23
+ * }
24
+ *
25
+ * // Can now use direct enqueue:
26
+ * await queueBus.enqueue(new WithdrawCommand(accountId, amount));
27
+ * ```
28
+ */
29
+ function EntityType(entityType) {
30
+ return (target) => {
31
+ Reflect.defineMetadata(constants_1.ENTITY_TYPE_METADATA, entityType, target);
32
+ };
33
+ }
34
+ /**
35
+ * @QueueEntityId decorator
36
+ *
37
+ * Marks a property OR constructor parameter as the entity ID for queue routing.
38
+ * Only ONE @QueueEntityId() allowed per class (enforced at decoration time).
39
+ * Overrides module-level defaultEntityId configuration.
40
+ *
41
+ * @example Property decorator:
42
+ * ```typescript
43
+ * export class TransferCommand {
44
+ * @QueueEntityId()
45
+ * public readonly sourceAccountId: string;
46
+ * public readonly amount: number;
47
+ * }
48
+ * ```
49
+ *
50
+ * @example Parameter decorator (recommended):
51
+ * ```typescript
52
+ * @QueueEntity('account')
53
+ * export class TransferCommand {
54
+ * constructor(
55
+ * @QueueEntityId() public readonly sourceAccountId: string,
56
+ * public readonly amount: number,
57
+ * ) {}
58
+ * }
59
+ * ```
60
+ */
61
+ function QueueEntityId() {
62
+ return (target, propertyKey, parameterIndex) => {
63
+ // Parameter decorator case (on constructor param)
64
+ if (typeof parameterIndex === 'number') {
65
+ const constructor = target;
66
+ const className = constructor.name;
67
+ // Extract parameter name from constructor
68
+ const paramName = (0, utils_1.getConstructorParamName)(constructor, parameterIndex);
69
+ if (!paramName) {
70
+ throw new Error(`Cannot determine parameter name at index ${parameterIndex} in ${className}. ` +
71
+ `Ensure you're using 'public readonly paramName' syntax.`);
72
+ }
73
+ // Check for duplicate
74
+ const existing = registry_1.queueEntityIdRegistry.get(constructor);
75
+ if (existing) {
76
+ throw new Error(`Multiple @QueueEntityId() decorators on ${className}. ` +
77
+ `Found on '${existing}' and '${paramName}'. ` +
78
+ `Only one parameter/property can be the entity ID.`);
79
+ }
80
+ registry_1.queueEntityIdRegistry.set(constructor, paramName);
81
+ Reflect.defineMetadata(constants_1.ENTITY_ID_METADATA, paramName, constructor);
82
+ return;
83
+ }
84
+ // Property decorator case (on class property)
85
+ const constructor = target.constructor;
86
+ const className = constructor.name;
87
+ const propName = String(propertyKey);
88
+ // Check for duplicate @QueueEntityId on same class
89
+ const existing = registry_1.queueEntityIdRegistry.get(constructor);
90
+ if (existing) {
91
+ throw new Error(`Multiple @QueueEntityId() decorators on ${className}. ` +
92
+ `Found on '${existing}' and '${propName}'. ` +
93
+ `Only one property can be the entity ID.`);
94
+ }
95
+ registry_1.queueEntityIdRegistry.set(constructor, propName);
96
+ Reflect.defineMetadata(constants_1.ENTITY_ID_METADATA, propName, constructor);
97
+ };
98
+ }
99
+ /**
100
+ * @deprecated Use @QueueEntityId() instead. This alias is provided for backwards compatibility.
101
+ */
102
+ exports.EntityId = QueueEntityId;
103
+ // =============================================================================
104
+ // NEW COMBINED DECORATOR - Less Invasive
105
+ // =============================================================================
106
+ /**
107
+ * @QueueEntity decorator
108
+ *
109
+ * Single decorator that combines @EntityType and @QueueEntityId into one.
110
+ * This is the recommended way to mark commands/queries for queue routing.
111
+ *
112
+ * @param entityType - The entity type for routing (e.g., 'table', 'account')
113
+ * @param entityIdProperty - Optional property name containing the entity ID.
114
+ * If omitted, uses module-level defaultEntityId from entities config.
115
+ *
116
+ * @example
117
+ * // With explicit property name:
118
+ * @QueueEntity('table', 'tableId')
119
+ * export class MakeBetCommand {
120
+ * constructor(
121
+ * public readonly tableId: string, // <- unchanged!
122
+ * public readonly amount: number,
123
+ * ) {}
124
+ * }
125
+ *
126
+ * @example
127
+ * // Using module default (entities config has defaultEntityId: 'tableId'):
128
+ * @QueueEntity('table')
129
+ * export class DealCommand {
130
+ * constructor(
131
+ * public readonly tableId: string,
132
+ * public readonly card: string,
133
+ * ) {}
134
+ * }
135
+ *
136
+ * @example
137
+ * // Then just enqueue directly:
138
+ * await queueBus.enqueue(new MakeBetCommand(tableId, 100));
139
+ */
140
+ function QueueEntity(entityType, entityIdProperty) {
141
+ return (target) => {
142
+ // Always set entity type
143
+ Reflect.defineMetadata(constants_1.ENTITY_TYPE_METADATA, entityType, target);
144
+ // Set entity ID property if provided (otherwise falls back to module config)
145
+ if (entityIdProperty) {
146
+ Reflect.defineMetadata(constants_1.ENTITY_ID_METADATA, entityIdProperty, target);
147
+ }
148
+ };
149
+ }
150
+ //# sourceMappingURL=entity.decorators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity.decorators.js","sourceRoot":"","sources":["../../src/decorators/entity.decorators.ts"],"names":[],"mappings":";;;AAuBA,gCAIC;AA6BD,sCAqDC;AA6CD,kCAUC;AApKD,2CAAuE;AACvE,yCAAmD;AACnD,mCAAkD;AAElD;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,UAAU,CAAC,UAAkB;IAC3C,OAAO,CAAC,MAAgB,EAAE,EAAE;QAC1B,OAAO,CAAC,cAAc,CAAC,gCAAoB,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IACnE,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,SAAgB,aAAa;IAC3B,OAAO,CACL,MAAc,EACd,WAAwC,EACxC,cAAuB,EACvB,EAAE;QACF,kDAAkD;QAClD,IAAI,OAAO,cAAc,KAAK,QAAQ,EAAE,CAAC;YACvC,MAAM,WAAW,GAAG,MAAkB,CAAC;YACvC,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC;YAEnC,0CAA0C;YAC1C,MAAM,SAAS,GAAG,IAAA,+BAAuB,EAAC,WAAW,EAAE,cAAc,CAAC,CAAC;YACvE,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CACb,4CAA4C,cAAc,OAAO,SAAS,IAAI;oBAC9E,yDAAyD,CAC1D,CAAC;YACJ,CAAC;YAED,sBAAsB;YACtB,MAAM,QAAQ,GAAG,gCAAqB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACxD,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CACb,2CAA2C,SAAS,IAAI;oBACxD,aAAa,QAAQ,UAAU,SAAS,KAAK;oBAC7C,mDAAmD,CACpD,CAAC;YACJ,CAAC;YAED,gCAAqB,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;YAClD,OAAO,CAAC,cAAc,CAAC,8BAAkB,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;YACnE,OAAO;QACT,CAAC;QAED,8CAA8C;QAC9C,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;QACvC,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC;QACnC,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;QAErC,mDAAmD;QACnD,MAAM,QAAQ,GAAG,gCAAqB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACxD,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,2CAA2C,SAAS,IAAI;gBACxD,aAAa,QAAQ,UAAU,QAAQ,KAAK;gBAC5C,yCAAyC,CAC1C,CAAC;QACJ,CAAC;QAED,gCAAqB,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QACjD,OAAO,CAAC,cAAc,CAAC,8BAAkB,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;IACpE,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACU,QAAA,QAAQ,GAAG,aAAa,CAAC;AAEtC,gFAAgF;AAChF,yCAAyC;AACzC,gFAAgF;AAEhF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,SAAgB,WAAW,CAAC,UAAkB,EAAE,gBAAyB;IACvE,OAAO,CAAC,MAAgB,EAAE,EAAE;QAC1B,yBAAyB;QACzB,OAAO,CAAC,cAAc,CAAC,gCAAoB,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;QAEjE,6EAA6E;QAC7E,IAAI,gBAAgB,EAAE,CAAC;YACrB,OAAO,CAAC,cAAc,CAAC,8BAAkB,EAAE,gBAAgB,EAAE,MAAM,CAAC,CAAC;QACvE,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -1,2 +1,10 @@
1
- export * from './decorators';
1
+ export * from './constants';
2
+ export * from './interfaces';
3
+ export * from './entity.decorators';
4
+ export * from './worker.decorators';
5
+ export * from './scaler.decorators';
6
+ export * from './job.decorators';
7
+ export * from './legacy.decorators';
8
+ export * from './metadata-readers';
9
+ export * from './type-guards';
2
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/decorators/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/decorators/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC"}
@@ -14,5 +14,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./decorators"), exports);
17
+ __exportStar(require("./constants"), exports);
18
+ __exportStar(require("./interfaces"), exports);
19
+ __exportStar(require("./entity.decorators"), exports);
20
+ __exportStar(require("./worker.decorators"), exports);
21
+ __exportStar(require("./scaler.decorators"), exports);
22
+ __exportStar(require("./job.decorators"), exports);
23
+ __exportStar(require("./legacy.decorators"), exports);
24
+ __exportStar(require("./metadata-readers"), exports);
25
+ __exportStar(require("./type-guards"), exports);
18
26
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/decorators/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA6B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/decorators/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B;AAC5B,+CAA6B;AAC7B,sDAAoC;AACpC,sDAAoC;AACpC,sDAAoC;AACpC,mDAAiC;AACjC,sDAAoC;AACpC,qDAAmC;AACnC,gDAA8B"}
@@ -0,0 +1,130 @@
1
+ import { Type } from '@nestjs/common';
2
+ import { IWorkerConfig } from '../domain';
3
+ /**
4
+ * Options for @WorkerProcessor decorator
5
+ */
6
+ export interface WorkerProcessorOptions {
7
+ /** Entity type this processor handles (e.g., 'table', 'user') */
8
+ entityType: string;
9
+ /** Default property name for entity ID extraction (optional) */
10
+ defaultEntityId?: string;
11
+ /** Function to generate queue name from entityId */
12
+ queueName?: string | ((entityId: string) => string);
13
+ /** Function to generate worker name from entityId */
14
+ workerName?: string | ((entityId: string) => string);
15
+ /** Worker configuration */
16
+ workerConfig?: IWorkerConfig;
17
+ /**
18
+ * If true, workerConfig fully replaces module workerDefaults (no merge).
19
+ * If false (default), workerConfig is merged with workerDefaults.
20
+ */
21
+ overrideDefaults?: boolean;
22
+ /**
23
+ * Maximum workers per entity (default: 1).
24
+ * Used when operating without an EntityScaler.
25
+ */
26
+ maxWorkersPerEntity?: number;
27
+ /**
28
+ * Idle timeout in seconds before a worker is considered idle and can be terminated.
29
+ * Workers self-report idle time via heartbeat. Default: 15 seconds.
30
+ * Used when operating without an EntityScaler.
31
+ */
32
+ idleTimeoutSeconds?: number;
33
+ /**
34
+ * If true, workers are automatically spawned when jobs arrive (scalerless mode).
35
+ * When enabled, no @EntityScaler is required - workers spawn on job arrival
36
+ * and terminate when idle. Default: true if no EntityScaler is registered.
37
+ */
38
+ autoSpawn?: boolean;
39
+ }
40
+ /**
41
+ * Options for @EntityScaler decorator
42
+ */
43
+ export interface EntityScalerOptions {
44
+ /** Entity type this scaler handles */
45
+ entityType: string;
46
+ /** Maximum workers per entity */
47
+ maxWorkersPerEntity?: number;
48
+ /**
49
+ * Idle timeout in seconds before a worker is considered idle and can be terminated.
50
+ * Workers self-report idle time via heartbeat. Default: 15 seconds.
51
+ */
52
+ idleTimeoutSeconds?: number;
53
+ }
54
+ /**
55
+ * Options for @JobCommand decorator
56
+ */
57
+ export interface JobCommandOptions {
58
+ /** Job name (defaults to kebab-case of class name without 'Command' suffix) */
59
+ name?: string;
60
+ /** Entity type this command belongs to (optional, for scoped routing) */
61
+ entityType?: string;
62
+ /** Which constructor parameter is the entityId (default: 0 = first param) */
63
+ entityIdParam?: number | string;
64
+ }
65
+ /**
66
+ * Options for @JobQuery decorator
67
+ */
68
+ export interface JobQueryOptions {
69
+ /** Job name (defaults to kebab-case of class name without 'Query' suffix) */
70
+ name?: string;
71
+ /** Entity type this query belongs to (optional, for scoped routing) */
72
+ entityType?: string;
73
+ /** Which constructor parameter is the entityId (default: 0 = first param) */
74
+ entityIdParam?: number | string;
75
+ }
76
+ /**
77
+ * Stored job command metadata
78
+ */
79
+ export interface JobCommandMetadata {
80
+ jobName: string;
81
+ entityType?: string;
82
+ entityIdParam: number | string;
83
+ targetClass: Function;
84
+ paramNames: string[];
85
+ }
86
+ /**
87
+ * Stored job query metadata
88
+ */
89
+ export interface JobQueryMetadata {
90
+ jobName: string;
91
+ entityType?: string;
92
+ entityIdParam: number | string;
93
+ targetClass: Function;
94
+ paramNames: string[];
95
+ }
96
+ /**
97
+ * Stored job handler metadata
98
+ */
99
+ export interface JobHandlerMetadata {
100
+ jobName: string;
101
+ methodName: string;
102
+ isWildcard: boolean;
103
+ }
104
+ /**
105
+ * Stored worker processor metadata
106
+ */
107
+ export interface WorkerProcessorMetadata {
108
+ entityType: string;
109
+ defaultEntityId?: string;
110
+ queueNameFn: (entityId: string) => string;
111
+ workerNameFn: (entityId: string) => string;
112
+ workerConfig: IWorkerConfig;
113
+ overrideDefaults: boolean;
114
+ targetClass: Type<any>;
115
+ jobHandlers: Map<string, JobHandlerMetadata>;
116
+ wildcardHandler?: JobHandlerMetadata;
117
+ }
118
+ /**
119
+ * Stored entity scaler metadata
120
+ */
121
+ export interface EntityScalerMetadata {
122
+ entityType: string;
123
+ maxWorkersPerEntity: number;
124
+ targetClass: Type<any>;
125
+ getActiveEntitiesMethod?: string;
126
+ getDesiredWorkerCountMethod?: string;
127
+ onSpawnWorkerMethod?: string;
128
+ onTerminateWorkerMethod?: string;
129
+ }
130
+ //# sourceMappingURL=interfaces.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/decorators/interfaces.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=interfaces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../src/decorators/interfaces.ts"],"names":[],"mappings":""}