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 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAGH,cAAc,UAAU,CAAC;AAGzB,cAAc,UAAU,CAAC;AAGzB,cAAc,YAAY,CAAC;AAG3B,cAAc,cAAc,CAAC;AAG7B,cAAc,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ /**
3
+ * =============================================================================
4
+ * ATOMIC QUEUES
5
+ * =============================================================================
6
+ *
7
+ * A plug-and-play NestJS library for atomic process handling per entity
8
+ * with BullMQ, Redis distributed locking, and dynamic worker management.
9
+ *
10
+ * Features:
11
+ * - Dynamic per-entity queue creation
12
+ * - Worker lifecycle management with heartbeat TTL
13
+ * - Distributed resource locking (Redis/Lua scripts)
14
+ * - Graceful shutdown coordination via pub/sub
15
+ * - Cron-based worker spawning/cleanup
16
+ * - CQRS command/query dynamic execution
17
+ * - Index tracking for jobs, workers, and queues
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * import { AtomicQueuesModule, QueueManagerService, WorkerManagerService } from 'atomic-queues';
22
+ *
23
+ * @Module({
24
+ * imports: [
25
+ * AtomicQueuesModule.forRoot({
26
+ * redis: { host: 'localhost', port: 6379 },
27
+ * enableCronManager: true,
28
+ * }),
29
+ * ],
30
+ * })
31
+ * export class AppModule {}
32
+ * ```
33
+ *
34
+ * @packageDocumentation
35
+ */
36
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
37
+ if (k2 === undefined) k2 = k;
38
+ var desc = Object.getOwnPropertyDescriptor(m, k);
39
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
40
+ desc = { enumerable: true, get: function() { return m[k]; } };
41
+ }
42
+ Object.defineProperty(o, k2, desc);
43
+ }) : (function(o, m, k, k2) {
44
+ if (k2 === undefined) k2 = k;
45
+ o[k2] = m[k];
46
+ }));
47
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
48
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
49
+ };
50
+ Object.defineProperty(exports, "__esModule", { value: true });
51
+ // Domain - Interfaces and Types
52
+ __exportStar(require("./domain"), exports);
53
+ // Module
54
+ __exportStar(require("./module"), exports);
55
+ // Services
56
+ __exportStar(require("./services"), exports);
57
+ // Decorators
58
+ __exportStar(require("./decorators"), exports);
59
+ // Utilities
60
+ __exportStar(require("./utils"), exports);
61
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;;;;;;;;;;;;;;;;AAEH,gCAAgC;AAChC,2CAAyB;AAEzB,SAAS;AACT,2CAAyB;AAEzB,WAAW;AACX,6CAA2B;AAE3B,aAAa;AACb,+CAA6B;AAE7B,YAAY;AACZ,0CAAwB"}
@@ -0,0 +1,97 @@
1
+ import { DynamicModule, Type } from '@nestjs/common';
2
+ import { IAtomicQueuesModuleConfig } from '../domain';
3
+ /**
4
+ * Async module options for AtomicQueuesModule.forRootAsync()
5
+ */
6
+ export interface AtomicQueuesModuleAsyncOptions {
7
+ /**
8
+ * Imports to include in the module
9
+ */
10
+ imports?: Type<unknown>[];
11
+ /**
12
+ * Factory function to create the module configuration
13
+ */
14
+ useFactory: (...args: unknown[]) => Promise<IAtomicQueuesModuleConfig> | IAtomicQueuesModuleConfig;
15
+ /**
16
+ * Dependencies to inject into the factory
17
+ */
18
+ inject?: unknown[];
19
+ /**
20
+ * Whether to make the module global
21
+ */
22
+ isGlobal?: boolean;
23
+ }
24
+ /**
25
+ * AtomicQueuesModule
26
+ *
27
+ * Main module for the AtomicQueues library.
28
+ * Provides all services for atomic process handling per entity.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * // Synchronous configuration
33
+ * @Module({
34
+ * imports: [
35
+ * AtomicQueuesModule.forRoot({
36
+ * redis: {
37
+ * host: 'localhost',
38
+ * port: 6379,
39
+ * },
40
+ * enableCronManager: true,
41
+ * cronInterval: 5000,
42
+ * }),
43
+ * ],
44
+ * })
45
+ * export class AppModule {}
46
+ *
47
+ * // Async configuration
48
+ * @Module({
49
+ * imports: [
50
+ * AtomicQueuesModule.forRootAsync({
51
+ * imports: [ConfigModule],
52
+ * useFactory: (configService: ConfigService) => ({
53
+ * redis: {
54
+ * url: configService.get('REDIS_URL'),
55
+ * },
56
+ * enableCronManager: true,
57
+ * }),
58
+ * inject: [ConfigService],
59
+ * }),
60
+ * ],
61
+ * })
62
+ * export class AppModule {}
63
+ * ```
64
+ */
65
+ export declare class AtomicQueuesModule {
66
+ /**
67
+ * Configure the module with synchronous options.
68
+ */
69
+ static forRoot(config: IAtomicQueuesModuleConfig): DynamicModule;
70
+ /**
71
+ * Configure the module with asynchronous options.
72
+ */
73
+ static forRootAsync(options: AtomicQueuesModuleAsyncOptions): DynamicModule;
74
+ /**
75
+ * Create a feature module for entity-specific configuration.
76
+ * Use this for registering entity scaling configurations.
77
+ */
78
+ static forFeature(options: {
79
+ entityType: string;
80
+ getDesiredWorkerCount: (entityId: string) => Promise<number>;
81
+ getActiveEntityIds: () => Promise<string[]>;
82
+ maxWorkersPerEntity?: number;
83
+ }): DynamicModule;
84
+ /**
85
+ * Create synchronous Redis provider.
86
+ */
87
+ private static createRedisProvider;
88
+ /**
89
+ * Create async configuration provider.
90
+ */
91
+ private static createAsyncConfigProvider;
92
+ /**
93
+ * Create async Redis provider.
94
+ */
95
+ private static createAsyncRedisProvider;
96
+ }
97
+ //# sourceMappingURL=atomic-queues.module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atomic-queues.module.d.ts","sourceRoot":"","sources":["../../src/module/atomic-queues.module.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAIb,IAAI,EACL,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,yBAAyB,EAAe,MAAM,WAAW,CAAC;AAiBnE;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC7C;;OAEG;IACH,OAAO,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;IAE1B;;OAEG;IACH,UAAU,EAAE,CACV,GAAG,IAAI,EAAE,OAAO,EAAE,KACf,OAAO,CAAC,yBAAyB,CAAC,GAAG,yBAAyB,CAAC;IAEpE;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;IAEnB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAkBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,qBAEa,kBAAkB;IAC7B;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,yBAAyB,GAAG,aAAa;IAuBhE;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,8BAA8B,GAAG,aAAa;IAmB3E;;;OAGG;IACH,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE;QACzB,UAAU,EAAE,MAAM,CAAC;QACnB,qBAAqB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;QAC7D,kBAAkB,EAAE,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAC5C,mBAAmB,CAAC,EAAE,MAAM,CAAC;KAC9B,GAAG,aAAa;IAgBjB;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAuBlC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,yBAAyB;IAUxC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,wBAAwB;CAqBxC"}
@@ -0,0 +1,197 @@
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 __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ var AtomicQueuesModule_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.AtomicQueuesModule = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const ioredis_1 = __importDefault(require("ioredis"));
16
+ const services_1 = require("../services");
17
+ /**
18
+ * Core services provided by the module
19
+ */
20
+ const CORE_SERVICES = [
21
+ services_1.QueueManagerService,
22
+ services_1.WorkerManagerService,
23
+ services_1.ResourceLockService,
24
+ services_1.IndexManagerService,
25
+ services_1.JobProcessorRegistry,
26
+ services_1.DynamicExecutorService,
27
+ services_1.AtomicJobProcessor,
28
+ services_1.CronManagerService,
29
+ services_1.ServiceQueueManager,
30
+ services_1.ShutdownStateService,
31
+ ];
32
+ /**
33
+ * AtomicQueuesModule
34
+ *
35
+ * Main module for the AtomicQueues library.
36
+ * Provides all services for atomic process handling per entity.
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * // Synchronous configuration
41
+ * @Module({
42
+ * imports: [
43
+ * AtomicQueuesModule.forRoot({
44
+ * redis: {
45
+ * host: 'localhost',
46
+ * port: 6379,
47
+ * },
48
+ * enableCronManager: true,
49
+ * cronInterval: 5000,
50
+ * }),
51
+ * ],
52
+ * })
53
+ * export class AppModule {}
54
+ *
55
+ * // Async configuration
56
+ * @Module({
57
+ * imports: [
58
+ * AtomicQueuesModule.forRootAsync({
59
+ * imports: [ConfigModule],
60
+ * useFactory: (configService: ConfigService) => ({
61
+ * redis: {
62
+ * url: configService.get('REDIS_URL'),
63
+ * },
64
+ * enableCronManager: true,
65
+ * }),
66
+ * inject: [ConfigService],
67
+ * }),
68
+ * ],
69
+ * })
70
+ * export class AppModule {}
71
+ * ```
72
+ */
73
+ let AtomicQueuesModule = AtomicQueuesModule_1 = class AtomicQueuesModule {
74
+ /**
75
+ * Configure the module with synchronous options.
76
+ */
77
+ static forRoot(config) {
78
+ const redisProvider = this.createRedisProvider(config);
79
+ return {
80
+ module: AtomicQueuesModule_1,
81
+ // Note: CqrsModule should be imported by the consuming app, not here
82
+ // to avoid duplicate CommandBus/QueryBus instances
83
+ providers: [
84
+ {
85
+ provide: services_1.ATOMIC_QUEUES_CONFIG,
86
+ useValue: config,
87
+ },
88
+ redisProvider,
89
+ ...CORE_SERVICES,
90
+ ],
91
+ exports: [
92
+ services_1.ATOMIC_QUEUES_CONFIG,
93
+ services_1.ATOMIC_QUEUES_REDIS,
94
+ ...CORE_SERVICES,
95
+ ],
96
+ };
97
+ }
98
+ /**
99
+ * Configure the module with asynchronous options.
100
+ */
101
+ static forRootAsync(options) {
102
+ const configProvider = this.createAsyncConfigProvider(options);
103
+ const redisProvider = this.createAsyncRedisProvider();
104
+ return {
105
+ module: AtomicQueuesModule_1,
106
+ // Note: CqrsModule should be imported by the consuming app, not here
107
+ // to avoid duplicate CommandBus/QueryBus instances
108
+ imports: [...(options.imports || [])],
109
+ providers: [configProvider, redisProvider, ...CORE_SERVICES],
110
+ exports: [
111
+ services_1.ATOMIC_QUEUES_CONFIG,
112
+ services_1.ATOMIC_QUEUES_REDIS,
113
+ ...CORE_SERVICES,
114
+ ],
115
+ global: options.isGlobal ?? true,
116
+ };
117
+ }
118
+ /**
119
+ * Create a feature module for entity-specific configuration.
120
+ * Use this for registering entity scaling configurations.
121
+ */
122
+ static forFeature(options) {
123
+ return {
124
+ module: AtomicQueuesModule_1,
125
+ providers: [
126
+ {
127
+ provide: `ENTITY_CONFIG_${options.entityType}`,
128
+ useValue: options,
129
+ },
130
+ ],
131
+ };
132
+ }
133
+ // =========================================================================
134
+ // PRIVATE METHODS
135
+ // =========================================================================
136
+ /**
137
+ * Create synchronous Redis provider.
138
+ */
139
+ static createRedisProvider(config) {
140
+ return {
141
+ provide: services_1.ATOMIC_QUEUES_REDIS,
142
+ useFactory: () => {
143
+ if (config.redis.url) {
144
+ return new ioredis_1.default(config.redis.url, {
145
+ maxRetriesPerRequest: config.redis.maxRetriesPerRequest ?? null,
146
+ });
147
+ }
148
+ return new ioredis_1.default({
149
+ host: config.redis.host || 'localhost',
150
+ port: config.redis.port || 6379,
151
+ password: config.redis.password,
152
+ db: config.redis.db,
153
+ maxRetriesPerRequest: config.redis.maxRetriesPerRequest ?? null,
154
+ });
155
+ },
156
+ };
157
+ }
158
+ /**
159
+ * Create async configuration provider.
160
+ */
161
+ static createAsyncConfigProvider(options) {
162
+ return {
163
+ provide: services_1.ATOMIC_QUEUES_CONFIG,
164
+ useFactory: options.useFactory,
165
+ inject: (options.inject || []),
166
+ };
167
+ }
168
+ /**
169
+ * Create async Redis provider.
170
+ */
171
+ static createAsyncRedisProvider() {
172
+ return {
173
+ provide: services_1.ATOMIC_QUEUES_REDIS,
174
+ useFactory: (config) => {
175
+ if (config.redis.url) {
176
+ return new ioredis_1.default(config.redis.url, {
177
+ maxRetriesPerRequest: config.redis.maxRetriesPerRequest ?? null,
178
+ });
179
+ }
180
+ return new ioredis_1.default({
181
+ host: config.redis.host || 'localhost',
182
+ port: config.redis.port || 6379,
183
+ password: config.redis.password,
184
+ db: config.redis.db,
185
+ maxRetriesPerRequest: config.redis.maxRetriesPerRequest ?? null,
186
+ });
187
+ },
188
+ inject: [services_1.ATOMIC_QUEUES_CONFIG],
189
+ };
190
+ }
191
+ };
192
+ exports.AtomicQueuesModule = AtomicQueuesModule;
193
+ exports.AtomicQueuesModule = AtomicQueuesModule = AtomicQueuesModule_1 = __decorate([
194
+ (0, common_1.Global)(),
195
+ (0, common_1.Module)({})
196
+ ], AtomicQueuesModule);
197
+ //# sourceMappingURL=atomic-queues.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atomic-queues.module.js","sourceRoot":"","sources":["../../src/module/atomic-queues.module.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export * from './atomic-queues.module';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/module/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./atomic-queues.module"), exports);
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/module/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yDAAuC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Injection tokens for AtomicQueues module
3
+ */
4
+ /** Redis client injection token */
5
+ export declare const ATOMIC_QUEUES_REDIS: unique symbol;
6
+ /** Module configuration injection token */
7
+ export declare const ATOMIC_QUEUES_CONFIG: unique symbol;
8
+ /** Async module options injection token */
9
+ export declare const ATOMIC_QUEUES_MODULE_OPTIONS: unique symbol;
10
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/services/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,mCAAmC;AACnC,eAAO,MAAM,mBAAmB,eAAgC,CAAC;AAEjE,2CAA2C;AAC3C,eAAO,MAAM,oBAAoB,eAAiC,CAAC;AAEnE,2CAA2C;AAC3C,eAAO,MAAM,4BAA4B,eAAyC,CAAC"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ /**
3
+ * Injection tokens for AtomicQueues module
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ATOMIC_QUEUES_MODULE_OPTIONS = exports.ATOMIC_QUEUES_CONFIG = exports.ATOMIC_QUEUES_REDIS = void 0;
7
+ /** Redis client injection token */
8
+ exports.ATOMIC_QUEUES_REDIS = Symbol('ATOMIC_QUEUES_REDIS');
9
+ /** Module configuration injection token */
10
+ exports.ATOMIC_QUEUES_CONFIG = Symbol('ATOMIC_QUEUES_CONFIG');
11
+ /** Async module options injection token */
12
+ exports.ATOMIC_QUEUES_MODULE_OPTIONS = Symbol('ATOMIC_QUEUES_MODULE_OPTIONS');
13
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/services/constants.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,mCAAmC;AACtB,QAAA,mBAAmB,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAEjE,2CAA2C;AAC9B,QAAA,oBAAoB,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAC;AAEnE,2CAA2C;AAC9B,QAAA,4BAA4B,GAAG,MAAM,CAAC,8BAA8B,CAAC,CAAC"}
@@ -0,0 +1,188 @@
1
+ import { OnModuleDestroy } from '@nestjs/common';
2
+ import Redis from 'ioredis';
3
+ import { ICronManager, IEntityScalingConfig, IScalingDecision, IAtomicQueuesModuleConfig } from '../../domain';
4
+ import { WorkerManagerService } from '../worker-manager';
5
+ import { IndexManagerService } from '../index-manager';
6
+ import { ServiceQueueManager } from '../service-queue';
7
+ /**
8
+ * CronManagerService
9
+ *
10
+ * Manages worker lifecycle through periodic scaling cycles.
11
+ * Implements the patterns from both Whatsapi's CronqProcessor and
12
+ * bl-blackjack-service's WorkerManagerProcessor.
13
+ *
14
+ * Key Features:
15
+ * - Automatic worker spawning when jobs are queued
16
+ * - Worker termination when queues are empty
17
+ * - Concurrency limits based on entity configuration
18
+ * - Queue cleanup after all work is done
19
+ * - Excess worker handling
20
+ *
21
+ * Architecture:
22
+ * - Runs on a configurable interval
23
+ * - Each entity type can register its own scaling logic
24
+ * - Supports per-entity concurrency limits
25
+ * - Integrates with WorkerManager for worker lifecycle
26
+ * - Integrates with IndexManager for state tracking
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * // Register entity scaling configuration
31
+ * cronManager.registerEntityType({
32
+ * entityType: 'user',
33
+ * getDesiredWorkerCount: async (userId) => {
34
+ * const plan = await getUserPlan(userId);
35
+ * return planConcurrencyMap[plan];
36
+ * },
37
+ * getActiveEntityIds: async () => {
38
+ * return indexManager.getEntitiesWithJobs('user');
39
+ * },
40
+ * maxWorkersPerEntity: 5,
41
+ * onSpawnWorker: async (userId) => {
42
+ * await commandBus.execute(new CreateUserWorkerCommand(userId));
43
+ * },
44
+ * });
45
+ *
46
+ * // Start the cron manager
47
+ * cronManager.start(5000); // Run every 5 seconds
48
+ * ```
49
+ */
50
+ export declare class CronManagerService implements ICronManager, OnModuleDestroy {
51
+ private readonly redis;
52
+ private readonly config;
53
+ private readonly workerManager;
54
+ private readonly indexManager;
55
+ private readonly serviceQueueManager?;
56
+ private readonly logger;
57
+ private readonly entityConfigs;
58
+ private cronInterval;
59
+ private running;
60
+ private readonly keyPrefix;
61
+ private readonly useServiceQueue;
62
+ private scalingHandlerRegistered;
63
+ constructor(redis: Redis, config: IAtomicQueuesModuleConfig, workerManager: WorkerManagerService, indexManager: IndexManagerService, serviceQueueManager?: ServiceQueueManager | undefined);
64
+ /**
65
+ * Register the scaling cycle handler with ServiceQueueManager.
66
+ * This ensures scaling cycles are processed atomically by the service worker.
67
+ */
68
+ private registerScalingHandler;
69
+ /**
70
+ * Register an entity type for automatic scaling.
71
+ */
72
+ registerEntityType(config: IEntityScalingConfig): void;
73
+ /**
74
+ * Unregister an entity type.
75
+ */
76
+ unregisterEntityType(entityType: string): void;
77
+ /**
78
+ * Run a scaling cycle for all registered entity types.
79
+ *
80
+ * When service queue is enabled, this triggers scaling cycles through the
81
+ * service queue to ensure atomic processing by the single service worker.
82
+ * This prevents race conditions in distributed deployments.
83
+ *
84
+ * IMPORTANT: Only the service worker owner node triggers scaling cycles.
85
+ * Other nodes skip the trigger to prevent duplicate jobs.
86
+ *
87
+ * This is the main logic that:
88
+ * 1. Gets entities with queued jobs
89
+ * 2. Gets entities with running workers
90
+ * 3. Calculates scaling decisions
91
+ * 4. Spawns missing workers
92
+ * 5. Terminates excess workers
93
+ * 6. Cleans up empty queues
94
+ */
95
+ runScalingCycle(): Promise<IScalingDecision[]>;
96
+ /**
97
+ * Trigger scaling cycles through the service queue.
98
+ * This ensures only the service worker processes scaling decisions.
99
+ */
100
+ private triggerScalingCyclesThroughServiceQueue;
101
+ /**
102
+ * Run scaling cycles directly (single instance or fallback mode).
103
+ */
104
+ private runScalingCycleDirectly;
105
+ /**
106
+ * Get current scaling state for all entity types.
107
+ */
108
+ getScalingState(): Promise<Map<string, IScalingDecision[]>>;
109
+ /**
110
+ * Start the cron manager.
111
+ */
112
+ start(intervalMs?: number): void;
113
+ /**
114
+ * Stop the cron manager.
115
+ */
116
+ stop(): void;
117
+ /**
118
+ * Check if cron manager is running.
119
+ */
120
+ isRunning(): boolean;
121
+ /**
122
+ * Cleanup on module destroy.
123
+ */
124
+ onModuleDestroy(): void;
125
+ /**
126
+ * Run scaling cycle for a specific entity type.
127
+ * This is the internal implementation called either directly or via service queue.
128
+ */
129
+ private runEntityScalingCycleInternal;
130
+ /**
131
+ * Handle worker spawning for an entity.
132
+ */
133
+ private handleEntitySpawning;
134
+ /**
135
+ * Handle excess workers for an entity.
136
+ */
137
+ private handleExcessWorkers;
138
+ /**
139
+ * Handle worker closure for entities with no jobs.
140
+ * Only terminates workers if the entity's queue is truly empty (no waiting or active jobs).
141
+ */
142
+ private handleWorkerClosure;
143
+ /**
144
+ * Check if a queue has any waiting or active jobs.
145
+ */
146
+ private checkQueueHasJobs;
147
+ /**
148
+ * Handle queue cleanup for entities with no jobs and no workers.
149
+ */
150
+ private handleQueueCleanup;
151
+ /**
152
+ * Queue worker termination via the entity's queue.
153
+ */
154
+ private queueWorkerTermination;
155
+ /**
156
+ * Get the number of workers for an entity.
157
+ * Uses the worker heartbeat TTL keys as the single source of truth.
158
+ * This is a direct Redis query - no service queue needed since we're just reading keys.
159
+ */
160
+ private getEntityWorkerCount;
161
+ /**
162
+ * Get all entities with workers.
163
+ * Uses the worker heartbeat TTL keys as the single source of truth.
164
+ * Worker names follow pattern: {entityId}-worker
165
+ */
166
+ private getEntitiesWithWorkers;
167
+ /**
168
+ * Get pending worker creation requests count.
169
+ */
170
+ private getPendingWorkerCreations;
171
+ /**
172
+ * Increment worker creation request counter.
173
+ */
174
+ private incrementWorkerCreationRequest;
175
+ /**
176
+ * Decrement worker creation request counter.
177
+ */
178
+ decrementWorkerCreationRequest(entityType: string, entityId: string): Promise<void>;
179
+ /**
180
+ * Determine the scaling action based on current vs desired.
181
+ */
182
+ private determineAction;
183
+ /**
184
+ * Scan Redis keys matching a pattern.
185
+ */
186
+ private scanKeys;
187
+ }
188
+ //# sourceMappingURL=cron-manager.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron-manager.service.d.ts","sourceRoot":"","sources":["../../../src/services/cron-manager/cron-manager.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,eAAe,EAAY,MAAM,gBAAgB,CAAC;AACvF,OAAO,KAAK,MAAM,SAAS,CAAC;AAC5B,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,EAChB,yBAAyB,EAC1B,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAwB,MAAM,kBAAkB,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,qBACa,kBAAmB,YAAW,YAAY,EAAE,eAAe;IAUvC,OAAO,CAAC,QAAQ,CAAC,KAAK;IAEnD,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,YAAY;IACjB,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC;IAdnD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;IAC9D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgD;IAC9E,OAAO,CAAC,YAAY,CAA+B;IACnD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAU;IAC1C,OAAO,CAAC,wBAAwB,CAAS;gBAGO,KAAK,EAAE,KAAK,EAEzC,MAAM,EAAE,yBAAyB,EACjC,aAAa,EAAE,oBAAoB,EACnC,YAAY,EAAE,mBAAmB,EACrB,mBAAmB,CAAC,EAAE,mBAAmB,YAAA;IAUxE;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAsB9B;;OAEG;IACH,kBAAkB,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI;IAKtD;;OAEG;IACH,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAK9C;;;;;;;;;;;;;;;;;OAiBG;IACG,eAAe,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAepD;;;OAGG;YACW,uCAAuC;IAYrD;;OAEG;YACW,uBAAuB;IAoBrC;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;IA8BjE;;OAEG;IACH,KAAK,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI;IA0BhC;;OAEG;IACH,IAAI,IAAI,IAAI;IASZ;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,eAAe,IAAI,IAAI;IAQvB;;;OAGG;YACW,6BAA6B;IAmD3C;;OAEG;YACW,oBAAoB;IAsDlC;;OAEG;YACW,mBAAmB;IAuCjC;;;OAGG;YACW,mBAAmB;IA8CjC;;OAEG;YACW,iBAAiB;IAyB/B;;OAEG;YACW,kBAAkB;IAqBhC;;OAEG;YACW,sBAAsB;IAapC;;;;OAIG;YACW,oBAAoB;IAYlC;;;;OAIG;YACW,sBAAsB;IAqBpC;;OAEG;YACW,yBAAyB;IASvC;;OAEG;YACW,8BAA8B;IAS5C;;OAEG;IACG,8BAA8B,CAClC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAShB;;OAEG;IACH,OAAO,CAAC,eAAe;IASvB;;OAEG;YACW,QAAQ;CAkBvB"}