atomic-queues 1.0.13

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 (110) hide show
  1. package/README.md +686 -0
  2. package/dist/decorators/decorators.d.ts +67 -0
  3. package/dist/decorators/decorators.d.ts.map +1 -0
  4. package/dist/decorators/decorators.js +91 -0
  5. package/dist/decorators/decorators.js.map +1 -0
  6. package/dist/decorators/index.d.ts +2 -0
  7. package/dist/decorators/index.d.ts.map +1 -0
  8. package/dist/decorators/index.js +18 -0
  9. package/dist/decorators/index.js.map +1 -0
  10. package/dist/domain/index.d.ts +5 -0
  11. package/dist/domain/index.d.ts.map +1 -0
  12. package/dist/domain/index.js +21 -0
  13. package/dist/domain/index.js.map +1 -0
  14. package/dist/domain/interfaces.d.ts +614 -0
  15. package/dist/domain/interfaces.d.ts.map +1 -0
  16. package/dist/domain/interfaces.js +19 -0
  17. package/dist/domain/interfaces.js.map +1 -0
  18. package/dist/index.d.ts +40 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +61 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/module/atomic-queues.module.d.ts +97 -0
  23. package/dist/module/atomic-queues.module.d.ts.map +1 -0
  24. package/dist/module/atomic-queues.module.js +197 -0
  25. package/dist/module/atomic-queues.module.js.map +1 -0
  26. package/dist/module/index.d.ts +2 -0
  27. package/dist/module/index.d.ts.map +1 -0
  28. package/dist/module/index.js +18 -0
  29. package/dist/module/index.js.map +1 -0
  30. package/dist/services/constants.d.ts +10 -0
  31. package/dist/services/constants.d.ts.map +1 -0
  32. package/dist/services/constants.js +13 -0
  33. package/dist/services/constants.js.map +1 -0
  34. package/dist/services/cron-manager/cron-manager.service.d.ts +188 -0
  35. package/dist/services/cron-manager/cron-manager.service.d.ts.map +1 -0
  36. package/dist/services/cron-manager/cron-manager.service.js +534 -0
  37. package/dist/services/cron-manager/cron-manager.service.js.map +1 -0
  38. package/dist/services/cron-manager/index.d.ts +2 -0
  39. package/dist/services/cron-manager/index.d.ts.map +1 -0
  40. package/dist/services/cron-manager/index.js +18 -0
  41. package/dist/services/cron-manager/index.js.map +1 -0
  42. package/dist/services/index-manager/index-manager.service.d.ts +146 -0
  43. package/dist/services/index-manager/index-manager.service.d.ts.map +1 -0
  44. package/dist/services/index-manager/index-manager.service.js +337 -0
  45. package/dist/services/index-manager/index-manager.service.js.map +1 -0
  46. package/dist/services/index-manager/index.d.ts +2 -0
  47. package/dist/services/index-manager/index.d.ts.map +1 -0
  48. package/dist/services/index-manager/index.js +18 -0
  49. package/dist/services/index-manager/index.js.map +1 -0
  50. package/dist/services/index.d.ts +10 -0
  51. package/dist/services/index.d.ts.map +1 -0
  52. package/dist/services/index.js +26 -0
  53. package/dist/services/index.js.map +1 -0
  54. package/dist/services/job-processor/index.d.ts +2 -0
  55. package/dist/services/job-processor/index.d.ts.map +1 -0
  56. package/dist/services/job-processor/index.js +18 -0
  57. package/dist/services/job-processor/index.js.map +1 -0
  58. package/dist/services/job-processor/job-processor.service.d.ts +156 -0
  59. package/dist/services/job-processor/job-processor.service.d.ts.map +1 -0
  60. package/dist/services/job-processor/job-processor.service.js +331 -0
  61. package/dist/services/job-processor/job-processor.service.js.map +1 -0
  62. package/dist/services/queue-manager/index.d.ts +2 -0
  63. package/dist/services/queue-manager/index.d.ts.map +1 -0
  64. package/dist/services/queue-manager/index.js +18 -0
  65. package/dist/services/queue-manager/index.js.map +1 -0
  66. package/dist/services/queue-manager/queue-manager.service.d.ts +128 -0
  67. package/dist/services/queue-manager/queue-manager.service.d.ts.map +1 -0
  68. package/dist/services/queue-manager/queue-manager.service.js +308 -0
  69. package/dist/services/queue-manager/queue-manager.service.js.map +1 -0
  70. package/dist/services/resource-lock/index.d.ts +2 -0
  71. package/dist/services/resource-lock/index.d.ts.map +1 -0
  72. package/dist/services/resource-lock/index.js +18 -0
  73. package/dist/services/resource-lock/index.js.map +1 -0
  74. package/dist/services/resource-lock/resource-lock.service.d.ts +124 -0
  75. package/dist/services/resource-lock/resource-lock.service.d.ts.map +1 -0
  76. package/dist/services/resource-lock/resource-lock.service.js +379 -0
  77. package/dist/services/resource-lock/resource-lock.service.js.map +1 -0
  78. package/dist/services/service-queue/index.d.ts +2 -0
  79. package/dist/services/service-queue/index.d.ts.map +1 -0
  80. package/dist/services/service-queue/index.js +18 -0
  81. package/dist/services/service-queue/index.js.map +1 -0
  82. package/dist/services/service-queue/service-queue.service.d.ts +232 -0
  83. package/dist/services/service-queue/service-queue.service.d.ts.map +1 -0
  84. package/dist/services/service-queue/service-queue.service.js +647 -0
  85. package/dist/services/service-queue/service-queue.service.js.map +1 -0
  86. package/dist/services/shutdown-state/index.d.ts +2 -0
  87. package/dist/services/shutdown-state/index.d.ts.map +1 -0
  88. package/dist/services/shutdown-state/index.js +18 -0
  89. package/dist/services/shutdown-state/index.js.map +1 -0
  90. package/dist/services/shutdown-state/shutdown-state.service.d.ts +69 -0
  91. package/dist/services/shutdown-state/shutdown-state.service.d.ts.map +1 -0
  92. package/dist/services/shutdown-state/shutdown-state.service.js +127 -0
  93. package/dist/services/shutdown-state/shutdown-state.service.js.map +1 -0
  94. package/dist/services/worker-manager/index.d.ts +2 -0
  95. package/dist/services/worker-manager/index.d.ts.map +1 -0
  96. package/dist/services/worker-manager/index.js +18 -0
  97. package/dist/services/worker-manager/index.js.map +1 -0
  98. package/dist/services/worker-manager/worker-manager.service.d.ts +163 -0
  99. package/dist/services/worker-manager/worker-manager.service.d.ts.map +1 -0
  100. package/dist/services/worker-manager/worker-manager.service.js +460 -0
  101. package/dist/services/worker-manager/worker-manager.service.js.map +1 -0
  102. package/dist/utils/helpers.d.ts +124 -0
  103. package/dist/utils/helpers.d.ts.map +1 -0
  104. package/dist/utils/helpers.js +229 -0
  105. package/dist/utils/helpers.js.map +1 -0
  106. package/dist/utils/index.d.ts +2 -0
  107. package/dist/utils/index.d.ts.map +1 -0
  108. package/dist/utils/index.js +18 -0
  109. package/dist/utils/index.js.map +1 -0
  110. package/package.json +80 -0
@@ -0,0 +1,460 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ var __importDefault = (this && this.__importDefault) || function (mod) {
15
+ return (mod && mod.__esModule) ? mod : { "default": mod };
16
+ };
17
+ var WorkerManagerService_1;
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.WorkerManagerService = void 0;
20
+ const common_1 = require("@nestjs/common");
21
+ const bullmq_1 = require("bullmq");
22
+ const ioredis_1 = __importDefault(require("ioredis"));
23
+ const uuid_1 = require("uuid");
24
+ const constants_1 = require("../constants");
25
+ /**
26
+ * WorkerManagerService
27
+ *
28
+ * Manages worker lifecycle with features from both Whatsapi and bl-blackjack-service:
29
+ *
30
+ * - Dynamic worker creation per entity (user message queue workers, table workers)
31
+ * - Heartbeat-based liveness tracking with TTL
32
+ * - Graceful shutdown via Redis pub/sub
33
+ * - Node-aware worker tracking (multi-instance support)
34
+ * - Automatic cleanup on application shutdown
35
+ *
36
+ * Architecture Notes:
37
+ * - Each worker registers itself with a heartbeat TTL
38
+ * - Workers subscribe to their own shutdown channel
39
+ * - A cron process monitors worker health and spawns/terminates as needed
40
+ * - On application shutdown, all node workers are signaled to close gracefully
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * const worker = await workerManager.createWorker({
45
+ * workerName: `user-${userId}-worker`,
46
+ * queueName: `user-${userId}-queue`,
47
+ * processor: async (job) => {
48
+ * // Process job
49
+ * },
50
+ * });
51
+ * ```
52
+ */
53
+ let WorkerManagerService = WorkerManagerService_1 = class WorkerManagerService {
54
+ constructor(redis, config) {
55
+ this.redis = redis;
56
+ this.config = config;
57
+ this.logger = new common_1.Logger(WorkerManagerService_1.name);
58
+ this.workers = new Map();
59
+ this.workerStates = new Map();
60
+ this.heartbeatIntervals = new Map();
61
+ this.shutdownSubscriptions = new Map();
62
+ this.subscriberClient = null;
63
+ this.nodeId = this.generateNodeId();
64
+ this.keyPrefix = config.keyPrefix || 'aq';
65
+ this.logger.log(`WorkerManager initialized with nodeId: ${this.nodeId}`);
66
+ }
67
+ /**
68
+ * Initialize subscriber client for pub/sub communication.
69
+ */
70
+ onModuleInit() {
71
+ this.subscriberClient = this.createSubscriberClient();
72
+ }
73
+ /**
74
+ * Create a new worker with automatic lifecycle management.
75
+ *
76
+ * This method:
77
+ * 1. Creates a BullMQ Worker
78
+ * 2. Sets up heartbeat TTL tracking
79
+ * 3. Subscribes to shutdown channel for graceful termination
80
+ * 4. Registers lifecycle event handlers
81
+ */
82
+ async createWorker(options) {
83
+ const { workerName, queueName, config, events, processor } = options;
84
+ // Check if worker already exists
85
+ if (await this.workerExists(workerName)) {
86
+ this.logger.warn(`Worker ${workerName} already exists, skipping creation`);
87
+ const existingWorker = this.workers.get(workerName);
88
+ if (existingWorker)
89
+ return existingWorker;
90
+ }
91
+ this.logger.log(`Creating worker: ${workerName} for queue: ${queueName}`);
92
+ const workerConfig = this.mergeWorkerConfig(config);
93
+ // Create the BullMQ worker
94
+ const worker = new bullmq_1.Worker(queueName, processor, {
95
+ connection: this.redis.duplicate(),
96
+ concurrency: workerConfig.concurrency,
97
+ stalledInterval: workerConfig.stalledInterval,
98
+ lockDuration: workerConfig.lockDuration,
99
+ maxStalledCount: workerConfig.maxStalledCount,
100
+ });
101
+ // Store worker instance
102
+ this.workers.set(workerName, worker);
103
+ // Initialize worker state
104
+ const state = {
105
+ workerId: (0, uuid_1.v4)(),
106
+ workerName,
107
+ nodeId: this.nodeId,
108
+ status: 'starting',
109
+ createdAt: new Date(),
110
+ lastHeartbeat: new Date(),
111
+ };
112
+ this.workerStates.set(workerName, state);
113
+ // Set up heartbeat
114
+ this.setupHeartbeat(workerName, workerConfig.heartbeatTTL || 3);
115
+ // Set up shutdown subscription
116
+ await this.subscribeToShutdown(workerName, worker);
117
+ // Register event handlers
118
+ this.registerWorkerEvents(worker, workerName, events);
119
+ return worker;
120
+ }
121
+ /**
122
+ * Check if a worker exists and is alive (has valid heartbeat).
123
+ */
124
+ async workerExists(workerName) {
125
+ const key = this.getWorkerKey(workerName);
126
+ const exists = await this.redis.exists(key);
127
+ return exists === 1;
128
+ }
129
+ /**
130
+ * Get all running workers for the current node.
131
+ */
132
+ async getNodeWorkers() {
133
+ const pattern = `${this.keyPrefix}:worker:${this.nodeId}:*`;
134
+ const keys = await this.redis.keys(pattern);
135
+ return keys.map((key) => key.split(':').pop());
136
+ }
137
+ /**
138
+ * Get all running workers across all nodes.
139
+ */
140
+ async getAllWorkers() {
141
+ const pattern = `${this.keyPrefix}:worker:*:*`;
142
+ const keys = await this.redis.keys(pattern);
143
+ return keys.map((key) => key.split(':').pop());
144
+ }
145
+ /**
146
+ * Get all workers for a specific entity.
147
+ * Uses the worker heartbeat TTL keys as the single source of truth.
148
+ * Worker names follow the pattern: {entityId}-worker
149
+ */
150
+ async getEntityWorkers(entityType, entityId) {
151
+ // Worker heartbeat keys follow pattern: {prefix}:worker:{nodeId}:{workerName}
152
+ // Worker names follow pattern: {entityId}-worker
153
+ const workerName = `${entityId}-worker`;
154
+ const pattern = `${this.keyPrefix}:worker:*:${workerName}`;
155
+ const keys = await this.redis.keys(pattern);
156
+ return keys.map((key) => key.split(':').pop());
157
+ }
158
+ /**
159
+ * Signal a worker to close gracefully via pub/sub.
160
+ */
161
+ async signalWorkerClose(workerName) {
162
+ const channel = this.getWorkerShutdownChannel(workerName);
163
+ await this.redis.publish(channel, 'shutdown');
164
+ this.logger.log(`Sent shutdown signal to worker: ${workerName}`);
165
+ }
166
+ /**
167
+ * Signal all workers on current node to close.
168
+ */
169
+ async signalNodeWorkersClose() {
170
+ const workers = await this.getNodeWorkers();
171
+ this.logger.log(`Signaling ${workers.length} workers to close on node ${this.nodeId}`);
172
+ await Promise.all(workers.map((workerName) => this.signalWorkerClose(workerName)));
173
+ }
174
+ /**
175
+ * Close all workers managed by this instance.
176
+ * This is the public API for external callers to gracefully shutdown workers.
177
+ */
178
+ async closeAllWorkers(timeoutMs = 30000) {
179
+ this.logger.warn(`Closing all workers on node ${this.nodeId}`);
180
+ // Clear all heartbeat intervals
181
+ for (const [workerName, interval] of this.heartbeatIntervals) {
182
+ clearInterval(interval);
183
+ this.heartbeatIntervals.delete(workerName);
184
+ }
185
+ // Signal all workers to close
186
+ await this.signalNodeWorkersClose();
187
+ // Wait for workers to close
188
+ try {
189
+ await this.waitForWorkersToClose(timeoutMs);
190
+ }
191
+ catch (error) {
192
+ this.logger.warn(`Some workers did not close gracefully: ${error}`);
193
+ }
194
+ }
195
+ /**
196
+ * Wait for all node workers to close with timeout.
197
+ */
198
+ async waitForWorkersToClose(timeoutMs = 60000) {
199
+ const startTime = Date.now();
200
+ while (Date.now() - startTime < timeoutMs) {
201
+ const workers = await this.getNodeWorkers();
202
+ if (workers.length === 0) {
203
+ this.logger.log(`All workers on node ${this.nodeId} have closed.`);
204
+ return;
205
+ }
206
+ this.logger.debug(`Waiting... ${workers.length} workers remaining.`);
207
+ await this.sleep(1000);
208
+ }
209
+ throw new Error(`Timeout reached while waiting for workers to close on node ${this.nodeId}`);
210
+ }
211
+ /**
212
+ * Reset worker heartbeat TTL.
213
+ */
214
+ async resetWorkerHeartbeat(workerName, ttlSeconds) {
215
+ const ttl = ttlSeconds || this.config.workerDefaults?.heartbeatTTL || 3;
216
+ const key = this.getWorkerKey(workerName);
217
+ const exists = await this.redis.exists(key);
218
+ if (exists) {
219
+ await this.redis.expire(key, ttl);
220
+ }
221
+ else {
222
+ await this.redis.set(key, '1', 'EX', ttl);
223
+ }
224
+ // Update local state
225
+ const state = this.workerStates.get(workerName);
226
+ if (state) {
227
+ state.lastHeartbeat = new Date();
228
+ }
229
+ }
230
+ /**
231
+ * Remove worker heartbeat (mark as dead).
232
+ */
233
+ async removeWorkerHeartbeat(workerName) {
234
+ const key = this.getWorkerKey(workerName);
235
+ await this.redis.del(key);
236
+ this.logger.debug(`Removed heartbeat for worker: ${workerName}`);
237
+ }
238
+ /**
239
+ * Get the node ID for this instance.
240
+ */
241
+ getNodeId() {
242
+ return this.nodeId;
243
+ }
244
+ /**
245
+ * Index a worker for an entity (for entity-based tracking).
246
+ */
247
+ async indexEntityWorker(entityType, entityId, workerId, ttlSeconds = 3) {
248
+ const key = `${this.keyPrefix}:entity-worker:${entityType}:${entityId}:${workerId}`;
249
+ await this.redis.set(key, '1', 'EX', ttlSeconds);
250
+ }
251
+ /**
252
+ * Remove entity worker index.
253
+ */
254
+ async removeEntityWorkerIndex(entityType, entityId, workerId) {
255
+ const key = `${this.keyPrefix}:entity-worker:${entityType}:${entityId}:${workerId}`;
256
+ await this.redis.del(key);
257
+ }
258
+ /**
259
+ * Get subscriber client for pub/sub operations.
260
+ */
261
+ getSubscriberClient() {
262
+ if (!this.subscriberClient) {
263
+ this.subscriberClient = this.createSubscriberClient();
264
+ }
265
+ return this.subscriberClient;
266
+ }
267
+ /**
268
+ * Graceful shutdown on application termination.
269
+ */
270
+ async onApplicationShutdown() {
271
+ this.logger.warn(`Application shutting down, closing workers on node ${this.nodeId}`);
272
+ // Clear all heartbeat intervals
273
+ for (const [workerName, interval] of this.heartbeatIntervals) {
274
+ clearInterval(interval);
275
+ this.heartbeatIntervals.delete(workerName);
276
+ }
277
+ // Signal all workers to close
278
+ await this.signalNodeWorkersClose();
279
+ // Wait for workers to close
280
+ try {
281
+ await this.waitForWorkersToClose(30000);
282
+ }
283
+ catch (error) {
284
+ this.logger.warn(`Some workers did not close gracefully: ${error}`);
285
+ }
286
+ // Close subscriber client
287
+ if (this.subscriberClient) {
288
+ await this.subscriberClient.quit();
289
+ }
290
+ }
291
+ // =========================================================================
292
+ // PRIVATE METHODS
293
+ // =========================================================================
294
+ /**
295
+ * Generate a unique node ID for this instance.
296
+ */
297
+ generateNodeId() {
298
+ return (0, uuid_1.v4)();
299
+ }
300
+ /**
301
+ * Create a subscriber client for pub/sub.
302
+ */
303
+ createSubscriberClient() {
304
+ return this.redis.duplicate();
305
+ }
306
+ /**
307
+ * Get the Redis key for a worker's heartbeat.
308
+ */
309
+ getWorkerKey(workerName) {
310
+ return `${this.keyPrefix}:worker:${this.nodeId}:${workerName}`;
311
+ }
312
+ /**
313
+ * Get the shutdown channel for a worker.
314
+ */
315
+ getWorkerShutdownChannel(workerName) {
316
+ return `${this.keyPrefix}:worker:${workerName}:shutdown`;
317
+ }
318
+ /**
319
+ * Merge worker config with defaults.
320
+ */
321
+ mergeWorkerConfig(config) {
322
+ const defaults = {
323
+ concurrency: 1,
324
+ stalledInterval: 1000,
325
+ lockDuration: 30000,
326
+ maxStalledCount: Number.MAX_SAFE_INTEGER,
327
+ heartbeatTTL: 3,
328
+ heartbeatInterval: 1000,
329
+ };
330
+ return { ...defaults, ...this.config.workerDefaults, ...config };
331
+ }
332
+ /**
333
+ * Set up heartbeat interval for a worker.
334
+ */
335
+ setupHeartbeat(workerName, ttlSeconds) {
336
+ const interval = setInterval(async () => {
337
+ try {
338
+ await this.resetWorkerHeartbeat(workerName, ttlSeconds);
339
+ }
340
+ catch (error) {
341
+ this.logger.error(`Failed to reset heartbeat for worker ${workerName}:`, error);
342
+ }
343
+ }, (ttlSeconds * 1000) / 2); // Update at half the TTL
344
+ this.heartbeatIntervals.set(workerName, interval);
345
+ }
346
+ /**
347
+ * Subscribe to shutdown channel for graceful termination.
348
+ */
349
+ async subscribeToShutdown(workerName, worker) {
350
+ const channel = this.getWorkerShutdownChannel(workerName);
351
+ const subscriber = this.getSubscriberClient();
352
+ await subscriber.subscribe(channel);
353
+ this.logger.debug(`Subscribed to shutdown channel: ${channel}`);
354
+ const messageHandler = async (msgChannel) => {
355
+ if (msgChannel === channel) {
356
+ this.logger.log(`Received shutdown signal for worker: ${workerName}`);
357
+ await this.closeWorker(workerName, worker);
358
+ }
359
+ };
360
+ subscriber.on('message', messageHandler);
361
+ // Store cleanup function
362
+ this.shutdownSubscriptions.set(workerName, () => {
363
+ subscriber.off('message', messageHandler);
364
+ subscriber.unsubscribe(channel).catch(() => { });
365
+ });
366
+ }
367
+ /**
368
+ * Close a worker and clean up resources.
369
+ */
370
+ async closeWorker(workerName, worker) {
371
+ // Clear heartbeat interval
372
+ const interval = this.heartbeatIntervals.get(workerName);
373
+ if (interval) {
374
+ clearInterval(interval);
375
+ this.heartbeatIntervals.delete(workerName);
376
+ }
377
+ // Unsubscribe from shutdown channel
378
+ const cleanup = this.shutdownSubscriptions.get(workerName);
379
+ if (cleanup) {
380
+ cleanup();
381
+ this.shutdownSubscriptions.delete(workerName);
382
+ }
383
+ // Remove heartbeat
384
+ await this.removeWorkerHeartbeat(workerName);
385
+ // Close worker
386
+ await worker.close();
387
+ // Remove from maps
388
+ this.workers.delete(workerName);
389
+ this.workerStates.delete(workerName);
390
+ this.logger.log(`Worker ${workerName} closed and cleaned up.`);
391
+ }
392
+ /**
393
+ * Register event handlers for a worker.
394
+ */
395
+ registerWorkerEvents(worker, workerName, events) {
396
+ worker.on('ready', async () => {
397
+ const state = this.workerStates.get(workerName);
398
+ if (state)
399
+ state.status = 'ready';
400
+ await this.resetWorkerHeartbeat(workerName);
401
+ this.logger.log(`Worker ${workerName} is ready.`);
402
+ if (events?.onReady) {
403
+ await events.onReady(worker, workerName);
404
+ }
405
+ });
406
+ worker.on('completed', async (job) => {
407
+ this.logger.debug(`Worker ${workerName} completed job: ${job.id}`);
408
+ if (events?.onCompleted) {
409
+ await events.onCompleted(job, workerName);
410
+ }
411
+ });
412
+ worker.on('failed', async (job, error) => {
413
+ this.logger.error(`Worker ${workerName} failed job ${job?.id}: ${error.message}`);
414
+ if (events?.onFailed) {
415
+ await events.onFailed(job, error, workerName);
416
+ }
417
+ });
418
+ worker.on('progress', async (job, progress) => {
419
+ this.logger.debug(`Worker ${workerName} job ${job.id} progress: ${JSON.stringify(progress)}`);
420
+ if (events?.onProgress) {
421
+ await events.onProgress(job, progress);
422
+ }
423
+ });
424
+ worker.on('stalled', async (jobId) => {
425
+ this.logger.warn(`Worker ${workerName} job ${jobId} stalled`);
426
+ if (events?.onStalled) {
427
+ await events.onStalled(jobId, workerName);
428
+ }
429
+ });
430
+ worker.on('closing', () => {
431
+ const state = this.workerStates.get(workerName);
432
+ if (state)
433
+ state.status = 'closing';
434
+ this.logger.log(`Worker ${workerName} is closing...`);
435
+ if (events?.onClosing) {
436
+ events.onClosing(workerName);
437
+ }
438
+ });
439
+ worker.on('closed', async () => {
440
+ this.logger.log(`Worker ${workerName} closed.`);
441
+ if (events?.onClosed) {
442
+ await events.onClosed(workerName);
443
+ }
444
+ });
445
+ }
446
+ /**
447
+ * Sleep utility.
448
+ */
449
+ sleep(ms) {
450
+ return new Promise((resolve) => setTimeout(resolve, ms));
451
+ }
452
+ };
453
+ exports.WorkerManagerService = WorkerManagerService;
454
+ exports.WorkerManagerService = WorkerManagerService = WorkerManagerService_1 = __decorate([
455
+ (0, common_1.Injectable)(),
456
+ __param(0, (0, common_1.Inject)(constants_1.ATOMIC_QUEUES_REDIS)),
457
+ __param(1, (0, common_1.Inject)(constants_1.ATOMIC_QUEUES_CONFIG)),
458
+ __metadata("design:paramtypes", [ioredis_1.default, Object])
459
+ ], WorkerManagerService);
460
+ //# sourceMappingURL=worker-manager.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-manager.service.js","sourceRoot":"","sources":["../../../src/services/worker-manager/worker-manager.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,124 @@
1
+ import { IAtomicJobData, IJobOptions } from '../domain';
2
+ /**
3
+ * Create an atomic job data payload.
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * const jobData = createAtomicJobData({
8
+ * entityType: 'user',
9
+ * entityId: '123',
10
+ * type: 'command',
11
+ * commandName: 'SendMessageCommand',
12
+ * payload: { message: 'Hello!' },
13
+ * });
14
+ *
15
+ * await queueManager.addJob('user-123-queue', 'send-message', jobData);
16
+ * ```
17
+ */
18
+ export declare function createAtomicJobData<T = unknown>(options: {
19
+ entityType: string;
20
+ entityId: string;
21
+ type: 'command' | 'query' | 'custom';
22
+ commandName?: string;
23
+ payload: T;
24
+ metadata?: Record<string, unknown>;
25
+ }): IAtomicJobData<T>;
26
+ /**
27
+ * Create default job options with common settings.
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * const options = createDefaultJobOptions({
32
+ * priority: 0, // Highest priority
33
+ * attempts: 5,
34
+ * });
35
+ * ```
36
+ */
37
+ export declare function createDefaultJobOptions(overrides?: Partial<IJobOptions>): IJobOptions;
38
+ /**
39
+ * Create high-priority job options (for SIGTERM signals, etc.)
40
+ */
41
+ export declare function createHighPriorityJobOptions(overrides?: Partial<IJobOptions>): IJobOptions;
42
+ /**
43
+ * Sleep utility for async operations.
44
+ */
45
+ export declare function sleep(ms: number): Promise<void>;
46
+ /**
47
+ * Retry utility with exponential backoff.
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * const result = await retry(
52
+ * () => someUnreliableOperation(),
53
+ * { maxAttempts: 3, baseDelay: 1000 },
54
+ * );
55
+ * ```
56
+ */
57
+ export declare function retry<T>(fn: () => Promise<T>, options: {
58
+ maxAttempts: number;
59
+ baseDelay: number;
60
+ maxDelay?: number;
61
+ exponential?: boolean;
62
+ onRetry?: (attempt: number, error: Error) => void;
63
+ }): Promise<T>;
64
+ /**
65
+ * Generate a queue name for an entity.
66
+ */
67
+ export declare function getEntityQueueName(entityType: string, entityId: string, prefix?: string): string;
68
+ /**
69
+ * Generate a worker name for an entity.
70
+ */
71
+ export declare function getEntityWorkerName(entityType: string, entityId: string, prefix?: string): string;
72
+ /**
73
+ * Parse a queue name to extract entity info.
74
+ */
75
+ export declare function parseQueueName(queueName: string): {
76
+ prefix: string;
77
+ entityType: string;
78
+ entityId: string;
79
+ } | null;
80
+ /**
81
+ * Create a SIGTERM job payload for worker termination.
82
+ */
83
+ export declare function createSigtermPayload<T = unknown>(entityType: string, entityId: string): IAtomicJobData<T>;
84
+ /**
85
+ * Check if a job is a SIGTERM signal.
86
+ */
87
+ export declare function isSigtermJob(data: IAtomicJobData): boolean;
88
+ /**
89
+ * Batch utility for processing items in chunks.
90
+ *
91
+ * @example
92
+ * ```typescript
93
+ * await batch(items, 10, async (chunk) => {
94
+ * await Promise.all(chunk.map(processItem));
95
+ * });
96
+ * ```
97
+ */
98
+ export declare function batch<T>(items: T[], batchSize: number, processor: (batch: T[]) => Promise<void>): Promise<void>;
99
+ /**
100
+ * Create a timeout promise that rejects after specified ms.
101
+ */
102
+ export declare function createTimeout(ms: number, message?: string): Promise<never>;
103
+ /**
104
+ * Run an operation with a timeout.
105
+ *
106
+ * @example
107
+ * ```typescript
108
+ * const result = await withTimeout(
109
+ * someAsyncOperation(),
110
+ * 5000,
111
+ * 'Operation took too long',
112
+ * );
113
+ * ```
114
+ */
115
+ export declare function withTimeout<T>(promise: Promise<T>, ms: number, message?: string): Promise<T>;
116
+ /**
117
+ * Debounce utility for functions.
118
+ */
119
+ export declare function debounce<T extends (...args: unknown[]) => unknown>(fn: T, ms: number): (...args: Parameters<T>) => void;
120
+ /**
121
+ * Throttle utility for functions.
122
+ */
123
+ export declare function throttle<T extends (...args: unknown[]) => unknown>(fn: T, ms: number): (...args: Parameters<T>) => void;
124
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":"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"}