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 @@
|
|
|
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 @@
|
|
|
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"}
|