atomic-queues 1.4.1 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +300 -283
- package/dist/decorators/constants.d.ts +17 -0
- package/dist/decorators/constants.d.ts.map +1 -0
- package/dist/decorators/constants.js +23 -0
- package/dist/decorators/constants.js.map +1 -0
- package/dist/decorators/entity.decorators.d.ts +88 -0
- package/dist/decorators/entity.decorators.d.ts.map +1 -0
- package/dist/decorators/entity.decorators.js +150 -0
- package/dist/decorators/entity.decorators.js.map +1 -0
- package/dist/decorators/index.d.ts +9 -1
- package/dist/decorators/index.d.ts.map +1 -1
- package/dist/decorators/index.js +9 -1
- package/dist/decorators/index.js.map +1 -1
- package/dist/decorators/interfaces.d.ts +130 -0
- package/dist/decorators/interfaces.d.ts.map +1 -0
- package/dist/decorators/interfaces.js +3 -0
- package/dist/decorators/interfaces.js.map +1 -0
- package/dist/decorators/job.decorators.d.ts +60 -0
- package/dist/decorators/job.decorators.d.ts.map +1 -0
- package/dist/decorators/job.decorators.js +97 -0
- package/dist/decorators/job.decorators.js.map +1 -0
- package/dist/decorators/legacy.decorators.d.ts +36 -0
- package/dist/decorators/legacy.decorators.d.ts.map +1 -0
- package/dist/decorators/legacy.decorators.js +61 -0
- package/dist/decorators/legacy.decorators.js.map +1 -0
- package/dist/decorators/metadata-readers.d.ts +31 -0
- package/dist/decorators/metadata-readers.d.ts.map +1 -0
- package/dist/decorators/metadata-readers.js +53 -0
- package/dist/decorators/metadata-readers.js.map +1 -0
- package/dist/decorators/registry.d.ts +2 -0
- package/dist/decorators/registry.d.ts.map +1 -0
- package/dist/decorators/registry.js +6 -0
- package/dist/decorators/registry.js.map +1 -0
- package/dist/decorators/scaler.decorators.d.ts +65 -0
- package/dist/decorators/scaler.decorators.d.ts.map +1 -0
- package/dist/decorators/scaler.decorators.js +103 -0
- package/dist/decorators/scaler.decorators.js.map +1 -0
- package/dist/decorators/type-guards.d.ts +18 -0
- package/dist/decorators/type-guards.d.ts.map +1 -0
- package/dist/decorators/type-guards.js +32 -0
- package/dist/decorators/type-guards.js.map +1 -0
- package/dist/decorators/utils.d.ts +20 -0
- package/dist/decorators/utils.d.ts.map +1 -0
- package/dist/decorators/utils.js +98 -0
- package/dist/decorators/utils.js.map +1 -0
- package/dist/decorators/worker.decorators.d.ts +58 -0
- package/dist/decorators/worker.decorators.d.ts.map +1 -0
- package/dist/decorators/worker.decorators.js +92 -0
- package/dist/decorators/worker.decorators.js.map +1 -0
- package/dist/domain/interfaces/config.interfaces.d.ts +188 -0
- package/dist/domain/interfaces/config.interfaces.d.ts.map +1 -0
- package/dist/domain/interfaces/config.interfaces.js +3 -0
- package/dist/domain/interfaces/config.interfaces.js.map +1 -0
- package/dist/domain/interfaces/cqrs.interfaces.d.ts +7 -0
- package/dist/domain/interfaces/cqrs.interfaces.d.ts.map +1 -0
- package/dist/domain/interfaces/cqrs.interfaces.js +3 -0
- package/dist/domain/interfaces/cqrs.interfaces.js.map +1 -0
- package/dist/domain/interfaces/event.interfaces.d.ts +71 -0
- package/dist/domain/interfaces/event.interfaces.d.ts.map +1 -0
- package/dist/domain/interfaces/event.interfaces.js +3 -0
- package/dist/domain/interfaces/event.interfaces.js.map +1 -0
- package/dist/domain/interfaces/index-tracking.interfaces.d.ts +69 -0
- package/dist/domain/interfaces/index-tracking.interfaces.d.ts.map +1 -0
- package/dist/domain/interfaces/index-tracking.interfaces.js +3 -0
- package/dist/domain/interfaces/index-tracking.interfaces.js.map +1 -0
- package/dist/domain/interfaces/index.d.ts +12 -0
- package/dist/domain/interfaces/index.d.ts.map +1 -0
- package/dist/domain/interfaces/index.js +28 -0
- package/dist/domain/interfaces/index.js.map +1 -0
- package/dist/domain/interfaces/job.interfaces.d.ts +76 -0
- package/dist/domain/interfaces/job.interfaces.d.ts.map +1 -0
- package/dist/domain/interfaces/job.interfaces.js +3 -0
- package/dist/domain/interfaces/job.interfaces.js.map +1 -0
- package/dist/domain/interfaces/lock.interfaces.d.ts +54 -0
- package/dist/domain/interfaces/lock.interfaces.d.ts.map +1 -0
- package/dist/domain/interfaces/lock.interfaces.js +3 -0
- package/dist/domain/interfaces/lock.interfaces.js.map +1 -0
- package/dist/domain/interfaces/process.interfaces.d.ts +44 -0
- package/dist/domain/interfaces/process.interfaces.d.ts.map +1 -0
- package/dist/domain/interfaces/process.interfaces.js +3 -0
- package/dist/domain/interfaces/process.interfaces.js.map +1 -0
- package/dist/domain/interfaces/queue.interfaces.d.ts +46 -0
- package/dist/domain/interfaces/queue.interfaces.d.ts.map +1 -0
- package/dist/domain/interfaces/queue.interfaces.js +3 -0
- package/dist/domain/interfaces/queue.interfaces.js.map +1 -0
- package/dist/domain/interfaces/scaling.interfaces.d.ts +62 -0
- package/dist/domain/interfaces/scaling.interfaces.d.ts.map +1 -0
- package/dist/domain/interfaces/scaling.interfaces.js +3 -0
- package/dist/domain/interfaces/scaling.interfaces.js.map +1 -0
- package/dist/domain/interfaces/utility.types.d.ts +15 -0
- package/dist/domain/interfaces/utility.types.d.ts.map +1 -0
- package/dist/domain/interfaces/utility.types.js +3 -0
- package/dist/domain/interfaces/utility.types.js.map +1 -0
- package/dist/domain/interfaces/worker.interfaces.d.ts +120 -0
- package/dist/domain/interfaces/worker.interfaces.d.ts.map +1 -0
- package/dist/domain/interfaces/worker.interfaces.js +3 -0
- package/dist/domain/interfaces/worker.interfaces.js.map +1 -0
- package/dist/module/atomic-queues.module.d.ts.map +1 -1
- package/dist/module/atomic-queues.module.js +5 -0
- package/dist/module/atomic-queues.module.js.map +1 -1
- package/dist/services/cron-manager/cron-manager.service.d.ts +5 -4
- package/dist/services/cron-manager/cron-manager.service.d.ts.map +1 -1
- package/dist/services/cron-manager/cron-manager.service.js +26 -57
- package/dist/services/cron-manager/cron-manager.service.js.map +1 -1
- package/dist/services/index-manager/index-manager.service.d.ts +0 -4
- package/dist/services/index-manager/index-manager.service.d.ts.map +1 -1
- package/dist/services/index-manager/index-manager.service.js +4 -16
- package/dist/services/index-manager/index-manager.service.js.map +1 -1
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +1 -0
- package/dist/services/index.js.map +1 -1
- package/dist/services/processor-discovery/decorator-discovery.service.d.ts +40 -0
- package/dist/services/processor-discovery/decorator-discovery.service.d.ts.map +1 -0
- package/dist/services/processor-discovery/decorator-discovery.service.js +191 -0
- package/dist/services/processor-discovery/decorator-discovery.service.js.map +1 -0
- package/dist/services/processor-discovery/index.d.ts +4 -0
- package/dist/services/processor-discovery/index.d.ts.map +1 -1
- package/dist/services/processor-discovery/index.js +4 -0
- package/dist/services/processor-discovery/index.js.map +1 -1
- package/dist/services/processor-discovery/processor-discovery.service.d.ts +30 -138
- package/dist/services/processor-discovery/processor-discovery.service.d.ts.map +1 -1
- package/dist/services/processor-discovery/processor-discovery.service.js +125 -502
- package/dist/services/processor-discovery/processor-discovery.service.js.map +1 -1
- package/dist/services/processor-discovery/processor-registry.d.ts +58 -0
- package/dist/services/processor-discovery/processor-registry.d.ts.map +1 -0
- package/dist/services/processor-discovery/processor-registry.js +74 -0
- package/dist/services/processor-discovery/processor-registry.js.map +1 -0
- package/dist/services/processor-discovery/scaling-registration.service.d.ts +60 -0
- package/dist/services/processor-discovery/scaling-registration.service.d.ts.map +1 -0
- package/dist/services/processor-discovery/scaling-registration.service.js +261 -0
- package/dist/services/processor-discovery/scaling-registration.service.js.map +1 -0
- package/dist/services/processor-discovery/worker-factory.service.d.ts +54 -0
- package/dist/services/processor-discovery/worker-factory.service.d.ts.map +1 -0
- package/dist/services/processor-discovery/worker-factory.service.js +185 -0
- package/dist/services/processor-discovery/worker-factory.service.js.map +1 -0
- package/dist/services/queue-bus/entity-target.d.ts +58 -0
- package/dist/services/queue-bus/entity-target.d.ts.map +1 -0
- package/dist/services/queue-bus/entity-target.js +109 -0
- package/dist/services/queue-bus/entity-target.js.map +1 -0
- package/dist/services/queue-bus/index.d.ts +4 -0
- package/dist/services/queue-bus/index.d.ts.map +1 -1
- package/dist/services/queue-bus/index.js +4 -0
- package/dist/services/queue-bus/index.js.map +1 -1
- package/dist/services/queue-bus/queue-bus.service.d.ts +9 -145
- package/dist/services/queue-bus/queue-bus.service.d.ts.map +1 -1
- package/dist/services/queue-bus/queue-bus.service.js +23 -311
- package/dist/services/queue-bus/queue-bus.service.js.map +1 -1
- package/dist/services/queue-bus/queue-bus.types.d.ts +40 -0
- package/dist/services/queue-bus/queue-bus.types.d.ts.map +1 -0
- package/dist/services/queue-bus/queue-bus.types.js +3 -0
- package/dist/services/queue-bus/queue-bus.types.js.map +1 -0
- package/dist/services/queue-bus/queue-bus.utils.d.ts +34 -0
- package/dist/services/queue-bus/queue-bus.utils.d.ts.map +1 -0
- package/dist/services/queue-bus/queue-bus.utils.js +82 -0
- package/dist/services/queue-bus/queue-bus.utils.js.map +1 -0
- package/dist/services/queue-bus/queue-target.d.ts +61 -0
- package/dist/services/queue-bus/queue-target.d.ts.map +1 -0
- package/dist/services/queue-bus/queue-target.js +123 -0
- package/dist/services/queue-bus/queue-target.js.map +1 -0
- package/dist/services/queue-events-manager/queue-events-manager.service.d.ts +23 -6
- package/dist/services/queue-events-manager/queue-events-manager.service.d.ts.map +1 -1
- package/dist/services/queue-events-manager/queue-events-manager.service.js +69 -37
- package/dist/services/queue-events-manager/queue-events-manager.service.js.map +1 -1
- package/dist/services/resource-lock/resource-lock.service.d.ts +0 -4
- package/dist/services/resource-lock/resource-lock.service.d.ts.map +1 -1
- package/dist/services/resource-lock/resource-lock.service.js +4 -16
- package/dist/services/resource-lock/resource-lock.service.js.map +1 -1
- package/dist/services/service-queue/index.d.ts +1 -0
- package/dist/services/service-queue/index.d.ts.map +1 -1
- package/dist/services/service-queue/index.js +1 -0
- package/dist/services/service-queue/index.js.map +1 -1
- package/dist/services/service-queue/service-queue.service.d.ts +2 -35
- package/dist/services/service-queue/service-queue.service.d.ts.map +1 -1
- package/dist/services/service-queue/service-queue.service.js +17 -49
- package/dist/services/service-queue/service-queue.service.js.map +1 -1
- package/dist/services/service-queue/service-queue.types.d.ts +32 -0
- package/dist/services/service-queue/service-queue.types.d.ts.map +1 -0
- package/dist/services/service-queue/service-queue.types.js +27 -0
- package/dist/services/service-queue/service-queue.types.js.map +1 -0
- package/dist/services/spawn-queue/index.d.ts +2 -0
- package/dist/services/spawn-queue/index.d.ts.map +1 -0
- package/dist/services/spawn-queue/index.js +18 -0
- package/dist/services/spawn-queue/index.js.map +1 -0
- package/dist/services/spawn-queue/spawn-queue.service.d.ts +119 -0
- package/dist/services/spawn-queue/spawn-queue.service.d.ts.map +1 -0
- package/dist/services/spawn-queue/spawn-queue.service.js +273 -0
- package/dist/services/spawn-queue/spawn-queue.service.js.map +1 -0
- package/dist/services/worker-manager/worker-manager.service.d.ts +18 -3
- package/dist/services/worker-manager/worker-manager.service.d.ts.map +1 -1
- package/dist/services/worker-manager/worker-manager.service.js +46 -21
- package/dist/services/worker-manager/worker-manager.service.js.map +1 -1
- package/dist/utils/async.utils.d.ts +51 -0
- package/dist/utils/async.utils.d.ts.map +1 -0
- package/dist/utils/async.utils.js +87 -0
- package/dist/utils/async.utils.js.map +1 -0
- package/dist/utils/helpers.d.ts +4 -123
- package/dist/utils/helpers.d.ts.map +1 -1
- package/dist/utils/helpers.js +18 -226
- package/dist/utils/helpers.js.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/job.utils.d.ts +50 -0
- package/dist/utils/job.utils.d.ts.map +1 -0
- package/dist/utils/job.utils.js +89 -0
- package/dist/utils/job.utils.js.map +1 -0
- package/dist/utils/naming.utils.d.ts +21 -0
- package/dist/utils/naming.utils.d.ts.map +1 -0
- package/dist/utils/naming.utils.js +38 -0
- package/dist/utils/naming.utils.js.map +1 -0
- package/dist/utils/rate-limit.utils.d.ts +9 -0
- package/dist/utils/rate-limit.utils.d.ts.map +1 -0
- package/dist/utils/rate-limit.utils.js +30 -0
- package/dist/utils/rate-limit.utils.js.map +1 -0
- package/dist/utils/redis.utils.d.ts +3 -0
- package/dist/utils/redis.utils.d.ts.map +1 -0
- package/dist/utils/redis.utils.js +14 -0
- package/dist/utils/redis.utils.js.map +1 -0
- package/package.json +17 -17
- package/dist/decorators/decorators.d.ts +0 -489
- package/dist/decorators/decorators.d.ts.map +0 -1
- package/dist/decorators/decorators.js +0 -680
- package/dist/decorators/decorators.js.map +0 -1
- package/dist/domain/interfaces.d.ts +0 -748
- package/dist/domain/interfaces.d.ts.map +0 -1
- package/dist/domain/interfaces.js +0 -19
- package/dist/domain/interfaces.js.map +0 -1
|
@@ -1,10 +1,43 @@
|
|
|
1
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
2
18
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
19
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
20
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
21
|
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
22
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
23
|
};
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
8
41
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
42
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
43
|
};
|
|
@@ -16,30 +49,26 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
16
49
|
exports.ProcessorDiscoveryService = void 0;
|
|
17
50
|
const common_1 = require("@nestjs/common");
|
|
18
51
|
const core_1 = require("@nestjs/core");
|
|
19
|
-
const decorators_1 = require("../../decorators");
|
|
20
|
-
const worker_manager_1 = require("../worker-manager");
|
|
21
|
-
const queue_manager_1 = require("../queue-manager");
|
|
22
|
-
const cron_manager_1 = require("../cron-manager");
|
|
23
52
|
const command_discovery_1 = require("../command-discovery");
|
|
24
|
-
const service_queue_1 = require("../service-queue");
|
|
25
53
|
const queue_bus_1 = require("../queue-bus");
|
|
26
|
-
const queue_events_manager_1 = require("../queue-events-manager");
|
|
27
54
|
const constants_1 = require("../constants");
|
|
55
|
+
const processor_registry_1 = require("./processor-registry");
|
|
56
|
+
const decorator_discovery_service_1 = require("./decorator-discovery.service");
|
|
57
|
+
const worker_factory_service_1 = require("./worker-factory.service");
|
|
58
|
+
const scaling_registration_service_1 = require("./scaling-registration.service");
|
|
28
59
|
/**
|
|
29
60
|
* ProcessorDiscoveryService
|
|
30
61
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* - @EntityScaler - For entity scaling logic
|
|
62
|
+
* Orchestrator that coordinates discovery, registration, worker creation,
|
|
63
|
+
* and scaling setup. Delegates to focused services:
|
|
34
64
|
*
|
|
35
|
-
*
|
|
36
|
-
* -
|
|
37
|
-
* -
|
|
38
|
-
* -
|
|
65
|
+
* - ProcessorRegistry: state management for processors/scalers/workers
|
|
66
|
+
* - DecoratorDiscoveryService: NestJS provider scanning and registration
|
|
67
|
+
* - WorkerFactoryService: worker creation and job processing
|
|
68
|
+
* - ScalingRegistrationService: scaling/spawn registration logic
|
|
39
69
|
*
|
|
40
70
|
* @example
|
|
41
71
|
* ```typescript
|
|
42
|
-
* // Classes are auto-discovered from module providers
|
|
43
72
|
* @WorkerProcessor({ entityType: 'table' })
|
|
44
73
|
* @Injectable()
|
|
45
74
|
* export class TableProcessor {
|
|
@@ -56,218 +85,82 @@ const constants_1 = require("../constants");
|
|
|
56
85
|
* ```
|
|
57
86
|
*/
|
|
58
87
|
let ProcessorDiscoveryService = ProcessorDiscoveryService_1 = class ProcessorDiscoveryService {
|
|
59
|
-
constructor(discoveryService,
|
|
88
|
+
constructor(discoveryService, moduleRef, registry, decoratorDiscovery, workerFactory, scalingRegistration, commandDiscovery, config) {
|
|
60
89
|
this.discoveryService = discoveryService;
|
|
61
|
-
this.metadataScanner = metadataScanner;
|
|
62
90
|
this.moduleRef = moduleRef;
|
|
63
|
-
this.
|
|
64
|
-
this.
|
|
65
|
-
this.
|
|
91
|
+
this.registry = registry;
|
|
92
|
+
this.decoratorDiscovery = decoratorDiscovery;
|
|
93
|
+
this.workerFactory = workerFactory;
|
|
94
|
+
this.scalingRegistration = scalingRegistration;
|
|
66
95
|
this.commandDiscovery = commandDiscovery;
|
|
67
|
-
this.serviceQueueManager = serviceQueueManager;
|
|
68
|
-
this.queueEventsManager = queueEventsManager;
|
|
69
96
|
this.config = config;
|
|
70
97
|
this.logger = new common_1.Logger(ProcessorDiscoveryService_1.name);
|
|
71
|
-
this.processors = new Map();
|
|
72
|
-
this.scalers = new Map();
|
|
73
|
-
this.activeWorkers = new Map(); // entityType -> Set of entityIds with workers
|
|
74
|
-
this.commandBus = null;
|
|
75
|
-
this.queryBus = null;
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Set the CommandBus for executing commands from QueueBus registry
|
|
79
|
-
*/
|
|
80
|
-
setCommandBus(commandBus) {
|
|
81
|
-
this.commandBus = commandBus;
|
|
82
|
-
// Also set on CommandDiscoveryService if available
|
|
83
|
-
if (this.commandDiscovery) {
|
|
84
|
-
this.commandDiscovery.setCommandBus(commandBus);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Set the QueryBus for executing queries from QueueBus registry
|
|
89
|
-
*/
|
|
90
|
-
setQueryBus(queryBus) {
|
|
91
|
-
this.queryBus = queryBus;
|
|
92
|
-
// Also set on CommandDiscoveryService if available
|
|
93
|
-
if (this.commandDiscovery) {
|
|
94
|
-
this.commandDiscovery.setQueryBus(queryBus);
|
|
95
|
-
}
|
|
96
98
|
}
|
|
97
99
|
async onModuleInit() {
|
|
98
100
|
if (!this.discoveryService) {
|
|
99
101
|
this.logger.warn('DiscoveryService not available. Manual registration required.');
|
|
100
102
|
return;
|
|
101
103
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
104
|
+
// Phase 1: Discovery and registration
|
|
105
|
+
this.decoratorDiscovery.discoverProcessors(this.registry);
|
|
106
|
+
this.decoratorDiscovery.discoverScalers(this.registry);
|
|
107
|
+
this.decoratorDiscovery.registerEntitiesFromConfig(this.registry);
|
|
108
|
+
// Phase 2: Wire up worker factory
|
|
109
|
+
this.workerFactory.setRegistry(this.registry);
|
|
110
|
+
// Phase 3: Register all scaling handlers
|
|
111
|
+
await this.scalingRegistration.registerAll(this.registry, this.workerFactory);
|
|
112
|
+
// Phase 4: CQRS auto-wiring
|
|
110
113
|
if (this.config.autoRegisterCommands !== false) {
|
|
111
114
|
this.autoRegisterCommandsFromCqrs();
|
|
112
115
|
}
|
|
116
|
+
this.autoWireCqrsBuses();
|
|
113
117
|
}
|
|
118
|
+
// ==========================================================================
|
|
119
|
+
// CQRS WIRING
|
|
120
|
+
// ==========================================================================
|
|
114
121
|
/**
|
|
115
|
-
*
|
|
116
|
-
* This creates virtual processors for entities that don't have explicit @WorkerProcessor classes.
|
|
117
|
-
*
|
|
118
|
-
* Benefits:
|
|
119
|
-
* - No boilerplate @WorkerProcessor class needed
|
|
120
|
-
* - Just configure in module and decorate commands with @QueueEntity
|
|
121
|
-
* - Workers auto-spawn on job arrival and terminate when idle
|
|
122
|
+
* Set the CommandBus for executing commands from QueueBus registry
|
|
122
123
|
*/
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
if (
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
const keyPrefix = this.config.keyPrefix || 'aq';
|
|
129
|
-
for (const [entityType, entityConfig] of Object.entries(entities)) {
|
|
130
|
-
// Skip if a processor is already registered for this entity type
|
|
131
|
-
if (this.processors.has(entityType)) {
|
|
132
|
-
this.logger.debug(`Entity '${entityType}' already has a @WorkerProcessor, skipping config-based registration`);
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
this.logger.log(`Registering entity '${entityType}' from module config (no @WorkerProcessor needed)`);
|
|
136
|
-
// Build queue and worker name functions
|
|
137
|
-
const queueNameFn = entityConfig.queueName
|
|
138
|
-
?? ((entityId) => `${keyPrefix}:${entityType}:${entityId}:queue`);
|
|
139
|
-
const workerNameFn = entityConfig.workerName
|
|
140
|
-
?? ((entityId) => `${keyPrefix}:${entityType}:${entityId}:worker`);
|
|
141
|
-
// Create a virtual processor entry
|
|
142
|
-
const processor = {
|
|
143
|
-
entityType,
|
|
144
|
-
processorInstance: null, // No instance - we use generic processing
|
|
145
|
-
options: {
|
|
146
|
-
entityType,
|
|
147
|
-
defaultEntityId: entityConfig.defaultEntityId,
|
|
148
|
-
queueName: queueNameFn,
|
|
149
|
-
workerName: workerNameFn,
|
|
150
|
-
workerConfig: entityConfig.workerConfig,
|
|
151
|
-
maxWorkersPerEntity: entityConfig.maxWorkersPerEntity ?? 1,
|
|
152
|
-
idleTimeoutSeconds: entityConfig.idleTimeoutSeconds ?? 15,
|
|
153
|
-
autoSpawn: entityConfig.autoSpawn !== false, // Default true
|
|
154
|
-
},
|
|
155
|
-
jobHandlers: new Map(), // No explicit handlers - use generic routing
|
|
156
|
-
wildcardHandler: undefined,
|
|
157
|
-
queueNameFn,
|
|
158
|
-
workerNameFn,
|
|
159
|
-
};
|
|
160
|
-
this.processors.set(entityType, processor);
|
|
161
|
-
this.activeWorkers.set(entityType, new Set());
|
|
162
|
-
this.logger.debug(`Registered config-based processor for '${entityType}' ` +
|
|
163
|
-
`(maxWorkers: ${processor.options.maxWorkersPerEntity}, idle: ${processor.options.idleTimeoutSeconds}s)`);
|
|
124
|
+
setCommandBus(commandBus) {
|
|
125
|
+
this.workerFactory.setCommandBus(commandBus);
|
|
126
|
+
if (this.commandDiscovery) {
|
|
127
|
+
this.commandDiscovery.setCommandBus(commandBus);
|
|
164
128
|
}
|
|
165
129
|
}
|
|
166
130
|
/**
|
|
167
|
-
*
|
|
168
|
-
* These processors will auto-spawn workers when jobs arrive and
|
|
169
|
-
* auto-terminate when idle.
|
|
131
|
+
* Set the QueryBus for executing queries from QueueBus registry
|
|
170
132
|
*/
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
for (const [entityType, processor] of this.processors) {
|
|
177
|
-
// Skip if a scaler is already registered for this entity type
|
|
178
|
-
if (this.scalers.has(entityType)) {
|
|
179
|
-
continue;
|
|
180
|
-
}
|
|
181
|
-
// Check if autoSpawn is explicitly disabled
|
|
182
|
-
if (processor.options.autoSpawn === false) {
|
|
183
|
-
this.logger.debug(`Auto-spawn disabled for ${entityType}, skipping scalerless registration`);
|
|
184
|
-
continue;
|
|
185
|
-
}
|
|
186
|
-
this.logger.log(`Registering scalerless config for '${entityType}' (autoSpawn mode)`);
|
|
187
|
-
const scalingConfig = {
|
|
188
|
-
entityType,
|
|
189
|
-
maxWorkersPerEntity: processor.options.maxWorkersPerEntity ?? 1,
|
|
190
|
-
idleTimeoutSeconds: processor.options.idleTimeoutSeconds ?? 15,
|
|
191
|
-
// In scalerless mode, we don't rely on getActiveEntityIds
|
|
192
|
-
// Workers are spawned reactively when jobs arrive
|
|
193
|
-
getActiveEntityIds: async () => {
|
|
194
|
-
// Return empty - workers are spawned by QueueEventsManager when jobs arrive
|
|
195
|
-
return [];
|
|
196
|
-
},
|
|
197
|
-
getDesiredWorkerCount: async (_entityId) => {
|
|
198
|
-
return 1; // Default to 1 worker per entity
|
|
199
|
-
},
|
|
200
|
-
onSpawnWorker: async (entityId) => {
|
|
201
|
-
await this.createWorkerForEntity(entityType, entityId);
|
|
202
|
-
},
|
|
203
|
-
onTerminateWorker: async (entityId, _workerId) => {
|
|
204
|
-
const workerName = processor.workerNameFn(entityId);
|
|
205
|
-
await this.workerManager.signalWorkerClose(workerName);
|
|
206
|
-
},
|
|
207
|
-
};
|
|
208
|
-
this.cronManager.registerEntityType(scalingConfig);
|
|
209
|
-
this.logger.log(`Registered scalerless config for '${entityType}' (idleTimeout: ${scalingConfig.idleTimeoutSeconds}s)`);
|
|
133
|
+
setQueryBus(queryBus) {
|
|
134
|
+
this.workerFactory.setQueryBus(queryBus);
|
|
135
|
+
if (this.commandDiscovery) {
|
|
136
|
+
this.commandDiscovery.setQueryBus(queryBus);
|
|
210
137
|
}
|
|
211
138
|
}
|
|
212
139
|
/**
|
|
213
|
-
*
|
|
214
|
-
* This enables automatic worker spawning when jobs are added.
|
|
140
|
+
* Attempt to resolve CommandBus and QueryBus from the DI container.
|
|
215
141
|
*/
|
|
216
|
-
|
|
217
|
-
if (!this.
|
|
218
|
-
this.logger.debug('QueueEventsManager not available, skipping event listening setup');
|
|
142
|
+
autoWireCqrsBuses() {
|
|
143
|
+
if (!this.discoveryService)
|
|
219
144
|
return;
|
|
145
|
+
const providers = this.discoveryService.getProviders();
|
|
146
|
+
const commandBusWrapper = providers.find((w) => w.metatype?.name === 'CommandBus' && w.instance);
|
|
147
|
+
if (commandBusWrapper?.instance) {
|
|
148
|
+
this.setCommandBus(commandBusWrapper.instance);
|
|
149
|
+
this.logger.log('Auto-wired CommandBus from @nestjs/cqrs');
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
this.logger.debug('CommandBus not found in DI container. ' +
|
|
153
|
+
'Import CqrsModule in your app or call setCommandBus() manually.');
|
|
220
154
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
const processor = this.processors.get(entityType);
|
|
226
|
-
const scaler = this.scalers.get(entityType);
|
|
227
|
-
// If there's a scaler with @OnSpawnWorker, use it
|
|
228
|
-
if (scaler?.methods.onSpawnWorker) {
|
|
229
|
-
await scaler.scalerInstance[scaler.methods.onSpawnWorker](entityId);
|
|
230
|
-
}
|
|
231
|
-
// Also auto-create worker if processor is registered
|
|
232
|
-
if (processor) {
|
|
233
|
-
await this.createWorkerForEntity(entityType, entityId);
|
|
234
|
-
}
|
|
235
|
-
});
|
|
236
|
-
// Register entity patterns for all processors
|
|
237
|
-
for (const [entityType, processor] of this.processors) {
|
|
238
|
-
this.queueEventsManager.registerEntityPattern(entityType, processor.queueNameFn, processor.workerNameFn);
|
|
155
|
+
const queryBusWrapper = providers.find((w) => w.metatype?.name === 'QueryBus' && w.instance);
|
|
156
|
+
if (queryBusWrapper?.instance) {
|
|
157
|
+
this.setQueryBus(queryBusWrapper.instance);
|
|
158
|
+
this.logger.log('Auto-wired QueryBus from @nestjs/cqrs');
|
|
239
159
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
* Register spawn worker handler with ServiceQueueManager
|
|
244
|
-
* This allows workers to be spawned on-demand via the service queue.
|
|
245
|
-
* Uses the same logic as scaling cycle - calls scaler's @OnSpawnWorker first,
|
|
246
|
-
* then auto-creates via processor if registered.
|
|
247
|
-
*/
|
|
248
|
-
async registerSpawnWorkerHandler() {
|
|
249
|
-
if (!this.serviceQueueManager) {
|
|
250
|
-
this.logger.debug('ServiceQueueManager not available, skipping spawn handler registration');
|
|
251
|
-
return;
|
|
160
|
+
else {
|
|
161
|
+
this.logger.debug('QueryBus not found in DI container. ' +
|
|
162
|
+
'Import CqrsModule in your app or call setQueryBus() manually.');
|
|
252
163
|
}
|
|
253
|
-
this.serviceQueueManager.registerSpawnWorkerHandler(async (entityType, entityId) => {
|
|
254
|
-
const scaler = this.scalers.get(entityType);
|
|
255
|
-
const processor = this.processors.get(entityType);
|
|
256
|
-
// First call custom spawn handler if scaler has @OnSpawnWorker defined
|
|
257
|
-
if (scaler?.methods.onSpawnWorker) {
|
|
258
|
-
await scaler.scalerInstance[scaler.methods.onSpawnWorker](entityId);
|
|
259
|
-
}
|
|
260
|
-
// Also auto-create worker if processor is registered (and scaler didn't create one)
|
|
261
|
-
if (processor) {
|
|
262
|
-
await this.createWorkerForEntity(entityType, entityId);
|
|
263
|
-
}
|
|
264
|
-
// If neither scaler nor processor can handle this, log a warning
|
|
265
|
-
if (!scaler?.methods.onSpawnWorker && !processor) {
|
|
266
|
-
this.logger.warn(`No spawn handler for entity type '${entityType}'. ` +
|
|
267
|
-
`Either add @OnSpawnWorker() to your scaler or register a @WorkerProcessor.`);
|
|
268
|
-
}
|
|
269
|
-
});
|
|
270
|
-
this.logger.debug('Spawn worker handler registered with ServiceQueueManager');
|
|
271
164
|
}
|
|
272
165
|
/**
|
|
273
166
|
* Auto-discover and register commands/queries from @nestjs/cqrs handlers
|
|
@@ -278,358 +171,88 @@ let ProcessorDiscoveryService = ProcessorDiscoveryService_1 = class ProcessorDis
|
|
|
278
171
|
this.logger.log(`Auto-registered ${commands} commands and ${queries} queries from CQRS handlers`);
|
|
279
172
|
}
|
|
280
173
|
}
|
|
174
|
+
// ==========================================================================
|
|
175
|
+
// PUBLIC API — Delegated to Registry
|
|
176
|
+
// ==========================================================================
|
|
281
177
|
/**
|
|
282
|
-
*
|
|
178
|
+
* Get registered processor for an entity type
|
|
283
179
|
*/
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
for (const wrapper of providers) {
|
|
287
|
-
const { instance, metatype } = wrapper;
|
|
288
|
-
if (!instance || !metatype)
|
|
289
|
-
continue;
|
|
290
|
-
// Cast to Type<any> for metadata functions
|
|
291
|
-
const targetClass = metatype;
|
|
292
|
-
const options = (0, decorators_1.getWorkerProcessorMetadata)(targetClass);
|
|
293
|
-
if (!options)
|
|
294
|
-
continue;
|
|
295
|
-
this.registerProcessor(targetClass, instance, options);
|
|
296
|
-
}
|
|
297
|
-
this.logger.log(`Discovered ${this.processors.size} worker processor(s): ${Array.from(this.processors.keys()).join(', ')}`);
|
|
180
|
+
getProcessor(entityType) {
|
|
181
|
+
return this.registry.getProcessor(entityType);
|
|
298
182
|
}
|
|
299
183
|
/**
|
|
300
|
-
*
|
|
184
|
+
* Get registered scaler for an entity type
|
|
301
185
|
*/
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
for (const wrapper of providers) {
|
|
305
|
-
const { instance, metatype } = wrapper;
|
|
306
|
-
if (!instance || !metatype)
|
|
307
|
-
continue;
|
|
308
|
-
// Cast to Type<any> for metadata functions
|
|
309
|
-
const targetClass = metatype;
|
|
310
|
-
const options = (0, decorators_1.getEntityScalerMetadata)(targetClass);
|
|
311
|
-
if (!options)
|
|
312
|
-
continue;
|
|
313
|
-
this.registerScaler(targetClass, instance, options);
|
|
314
|
-
}
|
|
315
|
-
this.logger.log(`Discovered ${this.scalers.size} entity scaler(s): ${Array.from(this.scalers.keys()).join(', ')}`);
|
|
186
|
+
getScaler(entityType) {
|
|
187
|
+
return this.registry.getScaler(entityType);
|
|
316
188
|
}
|
|
317
189
|
/**
|
|
318
|
-
*
|
|
190
|
+
* Get all registered entity types
|
|
319
191
|
*/
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
// Build job handlers map
|
|
323
|
-
const handlers = (0, decorators_1.getJobHandlerMetadata)(metatype);
|
|
324
|
-
const jobHandlers = new Map();
|
|
325
|
-
let wildcardHandler;
|
|
326
|
-
for (const handler of handlers) {
|
|
327
|
-
if (handler.isWildcard) {
|
|
328
|
-
wildcardHandler = { method: handler.methodName };
|
|
329
|
-
}
|
|
330
|
-
else {
|
|
331
|
-
jobHandlers.set(handler.jobName, {
|
|
332
|
-
method: handler.methodName,
|
|
333
|
-
isWildcard: false,
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
// Build queue and worker name functions
|
|
338
|
-
const keyPrefix = this.config.keyPrefix || 'aq';
|
|
339
|
-
const queueNameFn = typeof options.queueName === 'function'
|
|
340
|
-
? options.queueName
|
|
341
|
-
: options.queueName
|
|
342
|
-
? () => options.queueName
|
|
343
|
-
: (entityId) => `${keyPrefix}:${entityType}:${entityId}:queue`;
|
|
344
|
-
const workerNameFn = typeof options.workerName === 'function'
|
|
345
|
-
? options.workerName
|
|
346
|
-
: options.workerName
|
|
347
|
-
? () => options.workerName
|
|
348
|
-
: (entityId) => `${keyPrefix}:${entityType}:${entityId}:worker`;
|
|
349
|
-
const processor = {
|
|
350
|
-
entityType,
|
|
351
|
-
processorInstance: instance,
|
|
352
|
-
options,
|
|
353
|
-
jobHandlers,
|
|
354
|
-
wildcardHandler,
|
|
355
|
-
queueNameFn,
|
|
356
|
-
workerNameFn,
|
|
357
|
-
};
|
|
358
|
-
this.processors.set(entityType, processor);
|
|
359
|
-
this.activeWorkers.set(entityType, new Set());
|
|
360
|
-
this.logger.debug(`Registered processor for entity type '${entityType}' with ${jobHandlers.size} job handlers` +
|
|
361
|
-
(wildcardHandler ? ' and wildcard handler' : ''));
|
|
192
|
+
getRegisteredEntityTypes() {
|
|
193
|
+
return this.registry.getRegisteredEntityTypes();
|
|
362
194
|
}
|
|
363
195
|
/**
|
|
364
|
-
*
|
|
196
|
+
* Check if a worker exists for an entity
|
|
365
197
|
*/
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
// Find decorated methods
|
|
369
|
-
const methods = {
|
|
370
|
-
getActiveEntities: Reflect.getMetadata(decorators_1.GET_ACTIVE_ENTITIES_METADATA + ':method', metatype),
|
|
371
|
-
getDesiredWorkerCount: Reflect.getMetadata(decorators_1.GET_DESIRED_WORKER_COUNT_METADATA + ':method', metatype),
|
|
372
|
-
onSpawnWorker: Reflect.getMetadata(decorators_1.ON_SPAWN_WORKER_METADATA + ':method', metatype),
|
|
373
|
-
onTerminateWorker: Reflect.getMetadata(decorators_1.ON_TERMINATE_WORKER_METADATA + ':method', metatype),
|
|
374
|
-
};
|
|
375
|
-
const scaler = {
|
|
376
|
-
entityType,
|
|
377
|
-
scalerInstance: instance,
|
|
378
|
-
options,
|
|
379
|
-
methods,
|
|
380
|
-
};
|
|
381
|
-
this.scalers.set(entityType, scaler);
|
|
382
|
-
this.logger.debug(`Registered scaler for entity type '${entityType}' with methods: ` +
|
|
383
|
-
Object.entries(methods)
|
|
384
|
-
.filter(([_, v]) => v)
|
|
385
|
-
.map(([k, _]) => k)
|
|
386
|
-
.join(', '));
|
|
198
|
+
hasActiveWorker(entityType, entityId) {
|
|
199
|
+
return this.registry.hasActiveWorker(entityType, entityId);
|
|
387
200
|
}
|
|
388
201
|
/**
|
|
389
|
-
*
|
|
202
|
+
* Get all active workers for an entity type
|
|
390
203
|
*/
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
this.logger.warn('CronManager not available. Automatic scaling disabled.');
|
|
394
|
-
return;
|
|
395
|
-
}
|
|
396
|
-
for (const [entityType, scaler] of this.scalers) {
|
|
397
|
-
const processor = this.processors.get(entityType);
|
|
398
|
-
const scalingConfig = {
|
|
399
|
-
entityType,
|
|
400
|
-
maxWorkersPerEntity: scaler.options.maxWorkersPerEntity ?? 1,
|
|
401
|
-
idleTimeoutSeconds: scaler.options.idleTimeoutSeconds ?? 15,
|
|
402
|
-
getActiveEntityIds: async () => {
|
|
403
|
-
if (scaler.methods.getActiveEntities) {
|
|
404
|
-
return scaler.scalerInstance[scaler.methods.getActiveEntities]();
|
|
405
|
-
}
|
|
406
|
-
return [];
|
|
407
|
-
},
|
|
408
|
-
getDesiredWorkerCount: async (entityId) => {
|
|
409
|
-
if (scaler.methods.getDesiredWorkerCount) {
|
|
410
|
-
return scaler.scalerInstance[scaler.methods.getDesiredWorkerCount](entityId);
|
|
411
|
-
}
|
|
412
|
-
return 1; // Default to 1 worker
|
|
413
|
-
},
|
|
414
|
-
onSpawnWorker: async (entityId) => {
|
|
415
|
-
// First call custom spawn handler if defined
|
|
416
|
-
if (scaler.methods.onSpawnWorker) {
|
|
417
|
-
await scaler.scalerInstance[scaler.methods.onSpawnWorker](entityId);
|
|
418
|
-
}
|
|
419
|
-
// Auto-create worker if processor is registered
|
|
420
|
-
if (processor) {
|
|
421
|
-
await this.createWorkerForEntity(entityType, entityId);
|
|
422
|
-
}
|
|
423
|
-
},
|
|
424
|
-
onTerminateWorker: async (entityId, workerId) => {
|
|
425
|
-
// First call custom terminate handler if defined
|
|
426
|
-
if (scaler.methods.onTerminateWorker) {
|
|
427
|
-
await scaler.scalerInstance[scaler.methods.onTerminateWorker](entityId, workerId);
|
|
428
|
-
}
|
|
429
|
-
// Auto-terminate worker if processor is registered
|
|
430
|
-
if (processor) {
|
|
431
|
-
const workerName = processor.workerNameFn(entityId);
|
|
432
|
-
await this.workerManager.signalWorkerClose(workerName);
|
|
433
|
-
}
|
|
434
|
-
},
|
|
435
|
-
};
|
|
436
|
-
this.cronManager.registerEntityType(scalingConfig);
|
|
437
|
-
this.logger.log(`Registered scaling config for entity type '${entityType}' (idleTimeout: ${scalingConfig.idleTimeoutSeconds}s)`);
|
|
438
|
-
}
|
|
204
|
+
getActiveWorkers(entityType) {
|
|
205
|
+
return this.registry.getActiveWorkers(entityType);
|
|
439
206
|
}
|
|
207
|
+
// ==========================================================================
|
|
208
|
+
// PUBLIC API — Delegated to WorkerFactory
|
|
209
|
+
// ==========================================================================
|
|
440
210
|
/**
|
|
441
211
|
* Create a worker for an entity using the registered processor
|
|
442
212
|
*/
|
|
443
213
|
async createWorkerForEntity(entityType, entityId) {
|
|
444
|
-
|
|
445
|
-
if (!processor) {
|
|
446
|
-
throw new Error(`No processor registered for entity type: ${entityType}`);
|
|
447
|
-
}
|
|
448
|
-
const workerName = processor.workerNameFn(entityId);
|
|
449
|
-
const queueName = processor.queueNameFn(entityId);
|
|
450
|
-
// Check if worker already exists
|
|
451
|
-
if (await this.workerManager.workerExists(workerName)) {
|
|
452
|
-
this.logger.debug(`Worker ${workerName} already exists, skipping`);
|
|
453
|
-
return;
|
|
454
|
-
}
|
|
455
|
-
this.logger.log(`Creating worker ${workerName} for ${entityType}:${entityId}`);
|
|
456
|
-
// Ensure queue exists
|
|
457
|
-
this.queueManager.getOrCreateQueue(queueName);
|
|
458
|
-
// Create the worker with the processor
|
|
459
|
-
const workerConfig = {
|
|
460
|
-
concurrency: 1,
|
|
461
|
-
stalledInterval: 1000,
|
|
462
|
-
lockDuration: 30000,
|
|
463
|
-
heartbeatTTL: 3,
|
|
464
|
-
heartbeatInterval: 1000,
|
|
465
|
-
...this.config.workerDefaults,
|
|
466
|
-
...processor.options.workerConfig,
|
|
467
|
-
};
|
|
468
|
-
await this.workerManager.createWorker({
|
|
469
|
-
workerName,
|
|
470
|
-
queueName,
|
|
471
|
-
config: workerConfig,
|
|
472
|
-
processor: async (job) => {
|
|
473
|
-
return this.processJob(processor, job, entityId);
|
|
474
|
-
},
|
|
475
|
-
events: {
|
|
476
|
-
onReady: async () => {
|
|
477
|
-
this.logger.log(`Worker ${workerName} ready`);
|
|
478
|
-
this.activeWorkers.get(entityType)?.add(entityId);
|
|
479
|
-
},
|
|
480
|
-
onCompleted: async (job) => {
|
|
481
|
-
this.logger.debug(`Worker ${workerName}: Job ${job.id} completed`);
|
|
482
|
-
},
|
|
483
|
-
onFailed: async (job, error) => {
|
|
484
|
-
this.logger.error(`Worker ${workerName}: Job ${job?.id} failed: ${error.message}`);
|
|
485
|
-
},
|
|
486
|
-
onClosed: async () => {
|
|
487
|
-
this.logger.log(`Worker ${workerName} closed`);
|
|
488
|
-
this.activeWorkers.get(entityType)?.delete(entityId);
|
|
489
|
-
},
|
|
490
|
-
},
|
|
491
|
-
});
|
|
492
|
-
}
|
|
493
|
-
/**
|
|
494
|
-
* Process a job using the registered handlers
|
|
495
|
-
*
|
|
496
|
-
* Priority order:
|
|
497
|
-
* 1. Explicit @JobHandler on the processor class (if instance exists)
|
|
498
|
-
* 2. Auto-routing via @JobCommand/@JobQuery decorated classes
|
|
499
|
-
* 3. QueueBus registry lookup (class name as job name)
|
|
500
|
-
* 4. Wildcard @JobHandler('*') on the processor class (if instance exists)
|
|
501
|
-
*/
|
|
502
|
-
async processJob(processor, job, entityId) {
|
|
503
|
-
const { processorInstance, jobHandlers, wildcardHandler, entityType } = processor;
|
|
504
|
-
const jobName = job.name;
|
|
505
|
-
// 1. Try to find specific @JobHandler (only if processor has an instance)
|
|
506
|
-
if (processorInstance) {
|
|
507
|
-
const handler = jobHandlers.get(jobName);
|
|
508
|
-
if (handler) {
|
|
509
|
-
return processorInstance[handler.method](job, entityId);
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
// 2. Try auto-routing via @JobCommand/@JobQuery
|
|
513
|
-
if (this.commandDiscovery) {
|
|
514
|
-
const result = await this.commandDiscovery.executeJob(job, entityId, entityType);
|
|
515
|
-
if (result !== undefined) {
|
|
516
|
-
return result;
|
|
517
|
-
}
|
|
518
|
-
// Check if a handler exists (even if it returned undefined)
|
|
519
|
-
if (this.commandDiscovery.hasHandler(jobName, entityType)) {
|
|
520
|
-
return result;
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
// 3. Try QueueBus registry lookup (job.name = class name like 'MakeBetCommand')
|
|
524
|
-
const registryEntry = queue_bus_1.QueueBus.getRegistered(jobName);
|
|
525
|
-
if (registryEntry) {
|
|
526
|
-
return this.executeFromRegistry(registryEntry, job, entityId);
|
|
527
|
-
}
|
|
528
|
-
// 4. Fall back to wildcard handler (only if processor has an instance)
|
|
529
|
-
if (processorInstance && wildcardHandler) {
|
|
530
|
-
return processorInstance[wildcardHandler.method](job, entityId);
|
|
531
|
-
}
|
|
532
|
-
// No handler found
|
|
533
|
-
this.logger.warn(`No handler found for job '${jobName}' on entity type '${entityType}'`);
|
|
534
|
-
return null;
|
|
535
|
-
}
|
|
536
|
-
/**
|
|
537
|
-
* Execute a command/query from QueueBus registry
|
|
538
|
-
*/
|
|
539
|
-
async executeFromRegistry(entry, job, entityId) {
|
|
540
|
-
const { targetClass, isQuery, className } = entry;
|
|
541
|
-
// Instantiate the command/query with job data
|
|
542
|
-
const instance = Object.assign(new targetClass(), job.data);
|
|
543
|
-
if (isQuery) {
|
|
544
|
-
if (!this.queryBus) {
|
|
545
|
-
this.logger.error(`QueryBus not set. Cannot execute query ${className}. Call setQueryBus() first.`);
|
|
546
|
-
return null;
|
|
547
|
-
}
|
|
548
|
-
return this.queryBus.execute(instance);
|
|
549
|
-
}
|
|
550
|
-
else {
|
|
551
|
-
if (!this.commandBus) {
|
|
552
|
-
this.logger.error(`CommandBus not set. Cannot execute command ${className}. Call setCommandBus() first.`);
|
|
553
|
-
return null;
|
|
554
|
-
}
|
|
555
|
-
return this.commandBus.execute(instance);
|
|
556
|
-
}
|
|
214
|
+
return this.workerFactory.createWorkerForEntity(entityType, entityId);
|
|
557
215
|
}
|
|
558
216
|
// ==========================================================================
|
|
559
|
-
// PUBLIC API
|
|
217
|
+
// PUBLIC API — Manual Registration (Delegated to DecoratorDiscovery)
|
|
560
218
|
// ==========================================================================
|
|
561
219
|
/**
|
|
562
220
|
* Manually register a processor class
|
|
563
|
-
* Use this when auto-discovery is not available or for dynamic registration
|
|
564
221
|
*/
|
|
565
222
|
async registerProcessorClass(processorClass, instance) {
|
|
566
|
-
const
|
|
223
|
+
const { getWorkerProcessorMetadata } = await Promise.resolve().then(() => __importStar(require('../../decorators')));
|
|
224
|
+
const options = getWorkerProcessorMetadata(processorClass);
|
|
567
225
|
if (!options) {
|
|
568
226
|
throw new Error(`Class ${processorClass.name} is not decorated with @WorkerProcessor`);
|
|
569
227
|
}
|
|
570
228
|
const resolvedInstance = instance || this.moduleRef.get(processorClass, { strict: false });
|
|
571
|
-
this.registerProcessor(processorClass, resolvedInstance, options);
|
|
229
|
+
this.decoratorDiscovery.registerProcessor(this.registry, processorClass, resolvedInstance, options);
|
|
572
230
|
}
|
|
573
231
|
/**
|
|
574
232
|
* Manually register a scaler class
|
|
575
233
|
*/
|
|
576
234
|
async registerScalerClass(scalerClass, instance) {
|
|
577
|
-
const
|
|
235
|
+
const { getEntityScalerMetadata } = await Promise.resolve().then(() => __importStar(require('../../decorators')));
|
|
236
|
+
const options = getEntityScalerMetadata(scalerClass);
|
|
578
237
|
if (!options) {
|
|
579
238
|
throw new Error(`Class ${scalerClass.name} is not decorated with @EntityScaler`);
|
|
580
239
|
}
|
|
581
240
|
const resolvedInstance = instance || this.moduleRef.get(scalerClass, { strict: false });
|
|
582
|
-
this.registerScaler(scalerClass, resolvedInstance, options);
|
|
583
|
-
}
|
|
584
|
-
/**
|
|
585
|
-
* Get registered processor for an entity type
|
|
586
|
-
*/
|
|
587
|
-
getProcessor(entityType) {
|
|
588
|
-
return this.processors.get(entityType);
|
|
589
|
-
}
|
|
590
|
-
/**
|
|
591
|
-
* Get registered scaler for an entity type
|
|
592
|
-
*/
|
|
593
|
-
getScaler(entityType) {
|
|
594
|
-
return this.scalers.get(entityType);
|
|
595
|
-
}
|
|
596
|
-
/**
|
|
597
|
-
* Get all registered entity types
|
|
598
|
-
*/
|
|
599
|
-
getRegisteredEntityTypes() {
|
|
600
|
-
return Array.from(new Set([...this.processors.keys(), ...this.scalers.keys()]));
|
|
601
|
-
}
|
|
602
|
-
/**
|
|
603
|
-
* Check if a worker exists for an entity
|
|
604
|
-
*/
|
|
605
|
-
hasActiveWorker(entityType, entityId) {
|
|
606
|
-
return this.activeWorkers.get(entityType)?.has(entityId) ?? false;
|
|
607
|
-
}
|
|
608
|
-
/**
|
|
609
|
-
* Get all active workers for an entity type
|
|
610
|
-
*/
|
|
611
|
-
getActiveWorkers(entityType) {
|
|
612
|
-
return Array.from(this.activeWorkers.get(entityType) || []);
|
|
241
|
+
this.decoratorDiscovery.registerScaler(this.registry, scalerClass, resolvedInstance, options);
|
|
613
242
|
}
|
|
614
243
|
};
|
|
615
244
|
exports.ProcessorDiscoveryService = ProcessorDiscoveryService;
|
|
616
245
|
exports.ProcessorDiscoveryService = ProcessorDiscoveryService = ProcessorDiscoveryService_1 = __decorate([
|
|
617
246
|
(0, common_1.Injectable)(),
|
|
618
247
|
__param(0, (0, common_1.Optional)()),
|
|
619
|
-
__param(1, (0, common_1.Optional)()),
|
|
620
|
-
__param(5, (0, common_1.Optional)()),
|
|
621
248
|
__param(6, (0, common_1.Optional)()),
|
|
622
|
-
__param(7, (0, common_1.
|
|
623
|
-
__param(8, (0, common_1.Optional)()),
|
|
624
|
-
__param(9, (0, common_1.Inject)(constants_1.ATOMIC_QUEUES_CONFIG)),
|
|
249
|
+
__param(7, (0, common_1.Inject)(constants_1.ATOMIC_QUEUES_CONFIG)),
|
|
625
250
|
__metadata("design:paramtypes", [core_1.DiscoveryService,
|
|
626
|
-
core_1.MetadataScanner,
|
|
627
251
|
core_1.ModuleRef,
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
queue_events_manager_1.QueueEventsManagerService, Object])
|
|
252
|
+
processor_registry_1.ProcessorRegistry,
|
|
253
|
+
decorator_discovery_service_1.DecoratorDiscoveryService,
|
|
254
|
+
worker_factory_service_1.WorkerFactoryService,
|
|
255
|
+
scaling_registration_service_1.ScalingRegistrationService,
|
|
256
|
+
command_discovery_1.CommandDiscoveryService, Object])
|
|
634
257
|
], ProcessorDiscoveryService);
|
|
635
258
|
//# sourceMappingURL=processor-discovery.service.js.map
|