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.
- package/README.md +686 -0
- package/dist/decorators/decorators.d.ts +67 -0
- package/dist/decorators/decorators.d.ts.map +1 -0
- package/dist/decorators/decorators.js +91 -0
- package/dist/decorators/decorators.js.map +1 -0
- package/dist/decorators/index.d.ts +2 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/index.js +18 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/domain/index.d.ts +5 -0
- package/dist/domain/index.d.ts.map +1 -0
- package/dist/domain/index.js +21 -0
- package/dist/domain/index.js.map +1 -0
- package/dist/domain/interfaces.d.ts +614 -0
- package/dist/domain/interfaces.d.ts.map +1 -0
- package/dist/domain/interfaces.js +19 -0
- package/dist/domain/interfaces.js.map +1 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +1 -0
- package/dist/module/atomic-queues.module.d.ts +97 -0
- package/dist/module/atomic-queues.module.d.ts.map +1 -0
- package/dist/module/atomic-queues.module.js +197 -0
- package/dist/module/atomic-queues.module.js.map +1 -0
- package/dist/module/index.d.ts +2 -0
- package/dist/module/index.d.ts.map +1 -0
- package/dist/module/index.js +18 -0
- package/dist/module/index.js.map +1 -0
- package/dist/services/constants.d.ts +10 -0
- package/dist/services/constants.d.ts.map +1 -0
- package/dist/services/constants.js +13 -0
- package/dist/services/constants.js.map +1 -0
- package/dist/services/cron-manager/cron-manager.service.d.ts +188 -0
- package/dist/services/cron-manager/cron-manager.service.d.ts.map +1 -0
- package/dist/services/cron-manager/cron-manager.service.js +534 -0
- package/dist/services/cron-manager/cron-manager.service.js.map +1 -0
- package/dist/services/cron-manager/index.d.ts +2 -0
- package/dist/services/cron-manager/index.d.ts.map +1 -0
- package/dist/services/cron-manager/index.js +18 -0
- package/dist/services/cron-manager/index.js.map +1 -0
- package/dist/services/index-manager/index-manager.service.d.ts +146 -0
- package/dist/services/index-manager/index-manager.service.d.ts.map +1 -0
- package/dist/services/index-manager/index-manager.service.js +337 -0
- package/dist/services/index-manager/index-manager.service.js.map +1 -0
- package/dist/services/index-manager/index.d.ts +2 -0
- package/dist/services/index-manager/index.d.ts.map +1 -0
- package/dist/services/index-manager/index.js +18 -0
- package/dist/services/index-manager/index.js.map +1 -0
- package/dist/services/index.d.ts +10 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +26 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/job-processor/index.d.ts +2 -0
- package/dist/services/job-processor/index.d.ts.map +1 -0
- package/dist/services/job-processor/index.js +18 -0
- package/dist/services/job-processor/index.js.map +1 -0
- package/dist/services/job-processor/job-processor.service.d.ts +156 -0
- package/dist/services/job-processor/job-processor.service.d.ts.map +1 -0
- package/dist/services/job-processor/job-processor.service.js +331 -0
- package/dist/services/job-processor/job-processor.service.js.map +1 -0
- package/dist/services/queue-manager/index.d.ts +2 -0
- package/dist/services/queue-manager/index.d.ts.map +1 -0
- package/dist/services/queue-manager/index.js +18 -0
- package/dist/services/queue-manager/index.js.map +1 -0
- package/dist/services/queue-manager/queue-manager.service.d.ts +128 -0
- package/dist/services/queue-manager/queue-manager.service.d.ts.map +1 -0
- package/dist/services/queue-manager/queue-manager.service.js +308 -0
- package/dist/services/queue-manager/queue-manager.service.js.map +1 -0
- package/dist/services/resource-lock/index.d.ts +2 -0
- package/dist/services/resource-lock/index.d.ts.map +1 -0
- package/dist/services/resource-lock/index.js +18 -0
- package/dist/services/resource-lock/index.js.map +1 -0
- package/dist/services/resource-lock/resource-lock.service.d.ts +124 -0
- package/dist/services/resource-lock/resource-lock.service.d.ts.map +1 -0
- package/dist/services/resource-lock/resource-lock.service.js +379 -0
- package/dist/services/resource-lock/resource-lock.service.js.map +1 -0
- package/dist/services/service-queue/index.d.ts +2 -0
- package/dist/services/service-queue/index.d.ts.map +1 -0
- package/dist/services/service-queue/index.js +18 -0
- package/dist/services/service-queue/index.js.map +1 -0
- package/dist/services/service-queue/service-queue.service.d.ts +232 -0
- package/dist/services/service-queue/service-queue.service.d.ts.map +1 -0
- package/dist/services/service-queue/service-queue.service.js +647 -0
- package/dist/services/service-queue/service-queue.service.js.map +1 -0
- package/dist/services/shutdown-state/index.d.ts +2 -0
- package/dist/services/shutdown-state/index.d.ts.map +1 -0
- package/dist/services/shutdown-state/index.js +18 -0
- package/dist/services/shutdown-state/index.js.map +1 -0
- package/dist/services/shutdown-state/shutdown-state.service.d.ts +69 -0
- package/dist/services/shutdown-state/shutdown-state.service.d.ts.map +1 -0
- package/dist/services/shutdown-state/shutdown-state.service.js +127 -0
- package/dist/services/shutdown-state/shutdown-state.service.js.map +1 -0
- package/dist/services/worker-manager/index.d.ts +2 -0
- package/dist/services/worker-manager/index.d.ts.map +1 -0
- package/dist/services/worker-manager/index.js +18 -0
- package/dist/services/worker-manager/index.js.map +1 -0
- package/dist/services/worker-manager/worker-manager.service.d.ts +163 -0
- package/dist/services/worker-manager/worker-manager.service.d.ts.map +1 -0
- package/dist/services/worker-manager/worker-manager.service.js +460 -0
- package/dist/services/worker-manager/worker-manager.service.js.map +1 -0
- package/dist/utils/helpers.d.ts +124 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/dist/utils/helpers.js +229 -0
- package/dist/utils/helpers.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +18 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +80 -0
|
@@ -0,0 +1,534 @@
|
|
|
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 CronManagerService_1;
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.CronManagerService = void 0;
|
|
20
|
+
const common_1 = require("@nestjs/common");
|
|
21
|
+
const ioredis_1 = __importDefault(require("ioredis"));
|
|
22
|
+
const constants_1 = require("../constants");
|
|
23
|
+
const worker_manager_1 = require("../worker-manager");
|
|
24
|
+
const index_manager_1 = require("../index-manager");
|
|
25
|
+
const service_queue_1 = require("../service-queue");
|
|
26
|
+
/**
|
|
27
|
+
* CronManagerService
|
|
28
|
+
*
|
|
29
|
+
* Manages worker lifecycle through periodic scaling cycles.
|
|
30
|
+
* Implements the patterns from both Whatsapi's CronqProcessor and
|
|
31
|
+
* bl-blackjack-service's WorkerManagerProcessor.
|
|
32
|
+
*
|
|
33
|
+
* Key Features:
|
|
34
|
+
* - Automatic worker spawning when jobs are queued
|
|
35
|
+
* - Worker termination when queues are empty
|
|
36
|
+
* - Concurrency limits based on entity configuration
|
|
37
|
+
* - Queue cleanup after all work is done
|
|
38
|
+
* - Excess worker handling
|
|
39
|
+
*
|
|
40
|
+
* Architecture:
|
|
41
|
+
* - Runs on a configurable interval
|
|
42
|
+
* - Each entity type can register its own scaling logic
|
|
43
|
+
* - Supports per-entity concurrency limits
|
|
44
|
+
* - Integrates with WorkerManager for worker lifecycle
|
|
45
|
+
* - Integrates with IndexManager for state tracking
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* // Register entity scaling configuration
|
|
50
|
+
* cronManager.registerEntityType({
|
|
51
|
+
* entityType: 'user',
|
|
52
|
+
* getDesiredWorkerCount: async (userId) => {
|
|
53
|
+
* const plan = await getUserPlan(userId);
|
|
54
|
+
* return planConcurrencyMap[plan];
|
|
55
|
+
* },
|
|
56
|
+
* getActiveEntityIds: async () => {
|
|
57
|
+
* return indexManager.getEntitiesWithJobs('user');
|
|
58
|
+
* },
|
|
59
|
+
* maxWorkersPerEntity: 5,
|
|
60
|
+
* onSpawnWorker: async (userId) => {
|
|
61
|
+
* await commandBus.execute(new CreateUserWorkerCommand(userId));
|
|
62
|
+
* },
|
|
63
|
+
* });
|
|
64
|
+
*
|
|
65
|
+
* // Start the cron manager
|
|
66
|
+
* cronManager.start(5000); // Run every 5 seconds
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
let CronManagerService = CronManagerService_1 = class CronManagerService {
|
|
70
|
+
constructor(redis, config, workerManager, indexManager, serviceQueueManager) {
|
|
71
|
+
this.redis = redis;
|
|
72
|
+
this.config = config;
|
|
73
|
+
this.workerManager = workerManager;
|
|
74
|
+
this.indexManager = indexManager;
|
|
75
|
+
this.serviceQueueManager = serviceQueueManager;
|
|
76
|
+
this.logger = new common_1.Logger(CronManagerService_1.name);
|
|
77
|
+
this.entityConfigs = new Map();
|
|
78
|
+
this.cronInterval = null;
|
|
79
|
+
this.running = false;
|
|
80
|
+
this.scalingHandlerRegistered = false;
|
|
81
|
+
this.keyPrefix = config.keyPrefix || 'aq';
|
|
82
|
+
// Use service queue for atomic operations if enabled
|
|
83
|
+
this.useServiceQueue = config.serviceQueue?.enabled !== false;
|
|
84
|
+
// Register the scaling cycle handler with the service queue
|
|
85
|
+
this.registerScalingHandler();
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Register the scaling cycle handler with ServiceQueueManager.
|
|
89
|
+
* This ensures scaling cycles are processed atomically by the service worker.
|
|
90
|
+
*/
|
|
91
|
+
registerScalingHandler() {
|
|
92
|
+
if (this.scalingHandlerRegistered || !this.serviceQueueManager) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
this.serviceQueueManager.registerScalingCycleHandler(async (entityType) => {
|
|
96
|
+
const config = this.entityConfigs.get(entityType);
|
|
97
|
+
if (!config) {
|
|
98
|
+
this.logger.warn(`No config registered for entity type: ${entityType}`);
|
|
99
|
+
return { decisions: [] };
|
|
100
|
+
}
|
|
101
|
+
const decisions = await this.runEntityScalingCycleInternal(entityType, config);
|
|
102
|
+
return { decisions };
|
|
103
|
+
});
|
|
104
|
+
this.scalingHandlerRegistered = true;
|
|
105
|
+
this.logger.debug('Scaling cycle handler registered with ServiceQueueManager');
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Register an entity type for automatic scaling.
|
|
109
|
+
*/
|
|
110
|
+
registerEntityType(config) {
|
|
111
|
+
this.entityConfigs.set(config.entityType, config);
|
|
112
|
+
this.logger.log(`Registered entity type for scaling: ${config.entityType}`);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Unregister an entity type.
|
|
116
|
+
*/
|
|
117
|
+
unregisterEntityType(entityType) {
|
|
118
|
+
this.entityConfigs.delete(entityType);
|
|
119
|
+
this.logger.log(`Unregistered entity type: ${entityType}`);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Run a scaling cycle for all registered entity types.
|
|
123
|
+
*
|
|
124
|
+
* When service queue is enabled, this triggers scaling cycles through the
|
|
125
|
+
* service queue to ensure atomic processing by the single service worker.
|
|
126
|
+
* This prevents race conditions in distributed deployments.
|
|
127
|
+
*
|
|
128
|
+
* IMPORTANT: Only the service worker owner node triggers scaling cycles.
|
|
129
|
+
* Other nodes skip the trigger to prevent duplicate jobs.
|
|
130
|
+
*
|
|
131
|
+
* This is the main logic that:
|
|
132
|
+
* 1. Gets entities with queued jobs
|
|
133
|
+
* 2. Gets entities with running workers
|
|
134
|
+
* 3. Calculates scaling decisions
|
|
135
|
+
* 4. Spawns missing workers
|
|
136
|
+
* 5. Terminates excess workers
|
|
137
|
+
* 6. Cleans up empty queues
|
|
138
|
+
*/
|
|
139
|
+
async runScalingCycle() {
|
|
140
|
+
// If service queue is enabled, only the service worker owner should trigger
|
|
141
|
+
if (this.useServiceQueue && this.serviceQueueManager) {
|
|
142
|
+
// Only trigger if we're the service worker owner
|
|
143
|
+
if (this.serviceQueueManager.isServiceWorkerOwner()) {
|
|
144
|
+
await this.triggerScalingCyclesThroughServiceQueue();
|
|
145
|
+
}
|
|
146
|
+
// Return empty - actual decisions are processed by service worker
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
// Fallback to direct processing (single instance mode)
|
|
150
|
+
return this.runScalingCycleDirectly();
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Trigger scaling cycles through the service queue.
|
|
154
|
+
* This ensures only the service worker processes scaling decisions.
|
|
155
|
+
*/
|
|
156
|
+
async triggerScalingCyclesThroughServiceQueue() {
|
|
157
|
+
for (const entityType of this.entityConfigs.keys()) {
|
|
158
|
+
try {
|
|
159
|
+
await this.serviceQueueManager.triggerScalingCycle(entityType);
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
this.logger.error(`Failed to trigger scaling cycle for ${entityType}: ${error.message}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Run scaling cycles directly (single instance or fallback mode).
|
|
168
|
+
*/
|
|
169
|
+
async runScalingCycleDirectly() {
|
|
170
|
+
const decisions = [];
|
|
171
|
+
for (const [entityType, config] of this.entityConfigs) {
|
|
172
|
+
try {
|
|
173
|
+
const entityDecisions = await this.runEntityScalingCycleInternal(entityType, config);
|
|
174
|
+
decisions.push(...entityDecisions);
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
this.logger.error(`Error in scaling cycle for ${entityType}: ${error.message}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return decisions;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Get current scaling state for all entity types.
|
|
184
|
+
*/
|
|
185
|
+
async getScalingState() {
|
|
186
|
+
const state = new Map();
|
|
187
|
+
for (const [entityType, config] of this.entityConfigs) {
|
|
188
|
+
const entityIds = await config.getActiveEntityIds();
|
|
189
|
+
const decisions = [];
|
|
190
|
+
for (const entityId of entityIds) {
|
|
191
|
+
const currentWorkers = await this.getEntityWorkerCount(entityType, entityId);
|
|
192
|
+
const desiredWorkers = await config.getDesiredWorkerCount(entityId);
|
|
193
|
+
decisions.push({
|
|
194
|
+
entityId,
|
|
195
|
+
entityType,
|
|
196
|
+
currentWorkers,
|
|
197
|
+
desiredWorkers,
|
|
198
|
+
action: this.determineAction(currentWorkers, desiredWorkers),
|
|
199
|
+
count: Math.abs(desiredWorkers - currentWorkers),
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
state.set(entityType, decisions);
|
|
203
|
+
}
|
|
204
|
+
return state;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Start the cron manager.
|
|
208
|
+
*/
|
|
209
|
+
start(intervalMs) {
|
|
210
|
+
if (this.running) {
|
|
211
|
+
this.logger.warn('CronManager is already running');
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const interval = intervalMs || this.config.cronInterval || 5000;
|
|
215
|
+
this.logger.log(`Starting CronManager with ${interval}ms interval`);
|
|
216
|
+
this.running = true;
|
|
217
|
+
// Run immediately once
|
|
218
|
+
this.runScalingCycle().catch((error) => {
|
|
219
|
+
this.logger.error(`Initial scaling cycle failed: ${error.message}`);
|
|
220
|
+
});
|
|
221
|
+
// Then run on interval
|
|
222
|
+
this.cronInterval = setInterval(async () => {
|
|
223
|
+
try {
|
|
224
|
+
await this.runScalingCycle();
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
this.logger.error(`Scaling cycle failed: ${error.message}`);
|
|
228
|
+
}
|
|
229
|
+
}, interval);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Stop the cron manager.
|
|
233
|
+
*/
|
|
234
|
+
stop() {
|
|
235
|
+
if (this.cronInterval) {
|
|
236
|
+
clearInterval(this.cronInterval);
|
|
237
|
+
this.cronInterval = null;
|
|
238
|
+
}
|
|
239
|
+
this.running = false;
|
|
240
|
+
this.logger.log('CronManager stopped');
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Check if cron manager is running.
|
|
244
|
+
*/
|
|
245
|
+
isRunning() {
|
|
246
|
+
return this.running;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Cleanup on module destroy.
|
|
250
|
+
*/
|
|
251
|
+
onModuleDestroy() {
|
|
252
|
+
this.stop();
|
|
253
|
+
}
|
|
254
|
+
// =========================================================================
|
|
255
|
+
// PRIVATE METHODS
|
|
256
|
+
// =========================================================================
|
|
257
|
+
/**
|
|
258
|
+
* Run scaling cycle for a specific entity type.
|
|
259
|
+
* This is the internal implementation called either directly or via service queue.
|
|
260
|
+
*/
|
|
261
|
+
async runEntityScalingCycleInternal(entityType, config) {
|
|
262
|
+
const decisions = [];
|
|
263
|
+
// Get active entities from the config's getActiveEntityIds (primary source)
|
|
264
|
+
const activeEntityIds = await config.getActiveEntityIds();
|
|
265
|
+
// Get entities with running workers
|
|
266
|
+
const entitiesWithWorkers = await this.getEntitiesWithWorkers(entityType);
|
|
267
|
+
// Spawn missing workers for active entities
|
|
268
|
+
for (const entityId of activeEntityIds) {
|
|
269
|
+
const decision = await this.handleEntitySpawning(entityType, entityId, config, 1);
|
|
270
|
+
if (decision)
|
|
271
|
+
decisions.push(decision);
|
|
272
|
+
}
|
|
273
|
+
// Handle excess workers for active entities
|
|
274
|
+
for (const entityId of activeEntityIds) {
|
|
275
|
+
const decision = await this.handleExcessWorkers(entityType, entityId, config);
|
|
276
|
+
if (decision)
|
|
277
|
+
decisions.push(decision);
|
|
278
|
+
}
|
|
279
|
+
// Close workers for entities with workers but no longer active
|
|
280
|
+
const activeEntitySet = new Set(activeEntityIds);
|
|
281
|
+
const entitiesWithWorkersNoLongerActive = Array.from(entitiesWithWorkers).filter((entityId) => !activeEntitySet.has(entityId));
|
|
282
|
+
for (const entityId of entitiesWithWorkersNoLongerActive) {
|
|
283
|
+
const decision = await this.handleWorkerClosure(entityType, entityId, config);
|
|
284
|
+
if (decision)
|
|
285
|
+
decisions.push(decision);
|
|
286
|
+
}
|
|
287
|
+
return decisions;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Handle worker spawning for an entity.
|
|
291
|
+
*/
|
|
292
|
+
async handleEntitySpawning(entityType, entityId, config, queuedJobCount) {
|
|
293
|
+
const currentWorkers = await this.getEntityWorkerCount(entityType, entityId);
|
|
294
|
+
const desiredWorkers = await config.getDesiredWorkerCount(entityId);
|
|
295
|
+
const maxWorkers = config.maxWorkersPerEntity || desiredWorkers;
|
|
296
|
+
// Calculate how many workers we should have
|
|
297
|
+
const targetWorkers = Math.min(desiredWorkers, maxWorkers, queuedJobCount);
|
|
298
|
+
if (currentWorkers >= targetWorkers) {
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
const toSpawn = targetWorkers - currentWorkers;
|
|
302
|
+
this.logger.debug(`Spawning ${toSpawn} workers for ${entityType}/${entityId}`);
|
|
303
|
+
// Track worker creation requests to avoid over-spawning
|
|
304
|
+
const pendingCreations = await this.getPendingWorkerCreations(entityType, entityId);
|
|
305
|
+
const actualToSpawn = Math.max(0, toSpawn - pendingCreations);
|
|
306
|
+
for (let i = 0; i < actualToSpawn; i++) {
|
|
307
|
+
await this.incrementWorkerCreationRequest(entityType, entityId);
|
|
308
|
+
if (config.onSpawnWorker) {
|
|
309
|
+
try {
|
|
310
|
+
await config.onSpawnWorker(entityId);
|
|
311
|
+
}
|
|
312
|
+
catch (error) {
|
|
313
|
+
this.logger.error(`Failed to spawn worker for ${entityType}/${entityId}: ${error.message}`);
|
|
314
|
+
await this.decrementWorkerCreationRequest(entityType, entityId);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return {
|
|
319
|
+
entityId,
|
|
320
|
+
entityType,
|
|
321
|
+
currentWorkers,
|
|
322
|
+
desiredWorkers: targetWorkers,
|
|
323
|
+
action: 'spawn',
|
|
324
|
+
count: actualToSpawn,
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Handle excess workers for an entity.
|
|
329
|
+
*/
|
|
330
|
+
async handleExcessWorkers(entityType, entityId, config) {
|
|
331
|
+
const currentWorkers = await this.getEntityWorkerCount(entityType, entityId);
|
|
332
|
+
const desiredWorkers = await config.getDesiredWorkerCount(entityId);
|
|
333
|
+
const maxWorkers = config.maxWorkersPerEntity || desiredWorkers;
|
|
334
|
+
if (currentWorkers <= maxWorkers) {
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
const excess = currentWorkers - maxWorkers;
|
|
338
|
+
this.logger.debug(`Terminating ${excess} excess workers for ${entityType}/${entityId}`);
|
|
339
|
+
// Queue worker termination
|
|
340
|
+
const pendingDeaths = await this.indexManager.getQueuedWorkerDeaths(entityType, entityId);
|
|
341
|
+
if (pendingDeaths.length === 0 && excess > 0) {
|
|
342
|
+
await this.queueWorkerTermination(entityType, entityId, config);
|
|
343
|
+
}
|
|
344
|
+
return {
|
|
345
|
+
entityId,
|
|
346
|
+
entityType,
|
|
347
|
+
currentWorkers,
|
|
348
|
+
desiredWorkers: maxWorkers,
|
|
349
|
+
action: 'terminate',
|
|
350
|
+
count: excess,
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Handle worker closure for entities with no jobs.
|
|
355
|
+
* Only terminates workers if the entity's queue is truly empty (no waiting or active jobs).
|
|
356
|
+
*/
|
|
357
|
+
async handleWorkerClosure(entityType, entityId, config) {
|
|
358
|
+
const workers = await this.workerManager.getEntityWorkers(entityType, entityId);
|
|
359
|
+
if (workers.length === 0) {
|
|
360
|
+
return null;
|
|
361
|
+
}
|
|
362
|
+
// Check if there are pending or active jobs in the queue
|
|
363
|
+
// Don't terminate workers that might still be processing jobs
|
|
364
|
+
const queueName = `${entityId}-queue`;
|
|
365
|
+
const hasActiveJobs = await this.checkQueueHasJobs(queueName);
|
|
366
|
+
if (hasActiveJobs) {
|
|
367
|
+
this.logger.debug(`Skipping worker closure for ${entityType}/${entityId} - queue has active jobs`);
|
|
368
|
+
return null;
|
|
369
|
+
}
|
|
370
|
+
this.logger.debug(`Closing ${workers.length} workers for empty ${entityType}/${entityId}`);
|
|
371
|
+
// Signal all workers to close
|
|
372
|
+
for (const workerId of workers) {
|
|
373
|
+
if (config.onTerminateWorker) {
|
|
374
|
+
await config.onTerminateWorker(entityId, workerId);
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
await this.workerManager.signalWorkerClose(workerId);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return {
|
|
381
|
+
entityId,
|
|
382
|
+
entityType,
|
|
383
|
+
currentWorkers: workers.length,
|
|
384
|
+
desiredWorkers: 0,
|
|
385
|
+
action: 'terminate',
|
|
386
|
+
count: workers.length,
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Check if a queue has any waiting or active jobs.
|
|
391
|
+
*/
|
|
392
|
+
async checkQueueHasJobs(queueName) {
|
|
393
|
+
try {
|
|
394
|
+
// Check waiting list
|
|
395
|
+
const waitingKey = `bull:${queueName}:waiting`;
|
|
396
|
+
const waitingCount = await this.redis.llen(waitingKey);
|
|
397
|
+
if (waitingCount > 0)
|
|
398
|
+
return true;
|
|
399
|
+
// Check active list
|
|
400
|
+
const activeKey = `bull:${queueName}:active`;
|
|
401
|
+
const activeCount = await this.redis.llen(activeKey);
|
|
402
|
+
if (activeCount > 0)
|
|
403
|
+
return true;
|
|
404
|
+
// Check delayed set
|
|
405
|
+
const delayedKey = `bull:${queueName}:delayed`;
|
|
406
|
+
const delayedCount = await this.redis.zcard(delayedKey);
|
|
407
|
+
if (delayedCount > 0)
|
|
408
|
+
return true;
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
411
|
+
catch (error) {
|
|
412
|
+
this.logger.warn(`Error checking queue ${queueName} for jobs: ${error.message}`);
|
|
413
|
+
// If we can't check, don't terminate (safer)
|
|
414
|
+
return true;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Handle queue cleanup for entities with no jobs and no workers.
|
|
419
|
+
*/
|
|
420
|
+
async handleQueueCleanup(entityType, entityId) {
|
|
421
|
+
// Check if there's already a queue death queued
|
|
422
|
+
const pendingQueueDeaths = await this.indexManager.getEntitiesWithQueuedQueueDeaths(entityType);
|
|
423
|
+
if (pendingQueueDeaths.includes(entityId)) {
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
this.logger.debug(`Cleaning up queue for ${entityType}/${entityId}`);
|
|
427
|
+
// Index the queue death
|
|
428
|
+
await this.indexManager.indexQueueDeath(entityType, entityId);
|
|
429
|
+
// The actual queue cleanup should be handled by a separate processor
|
|
430
|
+
// or by the entity's cleanup callback
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Queue worker termination via the entity's queue.
|
|
434
|
+
*/
|
|
435
|
+
async queueWorkerTermination(entityType, entityId, config) {
|
|
436
|
+
// This is a placeholder - actual implementation would queue a SIGTERM
|
|
437
|
+
// job to the entity's queue, which the worker would pick up and
|
|
438
|
+
// gracefully terminate itself (like in Whatsapi)
|
|
439
|
+
this.logger.debug(`Queued worker termination for ${entityType}/${entityId}`);
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Get the number of workers for an entity.
|
|
443
|
+
* Uses the worker heartbeat TTL keys as the single source of truth.
|
|
444
|
+
* This is a direct Redis query - no service queue needed since we're just reading keys.
|
|
445
|
+
*/
|
|
446
|
+
async getEntityWorkerCount(entityType, entityId) {
|
|
447
|
+
// Direct query to worker heartbeat TTL keys - the single source of truth
|
|
448
|
+
const workers = await this.workerManager.getEntityWorkers(entityType, entityId);
|
|
449
|
+
return workers.length;
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Get all entities with workers.
|
|
453
|
+
* Uses the worker heartbeat TTL keys as the single source of truth.
|
|
454
|
+
* Worker names follow pattern: {entityId}-worker
|
|
455
|
+
*/
|
|
456
|
+
async getEntitiesWithWorkers(entityType) {
|
|
457
|
+
// Worker heartbeat keys follow pattern: {prefix}:worker:{nodeId}:{entityId}-worker
|
|
458
|
+
const pattern = `${this.keyPrefix}:worker:*:*-worker`;
|
|
459
|
+
const keys = await this.scanKeys(pattern);
|
|
460
|
+
const entities = new Set();
|
|
461
|
+
for (const key of keys) {
|
|
462
|
+
const parts = key.split(':');
|
|
463
|
+
if (parts.length >= 4) {
|
|
464
|
+
// workerName is last part, extract entityId by removing '-worker' suffix
|
|
465
|
+
const workerName = parts[parts.length - 1];
|
|
466
|
+
if (workerName.endsWith('-worker')) {
|
|
467
|
+
const entityId = workerName.slice(0, -7); // Remove '-worker' suffix
|
|
468
|
+
entities.add(entityId);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
return entities;
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Get pending worker creation requests count.
|
|
476
|
+
*/
|
|
477
|
+
async getPendingWorkerCreations(entityType, entityId) {
|
|
478
|
+
const key = `${this.keyPrefix}:worker-creation:${entityType}:${entityId}`;
|
|
479
|
+
const count = await this.redis.get(key);
|
|
480
|
+
return count ? parseInt(count, 10) : 0;
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Increment worker creation request counter.
|
|
484
|
+
*/
|
|
485
|
+
async incrementWorkerCreationRequest(entityType, entityId) {
|
|
486
|
+
const key = `${this.keyPrefix}:worker-creation:${entityType}:${entityId}`;
|
|
487
|
+
await this.redis.incr(key);
|
|
488
|
+
await this.redis.expire(key, 60); // TTL for cleanup
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Decrement worker creation request counter.
|
|
492
|
+
*/
|
|
493
|
+
async decrementWorkerCreationRequest(entityType, entityId) {
|
|
494
|
+
const key = `${this.keyPrefix}:worker-creation:${entityType}:${entityId}`;
|
|
495
|
+
const current = await this.redis.get(key);
|
|
496
|
+
if (current && parseInt(current, 10) > 0) {
|
|
497
|
+
await this.redis.decr(key);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Determine the scaling action based on current vs desired.
|
|
502
|
+
*/
|
|
503
|
+
determineAction(current, desired) {
|
|
504
|
+
if (current < desired)
|
|
505
|
+
return 'spawn';
|
|
506
|
+
if (current > desired)
|
|
507
|
+
return 'terminate';
|
|
508
|
+
return 'none';
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Scan Redis keys matching a pattern.
|
|
512
|
+
*/
|
|
513
|
+
async scanKeys(pattern) {
|
|
514
|
+
let cursor = '0';
|
|
515
|
+
const keys = [];
|
|
516
|
+
do {
|
|
517
|
+
const [nextCursor, scanKeys] = await this.redis.scan(cursor, 'MATCH', pattern, 'COUNT', 100);
|
|
518
|
+
cursor = nextCursor;
|
|
519
|
+
keys.push(...scanKeys);
|
|
520
|
+
} while (cursor !== '0');
|
|
521
|
+
return keys;
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
exports.CronManagerService = CronManagerService;
|
|
525
|
+
exports.CronManagerService = CronManagerService = CronManagerService_1 = __decorate([
|
|
526
|
+
(0, common_1.Injectable)(),
|
|
527
|
+
__param(0, (0, common_1.Inject)(constants_1.ATOMIC_QUEUES_REDIS)),
|
|
528
|
+
__param(1, (0, common_1.Inject)(constants_1.ATOMIC_QUEUES_CONFIG)),
|
|
529
|
+
__param(4, (0, common_1.Optional)()),
|
|
530
|
+
__metadata("design:paramtypes", [ioredis_1.default, Object, worker_manager_1.WorkerManagerService,
|
|
531
|
+
index_manager_1.IndexManagerService,
|
|
532
|
+
service_queue_1.ServiceQueueManager])
|
|
533
|
+
], CronManagerService);
|
|
534
|
+
//# sourceMappingURL=cron-manager.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-manager.service.js","sourceRoot":"","sources":["../../../src/services/cron-manager/cron-manager.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAAA,2CAAuF;AACvF,sDAA4B;AAO5B,4CAAyE;AACzE,sDAAyD;AACzD,oDAAuD;AACvD,oDAA6E;AAE7E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEI,IAAM,kBAAkB,0BAAxB,MAAM,kBAAkB;IAS7B,YAC+B,KAA6B,EAE1D,MAAkD,EACjC,aAAmC,EACnC,YAAiC,EACtC,mBAA0D;QALxB,UAAK,GAAL,KAAK,CAAO;QAEzC,WAAM,GAAN,MAAM,CAA2B;QACjC,kBAAa,GAAb,aAAa,CAAsB;QACnC,iBAAY,GAAZ,YAAY,CAAqB;QACrB,wBAAmB,GAAnB,mBAAmB,CAAsB;QAdvD,WAAM,GAAG,IAAI,eAAM,CAAC,oBAAkB,CAAC,IAAI,CAAC,CAAC;QAC7C,kBAAa,GAAsC,IAAI,GAAG,EAAE,CAAC;QACtE,iBAAY,GAA0B,IAAI,CAAC;QAC3C,YAAO,GAAG,KAAK,CAAC;QAGhB,6BAAwB,GAAG,KAAK,CAAC;QAUvC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,IAAI,CAAC;QAC1C,qDAAqD;QACrD,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC,YAAY,EAAE,OAAO,KAAK,KAAK,CAAC;QAE9D,4DAA4D;QAC5D,IAAI,CAAC,sBAAsB,EAAE,CAAC;IAChC,CAAC;IAED;;;OAGG;IACK,sBAAsB;QAC5B,IAAI,IAAI,CAAC,wBAAwB,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC/D,OAAO;QACT,CAAC;QAED,IAAI,CAAC,mBAAmB,CAAC,2BAA2B,CAClD,KAAK,EAAE,UAAkB,EAAE,EAAE;YAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAClD,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,yCAAyC,UAAU,EAAE,CAAC,CAAC;gBACxE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;YAC3B,CAAC;YAED,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,6BAA6B,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YAC/E,OAAO,EAAE,SAAS,EAAE,CAAC;QACvB,CAAC,CACF,CAAC;QAEF,IAAI,CAAC,wBAAwB,GAAG,IAAI,CAAC;QACrC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;IACjF,CAAC;IAED;;OAEG;IACH,kBAAkB,CAAC,MAA4B;QAC7C,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAClD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,uCAAuC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED;;OAEG;IACH,oBAAoB,CAAC,UAAkB;QACrC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,6BAA6B,UAAU,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,CAAC,eAAe;QACnB,4EAA4E;QAC5E,IAAI,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACrD,iDAAiD;YACjD,IAAI,IAAI,CAAC,mBAAmB,CAAC,oBAAoB,EAAE,EAAE,CAAC;gBACpD,MAAM,IAAI,CAAC,uCAAuC,EAAE,CAAC;YACvD,CAAC;YACD,kEAAkE;YAClE,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,uDAAuD;QACvD,OAAO,IAAI,CAAC,uBAAuB,EAAE,CAAC;IACxC,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,uCAAuC;QACnD,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC;YACnD,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,mBAAoB,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;YAClE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,uCAAuC,UAAU,KAAM,KAAe,CAAC,OAAO,EAAE,CACjF,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,uBAAuB;QACnC,MAAM,SAAS,GAAuB,EAAE,CAAC;QAEzC,KAAK,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACtD,IAAI,CAAC;gBACH,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,6BAA6B,CAC9D,UAAU,EACV,MAAM,CACP,CAAC;gBACF,SAAS,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,CAAC;YACrC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,8BAA8B,UAAU,KAAM,KAAe,CAAC,OAAO,EAAE,CACxE,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe;QACnB,MAAM,KAAK,GAAG,IAAI,GAAG,EAA8B,CAAC;QAEpD,KAAK,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACtD,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,kBAAkB,EAAE,CAAC;YACpD,MAAM,SAAS,GAAuB,EAAE,CAAC;YAEzC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBACjC,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,oBAAoB,CACpD,UAAU,EACV,QAAQ,CACT,CAAC;gBACF,MAAM,cAAc,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;gBAEpE,SAAS,CAAC,IAAI,CAAC;oBACb,QAAQ;oBACR,UAAU;oBACV,cAAc;oBACd,cAAc;oBACd,MAAM,EAAE,IAAI,CAAC,eAAe,CAAC,cAAc,EAAE,cAAc,CAAC;oBAC5D,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,cAAc,GAAG,cAAc,CAAC;iBACjD,CAAC,CAAC;YACL,CAAC;YAED,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QACnC,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAmB;QACvB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;YACnD,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,UAAU,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,IAAI,CAAC;QAEhE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,6BAA6B,QAAQ,aAAa,CAAC,CAAC;QACpE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QAEpB,uBAAuB;QACvB,IAAI,CAAC,eAAe,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACrC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,iCAAiC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;QAEH,uBAAuB;QACvB,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;YACzC,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;YAC/B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,yBAA0B,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;YACzE,CAAC;QACH,CAAC,EAAE,QAAQ,CAAC,CAAC;IACf,CAAC;IAED;;OAEG;IACH,IAAI;QACF,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACjC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QAC3B,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,SAAS;QACP,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,eAAe;QACb,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAED,4EAA4E;IAC5E,kBAAkB;IAClB,4EAA4E;IAE5E;;;OAGG;IACK,KAAK,CAAC,6BAA6B,CACzC,UAAkB,EAClB,MAA4B;QAE5B,MAAM,SAAS,GAAuB,EAAE,CAAC;QAEzC,4EAA4E;QAC5E,MAAM,eAAe,GAAG,MAAM,MAAM,CAAC,kBAAkB,EAAE,CAAC;QAE1D,oCAAoC;QACpC,MAAM,mBAAmB,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,CAAC;QAE1E,4CAA4C;QAC5C,KAAK,MAAM,QAAQ,IAAI,eAAe,EAAE,CAAC;YACvC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAC9C,UAAU,EACV,QAAQ,EACR,MAAM,EACN,CAAC,CACF,CAAC;YACF,IAAI,QAAQ;gBAAE,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzC,CAAC;QAED,4CAA4C;QAC5C,KAAK,MAAM,QAAQ,IAAI,eAAe,EAAE,CAAC;YACvC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAC7C,UAAU,EACV,QAAQ,EACR,MAAM,CACP,CAAC;YACF,IAAI,QAAQ;gBAAE,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzC,CAAC;QAED,+DAA+D;QAC/D,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,CAAC;QACjD,MAAM,iCAAiC,GAAG,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,MAAM,CAC9E,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAC7C,CAAC;QAEF,KAAK,MAAM,QAAQ,IAAI,iCAAiC,EAAE,CAAC;YACzD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAC7C,UAAU,EACV,QAAQ,EACR,MAAM,CACP,CAAC;YACF,IAAI,QAAQ;gBAAE,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzC,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,oBAAoB,CAChC,UAAkB,EAClB,QAAgB,EAChB,MAA4B,EAC5B,cAAsB;QAEtB,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC7E,MAAM,cAAc,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QACpE,MAAM,UAAU,GAAG,MAAM,CAAC,mBAAmB,IAAI,cAAc,CAAC;QAEhE,4CAA4C;QAC5C,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,UAAU,EAAE,cAAc,CAAC,CAAC;QAE3E,IAAI,cAAc,IAAI,aAAa,EAAE,CAAC;YACpC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,OAAO,GAAG,aAAa,GAAG,cAAc,CAAC;QAE/C,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,YAAY,OAAO,gBAAgB,UAAU,IAAI,QAAQ,EAAE,CAC5D,CAAC;QAEF,wDAAwD;QACxD,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,yBAAyB,CAC3D,UAAU,EACV,QAAQ,CACT,CAAC;QACF,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAAC,CAAC;QAE9D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,aAAa,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,MAAM,IAAI,CAAC,8BAA8B,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YAChE,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;gBACzB,IAAI,CAAC;oBACH,MAAM,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;gBACvC,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,8BAA8B,UAAU,IAAI,QAAQ,KAAM,KAAe,CAAC,OAAO,EAAE,CACpF,CAAC;oBACF,MAAM,IAAI,CAAC,8BAA8B,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;gBAClE,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO;YACL,QAAQ;YACR,UAAU;YACV,cAAc;YACd,cAAc,EAAE,aAAa;YAC7B,MAAM,EAAE,OAAO;YACf,KAAK,EAAE,aAAa;SACrB,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,mBAAmB,CAC/B,UAAkB,EAClB,QAAgB,EAChB,MAA4B;QAE5B,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC7E,MAAM,cAAc,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QACpE,MAAM,UAAU,GAAG,MAAM,CAAC,mBAAmB,IAAI,cAAc,CAAC;QAEhE,IAAI,cAAc,IAAI,UAAU,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,MAAM,GAAG,cAAc,GAAG,UAAU,CAAC;QAE3C,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,eAAe,MAAM,uBAAuB,UAAU,IAAI,QAAQ,EAAE,CACrE,CAAC;QAEF,2BAA2B;QAC3B,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,qBAAqB,CACjE,UAAU,EACV,QAAQ,CACT,CAAC;QAEF,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7C,MAAM,IAAI,CAAC,sBAAsB,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QAClE,CAAC;QAED,OAAO;YACL,QAAQ;YACR,UAAU;YACV,cAAc;YACd,cAAc,EAAE,UAAU;YAC1B,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,MAAM;SACd,CAAC;IACJ,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,mBAAmB,CAC/B,UAAkB,EAClB,QAAgB,EAChB,MAA4B;QAE5B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,gBAAgB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAEhF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,yDAAyD;QACzD,8DAA8D;QAC9D,MAAM,SAAS,GAAG,GAAG,QAAQ,QAAQ,CAAC;QACtC,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAE9D,IAAI,aAAa,EAAE,CAAC;YAClB,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,+BAA+B,UAAU,IAAI,QAAQ,0BAA0B,CAChF,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,WAAW,OAAO,CAAC,MAAM,sBAAsB,UAAU,IAAI,QAAQ,EAAE,CACxE,CAAC;QAEF,8BAA8B;QAC9B,KAAK,MAAM,QAAQ,IAAI,OAAO,EAAE,CAAC;YAC/B,IAAI,MAAM,CAAC,iBAAiB,EAAE,CAAC;gBAC7B,MAAM,MAAM,CAAC,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YACrD,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,CAAC,aAAa,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;QAED,OAAO;YACL,QAAQ;YACR,UAAU;YACV,cAAc,EAAE,OAAO,CAAC,MAAM;YAC9B,cAAc,EAAE,CAAC;YACjB,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,OAAO,CAAC,MAAM;SACtB,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,iBAAiB,CAAC,SAAiB;QAC/C,IAAI,CAAC;YACH,qBAAqB;YACrB,MAAM,UAAU,GAAG,QAAQ,SAAS,UAAU,CAAC;YAC/C,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACvD,IAAI,YAAY,GAAG,CAAC;gBAAE,OAAO,IAAI,CAAC;YAElC,oBAAoB;YACpB,MAAM,SAAS,GAAG,QAAQ,SAAS,SAAS,CAAC;YAC7C,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACrD,IAAI,WAAW,GAAG,CAAC;gBAAE,OAAO,IAAI,CAAC;YAEjC,oBAAoB;YACpB,MAAM,UAAU,GAAG,QAAQ,SAAS,UAAU,CAAC;YAC/C,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACxD,IAAI,YAAY,GAAG,CAAC;gBAAE,OAAO,IAAI,CAAC;YAElC,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,wBAAwB,SAAS,cAAe,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;YAC5F,6CAA6C;YAC7C,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,kBAAkB,CAC9B,UAAkB,EAClB,QAAgB;QAEhB,gDAAgD;QAChD,MAAM,kBAAkB,GACtB,MAAM,IAAI,CAAC,YAAY,CAAC,gCAAgC,CAAC,UAAU,CAAC,CAAC;QAEvE,IAAI,kBAAkB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1C,OAAO;QACT,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,yBAAyB,UAAU,IAAI,QAAQ,EAAE,CAAC,CAAC;QAErE,wBAAwB;QACxB,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAE9D,qEAAqE;QACrE,sCAAsC;IACxC,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,sBAAsB,CAClC,UAAkB,EAClB,QAAgB,EAChB,MAA4B;QAE5B,sEAAsE;QACtE,gEAAgE;QAChE,iDAAiD;QACjD,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,iCAAiC,UAAU,IAAI,QAAQ,EAAE,CAC1D,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,oBAAoB,CAChC,UAAkB,EAClB,QAAgB;QAEhB,yEAAyE;QACzE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,gBAAgB,CACvD,UAAU,EACV,QAAQ,CACT,CAAC;QACF,OAAO,OAAO,CAAC,MAAM,CAAC;IACxB,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,sBAAsB,CAAC,UAAkB;QACrD,mFAAmF;QACnF,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,SAAS,oBAAoB,CAAC;QACtD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC1C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;QAEnC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC7B,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;gBACtB,yEAAyE;gBACzE,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBAC3C,IAAI,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;oBACnC,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,0BAA0B;oBACpE,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBACzB,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,yBAAyB,CACrC,UAAkB,EAClB,QAAgB;QAEhB,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,SAAS,oBAAoB,UAAU,IAAI,QAAQ,EAAE,CAAC;QAC1E,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxC,OAAO,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,8BAA8B,CAC1C,UAAkB,EAClB,QAAgB;QAEhB,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,SAAS,oBAAoB,UAAU,IAAI,QAAQ,EAAE,CAAC;QAC1E,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3B,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,kBAAkB;IACtD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,8BAA8B,CAClC,UAAkB,EAClB,QAAgB;QAEhB,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,SAAS,oBAAoB,UAAU,IAAI,QAAQ,EAAE,CAAC;QAC1E,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAE1C,IAAI,OAAO,IAAI,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IAED;;OAEG;IACK,eAAe,CACrB,OAAe,EACf,OAAe;QAEf,IAAI,OAAO,GAAG,OAAO;YAAE,OAAO,OAAO,CAAC;QACtC,IAAI,OAAO,GAAG,OAAO;YAAE,OAAO,WAAW,CAAC;QAC1C,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,QAAQ,CAAC,OAAe;QACpC,IAAI,MAAM,GAAG,GAAG,CAAC;QACjB,MAAM,IAAI,GAAa,EAAE,CAAC;QAE1B,GAAG,CAAC;YACF,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAClD,MAAM,EACN,OAAO,EACP,OAAO,EACP,OAAO,EACP,GAAG,CACJ,CAAC;YACF,MAAM,GAAG,UAAU,CAAC;YACpB,IAAI,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;QACzB,CAAC,QAAQ,MAAM,KAAK,GAAG,EAAE;QAEzB,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AA1mBY,gDAAkB;6BAAlB,kBAAkB;IAD9B,IAAA,mBAAU,GAAE;IAWR,WAAA,IAAA,eAAM,EAAC,+BAAmB,CAAC,CAAA;IAC3B,WAAA,IAAA,eAAM,EAAC,gCAAoB,CAAC,CAAA;IAI5B,WAAA,IAAA,iBAAQ,GAAE,CAAA;qCAL0C,iBAAK,UAG1B,qCAAoB;QACrB,mCAAmB;QACC,mCAAmB;GAf7D,kBAAkB,CA0mB9B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/cron-manager/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("./cron-manager.service"), exports);
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/cron-manager/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yDAAuC"}
|