@rudderstack/integrations-lib 0.2.38 → 0.2.40

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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=examples.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"examples.d.ts","sourceRoot":"","sources":["../../src/cluster/examples.ts"],"names":[],"mappings":""}
@@ -0,0 +1,150 @@
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
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ /* eslint-disable require-await */
40
+ const cluster_1 = __importDefault(require("cluster"));
41
+ const manager_1 = require("./manager");
42
+ const logger = __importStar(require("../logger"));
43
+ async function normalExample() {
44
+ const manager = new manager_1.ClusterManager({
45
+ numWorkers: 2,
46
+ pingFrequency: 1000, // Check every second
47
+ pingTimeout: 5000, // 5 seconds for a worker to respond
48
+ shutdownTimeout: 5000, // 5 seconds for graceful shutdown
49
+ primaryFn: async () => {
50
+ setTimeout(() => {
51
+ logger.info('Primary process shutting down...');
52
+ manager.shutdown('manual shutdown');
53
+ }, 10000);
54
+ },
55
+ primaryShutdownFn: async (signal) => {
56
+ logger.info(`Primary process shutting down due to signal: ${signal}`);
57
+ },
58
+ workerFn: async () => {
59
+ // Simulate some work
60
+ setInterval(() => {
61
+ logger.info(`Worker ${cluster_1.default.worker?.id} is doing work`);
62
+ }, 1000);
63
+ },
64
+ workerShutdownFn: async (signal) => {
65
+ logger.info(`Worker ${cluster_1.default.worker?.id} shutting down due to signal: ${signal}`);
66
+ },
67
+ });
68
+ await manager.start();
69
+ }
70
+ async function stuckExample() {
71
+ let stuckCounter = 0;
72
+ const manager = new manager_1.ClusterManager({
73
+ numWorkers: 2,
74
+ pingFrequency: 1000, // Check every second
75
+ pingTimeout: 5000, // 5 seconds for a worker to respond
76
+ shutdownTimeout: 5000, // 5 seconds for graceful shutdown
77
+ stuckWorkerRespawnFunc: (worker) => {
78
+ stuckCounter += 1;
79
+ if (stuckCounter > 3) {
80
+ logger.info(`Stuck worker detected: ${worker.id}. Not respawning anymore.`);
81
+ return false; // Stop respawning after 3 stuck workers
82
+ }
83
+ logger.info(`Stuck worker detected: ${worker.id}. Respawning...`);
84
+ return true; // Respawn the worker
85
+ },
86
+ primaryFn: async () => {
87
+ logger.info('Primary process started');
88
+ },
89
+ primaryShutdownFn: async (signal) => {
90
+ logger.info(`Primary process shutting down due to signal: ${signal}`);
91
+ },
92
+ workerFn: async () => {
93
+ logger.info(`Worker ${cluster_1.default.worker?.id} will simulate being stuck`);
94
+ // eslint-disable-next-line no-constant-condition
95
+ while (true) {
96
+ // Simulate a stuck worker
97
+ }
98
+ },
99
+ workerShutdownFn: async (signal) => {
100
+ logger.info(`Worker ${cluster_1.default.worker?.id} shutting down due to signal: ${signal}`);
101
+ },
102
+ });
103
+ await manager.start();
104
+ }
105
+ async function killExample() {
106
+ const manager = new manager_1.ClusterManager({
107
+ numWorkers: 2,
108
+ pingFrequency: 1000, // Check every second
109
+ pingTimeout: 5000, // 5 seconds for a worker to respond
110
+ shutdownTimeout: 5000, // 5 seconds for graceful shutdown
111
+ restartMaxTimes: 3, // Restart a worker up to 3 times
112
+ primaryFn: async () => {
113
+ logger.info('Primary process started');
114
+ },
115
+ primaryShutdownFn: async (signal) => {
116
+ logger.info(`Primary process shutting down due to signal: ${signal}`);
117
+ },
118
+ workerFn: async () => {
119
+ logger.info(`Worker ${cluster_1.default.worker?.id} started and will crash after 5 seconds`);
120
+ // eslint-disable-next-line no-constant-condition
121
+ setTimeout(() => {
122
+ logger.info(`Killing worker ${cluster_1.default.worker?.id} process`);
123
+ process.exit(1); // Simulate a worker crash
124
+ }, 5000); // Kill the worker after 5 seconds
125
+ },
126
+ workerShutdownFn: async (signal) => {
127
+ logger.info(`Worker ${cluster_1.default.worker?.id} shutting down due to signal: ${signal}`);
128
+ },
129
+ });
130
+ await manager.start();
131
+ }
132
+ // to run use: npx ts-node src/cluster/examples.ts [normal|stuck|kill]
133
+ if (require.main === module) {
134
+ const mode = process.argv[2] || 'normal';
135
+ let run;
136
+ if (mode === 'stuck') {
137
+ run = stuckExample;
138
+ }
139
+ else if (mode === 'kill') {
140
+ run = killExample;
141
+ }
142
+ else {
143
+ run = normalExample;
144
+ }
145
+ run().catch((err) => {
146
+ logger.error(err);
147
+ process.exit(1);
148
+ });
149
+ }
150
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhhbXBsZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY2x1c3Rlci9leGFtcGxlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGtDQUFrQztBQUNsQyxzREFBOEI7QUFDOUIsdUNBQTJDO0FBQzNDLGtEQUFvQztBQUVwQyxLQUFLLFVBQVUsYUFBYTtJQUMxQixNQUFNLE9BQU8sR0FBRyxJQUFJLHdCQUFjLENBQUM7UUFDakMsVUFBVSxFQUFFLENBQUM7UUFDYixhQUFhLEVBQUUsSUFBSSxFQUFFLHFCQUFxQjtRQUMxQyxXQUFXLEVBQUUsSUFBSSxFQUFFLG9DQUFvQztRQUN2RCxlQUFlLEVBQUUsSUFBSSxFQUFFLGtDQUFrQztRQUN6RCxTQUFTLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDcEIsVUFBVSxDQUFDLEdBQUcsRUFBRTtnQkFDZCxNQUFNLENBQUMsSUFBSSxDQUFDLGtDQUFrQyxDQUFDLENBQUM7Z0JBQ2hELE9BQU8sQ0FBQyxRQUFRLENBQUMsaUJBQWlCLENBQUMsQ0FBQztZQUN0QyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDWixDQUFDO1FBQ0QsaUJBQWlCLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ2xDLE1BQU0sQ0FBQyxJQUFJLENBQUMsZ0RBQWdELE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDeEUsQ0FBQztRQUNELFFBQVEsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNuQixxQkFBcUI7WUFDckIsV0FBVyxDQUFDLEdBQUcsRUFBRTtnQkFDZixNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsaUJBQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1lBQzVELENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNYLENBQUM7UUFDRCxnQkFBZ0IsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEVBQUU7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c2FibGUgcmVxdWlyZS1hd2FpdCAqL1xuaW1wb3J0IGNsdXN0ZXIgZnJvbSAnY2x1c3Rlcic7XG5pbXBvcnQgeyBDbHVzdGVyTWFuYWdlciB9IGZyb20gJy4vbWFuYWdlcic7XG5pbXBvcnQgKiBhcyBsb2dnZXIgZnJvbSAnLi4vbG9nZ2VyJztcblxuYXN5bmMgZnVuY3Rpb24gbm9ybWFsRXhhbXBsZSgpIHtcbiAgY29uc3QgbWFuYWdlciA9IG5ldyBDbHVzdGVyTWFuYWdlcih7XG4gICAgbnVtV29ya2VyczogMixcbiAgICBwaW5nRnJlcXVlbmN5OiAxMDAwLCAvLyBDaGVjayBldmVyeSBzZWNvbmRcbiAgICBwaW5nVGltZW91dDogNTAwMCwgLy8gNSBzZWNvbmRzIGZvciBhIHdvcmtlciB0byByZXNwb25kXG4gICAgc2h1dGRvd25UaW1lb3V0OiA1MDAwLCAvLyA1IHNlY29uZHMgZm9yIGdyYWNlZnVsIHNodXRkb3duXG4gICAgcHJpbWFyeUZuOiBhc3luYyAoKSA9PiB7XG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgbG9nZ2VyLmluZm8oJ1ByaW1hcnkgcHJvY2VzcyBzaHV0dGluZyBkb3duLi4uJyk7XG4gICAgICAgIG1hbmFnZXIuc2h1dGRvd24oJ21hbnVhbCBzaHV0ZG93bicpO1xuICAgICAgfSwgMTAwMDApO1xuICAgIH0sXG4gICAgcHJpbWFyeVNodXRkb3duRm46IGFzeW5jIChzaWduYWwpID0+IHtcbiAgICAgIGxvZ2dlci5pbmZvKGBQcmltYXJ5IHByb2Nlc3Mgc2h1dHRpbmcgZG93biBkdWUgdG8gc2lnbmFsOiAke3NpZ25hbH1gKTtcbiAgICB9LFxuICAgIHdvcmtlckZuOiBhc3luYyAoKSA9PiB7XG4gICAgICAvLyBTaW11bGF0ZSBzb21lIHdvcmtcbiAgICAgIHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgbG9nZ2VyLmluZm8oYFdvcmtlciAke2NsdXN0ZXIud29ya2VyPy5pZH0gaXMgZG9pbmcgd29ya2ApO1xuICAgICAgfSwgMTAwMCk7XG4gICAgfSxcbiAgICB3b3JrZXJTaHV0ZG93bkZuOiBhc3luYyAoc2lnbmFsKSA9PiB7XG4gICAgICBsb2dnZXIuaW5mbyhgV29ya2VyICR7Y2x1c3Rlci53b3JrZXI/LmlkfSBzaHV0dGluZyBkb3duIGR1ZSB0byBzaWduYWw6ICR7c2lnbmFsfWApO1xuICAgIH0sXG4gIH0pO1xuICBhd2FpdCBtYW5hZ2VyLnN0YXJ0KCk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHN0dWNrRXhhbXBsZSgpIHtcbiAgbGV0IHN0dWNrQ291bnRlciA9IDA7XG4gIGNvbnN0IG1hbmFnZXIgPSBuZXcgQ2x1c3Rlck1hbmFnZXIoe1xuICAgIG51bVdvcmtlcnM6IDIsXG4gICAgcGluZ0ZyZXF1ZW5jeTogMTAwMCwgLy8gQ2hlY2sgZXZlcnkgc2Vjb25kXG4gICAgcGluZ1RpbWVvdXQ6IDUwMDAsIC8vIDUgc2Vjb25kcyBmb3IgYSB3b3JrZXIgdG8gcmVzcG9uZFxuICAgIHNodXRkb3duVGltZW91dDogNTAwMCwgLy8gNSBzZWNvbmRzIGZvciBncmFjZWZ1bCBzaHV0ZG93blxuICAgIHN0dWNrV29ya2VyUmVzcGF3bkZ1bmM6ICh3b3JrZXIpID0+IHtcbiAgICAgIHN0dWNrQ291bnRlciArPSAxO1xuICAgICAgaWYgKHN0dWNrQ291bnRlciA+IDMpIHtcbiAgICAgICAgbG9nZ2VyLmluZm8oYFN0dWNrIHdvcmtlciBkZXRlY3RlZDogJHt3b3JrZXIuaWR9LiBOb3QgcmVzcGF3bmluZyBhbnltb3JlLmApO1xuICAgICAgICByZXR1cm4gZmFsc2U7IC8vIFN0b3AgcmVzcGF3bmluZyBhZnRlciAzIHN0dWNrIHdvcmtlcnNcbiAgICAgIH1cbiAgICAgIGxvZ2dlci5pbmZvKGBTdHVjayB3b3JrZXIgZGV0ZWN0ZWQ6ICR7d29ya2VyLmlkfS4gUmVzcGF3bmluZy4uLmApO1xuICAgICAgcmV0dXJuIHRydWU7IC8vIFJlc3Bhd24gdGhlIHdvcmtlclxuICAgIH0sXG4gICAgcHJpbWFyeUZuOiBhc3luYyAoKSA9PiB7XG4gICAgICBsb2dnZXIuaW5mbygnUHJpbWFyeSBwcm9jZXNzIHN0YXJ0ZWQnKTtcbiAgICB9LFxuICAgIHByaW1hcnlTaHV0ZG93bkZuOiBhc3luYyAoc2lnbmFsKSA9PiB7XG4gICAgICBsb2dnZXIuaW5mbyhgUHJpbWFyeSBwcm9jZXNzIHNodXR0aW5nIGRvd24gZHVlIHRvIHNpZ25hbDogJHtzaWduYWx9YCk7XG4gICAgfSxcbiAgICB3b3JrZXJGbjogYXN5bmMgKCkgPT4ge1xuICAgICAgbG9nZ2VyLmluZm8oYFdvcmtlciAke2NsdXN0ZXIud29ya2VyPy5pZH0gd2lsbCBzaW11bGF0ZSBiZWluZyBzdHVja2ApO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnN0YW50LWNvbmRpdGlvblxuICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgLy8gU2ltdWxhdGUgYSBzdHVjayB3b3JrZXJcbiAgICAgIH1cbiAgICB9LFxuICAgIHdvcmtlclNodXRkb3duRm46IGFzeW5jIChzaWduYWwpID0+IHtcbiAgICAgIGxvZ2dlci5pbmZvKGBXb3JrZXIgJHtjbHVzdGVyLndvcmtlcj8uaWR9IHNodXR0aW5nIGRvd24gZHVlIHRvIHNpZ25hbDogJHtzaWduYWx9YCk7XG4gICAgfSxcbiAgfSk7XG4gIGF3YWl0IG1hbmFnZXIuc3RhcnQoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24ga2lsbEV4YW1wbGUoKSB7XG4gIGNvbnN0IG1hbmFnZXIgPSBuZXcgQ2x1c3Rlck1hbmFnZXIoe1xuICAgIG51bVdvcmtlcnM6IDIsXG4gICAgcGluZ0ZyZXF1ZW5jeTogMTAwMCwgLy8gQ2hlY2sgZXZlcnkgc2Vjb25kXG4gICAgcGluZ1RpbWVvdXQ6IDUwMDAsIC8vIDUgc2Vjb25kcyBmb3IgYSB3b3JrZXIgdG8gcmVzcG9uZFxuICAgIHNodXRkb3duVGltZW91dDogNTAwMCwgLy8gNSBzZWNvbmRzIGZvciBncmFjZWZ1bCBzaHV0ZG93blxuICAgIHJlc3RhcnRNYXhUaW1lczogMywgLy8gUmVzdGFydCBhIHdvcmtlciB1cCB0byAzIHRpbWVzXG4gICAgcHJpbWFyeUZuOiBhc3luYyAoKSA9PiB7XG4gICAgICBsb2dnZXIuaW5mbygnUHJpbWFyeSBwcm9jZXNzIHN0YXJ0ZWQnKTtcbiAgICB9LFxuICAgIHByaW1hcnlTaHV0ZG93bkZuOiBhc3luYyAoc2lnbmFsKSA9PiB7XG4gICAgICBsb2dnZXIuaW5mbyhgUHJpbWFyeSBwcm9jZXNzIHNodXR0aW5nIGRvd24gZHVlIHRvIHNpZ25hbDogJHtzaWduYWx9YCk7XG4gICAgfSxcbiAgICB3b3JrZXJGbjogYXN5bmMgKCkgPT4ge1xuICAgICAgbG9nZ2VyLmluZm8oYFdvcmtlciAke2NsdXN0ZXIud29ya2VyPy5pZH0gc3RhcnRlZCBhbmQgd2lsbCBjcmFzaCBhZnRlciA1IHNlY29uZHNgKTtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zdGFudC1jb25kaXRpb25cbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICBsb2dnZXIuaW5mbyhgS2lsbGluZyB3b3JrZXIgJHtjbHVzdGVyLndvcmtlcj8uaWR9IHByb2Nlc3NgKTtcbiAgICAgICAgcHJvY2Vzcy5leGl0KDEpOyAvLyBTaW11bGF0ZSBhIHdvcmtlciBjcmFzaFxuICAgICAgfSwgNTAwMCk7IC8vIEtpbGwgdGhlIHdvcmtlciBhZnRlciA1IHNlY29uZHNcbiAgICB9LFxuICAgIHdvcmtlclNodXRkb3duRm46IGFzeW5jIChzaWduYWwpID0+IHtcbiAgICAgIGxvZ2dlci5pbmZvKGBXb3JrZXIgJHtjbHVzdGVyLndvcmtlcj8uaWR9IHNodXR0aW5nIGRvd24gZHVlIHRvIHNpZ25hbDogJHtzaWduYWx9YCk7XG4gICAgfSxcbiAgfSk7XG4gIGF3YWl0IG1hbmFnZXIuc3RhcnQoKTtcbn1cblxuLy8gdG8gcnVuIHVzZTogbnB4IHRzLW5vZGUgc3JjL2NsdXN0ZXIvZXhhbXBsZXMudHMgW25vcm1hbHxzdHVja3xraWxsXVxuaWYgKHJlcXVpcmUubWFpbiA9PT0gbW9kdWxlKSB7XG4gIGNvbnN0IG1vZGUgPSBwcm9jZXNzLmFyZ3ZbMl0gfHwgJ25vcm1hbCc7XG4gIGxldCBydW47XG4gIGlmIChtb2RlID09PSAnc3R1Y2snKSB7XG4gICAgcnVuID0gc3R1Y2tFeGFtcGxlO1xuICB9IGVsc2UgaWYgKG1vZGUgPT09ICdraWxsJykge1xuICAgIHJ1biA9IGtpbGxFeGFtcGxlO1xuICB9IGVsc2Uge1xuICAgIHJ1biA9IG5vcm1hbEV4YW1wbGU7XG4gIH1cbiAgcnVuKCkuY2F0Y2goKGVycikgPT4ge1xuICAgIGxvZ2dlci5lcnJvcihlcnIpO1xuICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgfSk7XG59XG4iXX0=
@@ -0,0 +1,3 @@
1
+ export { ClusterManager, ClusterManagerEmitter } from './manager';
2
+ export type { ClusterManagerOptions, ClusterManagerEvents, WorkerState, PingMessage, PongMessage, ShutdownMessage, IPCMessage, } from './types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cluster/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAClE,YAAY,EACV,qBAAqB,EACrB,oBAAoB,EACpB,WAAW,EACX,WAAW,EACX,WAAW,EACX,eAAe,EACf,UAAU,GACX,MAAM,SAAS,CAAC"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ClusterManager = void 0;
4
+ var manager_1 = require("./manager");
5
+ Object.defineProperty(exports, "ClusterManager", { enumerable: true, get: function () { return manager_1.ClusterManager; } });
6
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY2x1c3Rlci9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxxQ0FBa0U7QUFBekQseUdBQUEsY0FBYyxPQUFBIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHsgQ2x1c3Rlck1hbmFnZXIsIENsdXN0ZXJNYW5hZ2VyRW1pdHRlciB9IGZyb20gJy4vbWFuYWdlcic7XG5leHBvcnQgdHlwZSB7XG4gIENsdXN0ZXJNYW5hZ2VyT3B0aW9ucyxcbiAgQ2x1c3Rlck1hbmFnZXJFdmVudHMsXG4gIFdvcmtlclN0YXRlLFxuICBQaW5nTWVzc2FnZSxcbiAgUG9uZ01lc3NhZ2UsXG4gIFNodXRkb3duTWVzc2FnZSxcbiAgSVBDTWVzc2FnZSxcbn0gZnJvbSAnLi90eXBlcyc7XG4iXX0=
@@ -0,0 +1,143 @@
1
+ import { EventEmitter } from 'events';
2
+ import { ClusterManagerOptions, ClusterManagerEvents } from './types';
3
+ /**
4
+ * ClusterManager - A cluster lifecycle management system
5
+ *
6
+ * The manager supports the following features:
7
+ * - Graceful shutdown with configurable timeout
8
+ * - Worker health monitoring with ping/pong mechanism
9
+ * - Automatic worker restart with configurable limits
10
+ * - Signal handling for shutdown triggers
11
+ * - Flexible primary and worker function handlers
12
+ */
13
+ export declare class ClusterManager extends EventEmitter {
14
+ private readonly options;
15
+ private readonly workers;
16
+ private started;
17
+ private isShuttingDown;
18
+ private shutdownPromise;
19
+ private healthCheckInterval;
20
+ private signalHandlers;
21
+ constructor(options?: ClusterManagerOptions);
22
+ /**
23
+ * Starts the cluster manager
24
+ * In primary process: starts workers and health monitoring
25
+ * In worker process: executes worker function
26
+ */
27
+ start(): Promise<void>;
28
+ /**
29
+ * Initiates graceful shutdown of the cluster
30
+ */
31
+ shutdown(signal?: string): Promise<void>;
32
+ /**
33
+ * Sets up signal handlers for graceful shutdown
34
+ */
35
+ private setupSignalHandlers;
36
+ /**
37
+ * Removes signal handlers
38
+ */
39
+ private removeSignalHandlers;
40
+ /**
41
+ * Starts the primary process
42
+ */
43
+ private startPrimary;
44
+ /**
45
+ * Starts a worker process
46
+ */
47
+ private startWorker;
48
+ /**
49
+ * Sets up cluster event handlers for the primary process
50
+ */
51
+ private setupClusterEventHandlers;
52
+ /**
53
+ * Sets up IPC message handlers for worker processes
54
+ */
55
+ private setupWorkerMessageHandlers;
56
+ /**
57
+ * Spawns a new worker and sets up its state
58
+ */
59
+ private spawnWorker;
60
+ /**
61
+ * Handles messages from workers
62
+ */
63
+ private handleWorkerMessage;
64
+ /**
65
+ * Handles ping messages in worker processes
66
+ */
67
+ private handleWorkerPing;
68
+ /**
69
+ * Starts health monitoring for all workers
70
+ */
71
+ private startHealthMonitoring;
72
+ /**
73
+ * Stops health monitoring
74
+ */
75
+ private stopHealthMonitoring;
76
+ /**
77
+ * Performs health check on all workers
78
+ */
79
+ private performHealthCheck;
80
+ /**
81
+ * Sends a ping message to a worker
82
+ */
83
+ private sendPingToWorker;
84
+ /**
85
+ * Handles a stuck worker
86
+ */
87
+ private handleStuckWorker;
88
+ /**
89
+ * Handles worker exit events
90
+ */
91
+ private handleWorkerExit;
92
+ private getWorkerId;
93
+ private getCurrentWorkerId;
94
+ /**
95
+ * Handles unexpected worker exits with restart logic
96
+ */
97
+ private handleUnexpectedWorkerExit;
98
+ /**
99
+ * Shuts down the primary process
100
+ */
101
+ private shutdownPrimary;
102
+ /**
103
+ * Shuts down all workers gracefully
104
+ */
105
+ private shutdownAllWorkers;
106
+ /**
107
+ * Waits for all workers to exit
108
+ */
109
+ private waitForAllWorkersToExit;
110
+ /**
111
+ * Force kills all remaining workers
112
+ */
113
+ private forceKillAllWorkers;
114
+ /**
115
+ * Shuts down a worker process
116
+ */
117
+ private shutdownWorker;
118
+ /**
119
+ * Gets the current number of active workers
120
+ */
121
+ getWorkerCount(): number;
122
+ /**
123
+ * Gets information about all workers
124
+ */
125
+ getWorkerInfo(): Array<{
126
+ id: number;
127
+ pid: number;
128
+ restartCount: number;
129
+ }>;
130
+ /**
131
+ * Checks if the cluster is currently started
132
+ */
133
+ isStarted(): boolean;
134
+ /**
135
+ * Checks if the cluster is currently shutting down
136
+ */
137
+ isShutdown(): boolean;
138
+ }
139
+ export interface ClusterManagerEmitter {
140
+ on<K extends keyof ClusterManagerEvents>(event: K, listener: ClusterManagerEvents[K]): this;
141
+ emit<K extends keyof ClusterManagerEvents>(event: K, ...args: Parameters<ClusterManagerEvents[K]>): boolean;
142
+ }
143
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/cluster/manager.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EAMrB,MAAM,SAAS,CAAC;AAGjB;;;;;;;;;GASG;AACH,qBAAa,cAAe,SAAQ,YAAY;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkC;IAE1D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkC;IAE1D,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,cAAc,CAAS;IAE/B,OAAO,CAAC,eAAe,CAA8B;IAErD,OAAO,CAAC,mBAAmB,CAA+B;IAE1D,OAAO,CAAC,cAAc,CAAyC;gBAEnD,OAAO,GAAE,qBAA0B;IAM/C;;;;OAIG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IASnC;;OAEG;IACI,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqB/C;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAU3B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAO5B;;OAEG;YACW,YAAY;IAqB1B;;OAEG;YACW,WAAW;IAUzB;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAWjC;;OAEG;IACH,OAAO,CAAC,0BAA0B;IAgBlC;;OAEG;IACH,OAAO,CAAC,WAAW;IAuBnB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAmB3B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAWxB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAM7B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAO5B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAkB1B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAkBxB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAiCzB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAsBxB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,kBAAkB;IAM1B;;OAEG;IACH,OAAO,CAAC,0BAA0B;IAsBlC;;OAEG;YACW,eAAe;IA2B7B;;OAEG;YACW,kBAAkB;IAwChC;;OAEG;YACW,uBAAuB;IAOrC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAU3B;;OAEG;YACW,cAAc;IAwB5B;;OAEG;IACI,cAAc,IAAI,MAAM;IAI/B;;OAEG;IACI,aAAa,IAAI,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;IAQhF;;OAEG;IACI,SAAS,IAAI,OAAO;IAI3B;;OAEG;IACI,UAAU,IAAI,OAAO;CAG7B;AAGD,MAAM,WAAW,qBAAqB;IACpC,EAAE,CAAC,CAAC,SAAS,MAAM,oBAAoB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC5F,IAAI,CAAC,CAAC,SAAS,MAAM,oBAAoB,EACvC,KAAK,EAAE,CAAC,EACR,GAAG,IAAI,EAAE,UAAU,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,GAC3C,OAAO,CAAC;CACZ"}
@@ -0,0 +1,457 @@
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
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ClusterManager = void 0;
37
+ const events_1 = require("events");
38
+ const logger = __importStar(require("../logger"));
39
+ const utils_1 = require("./utils");
40
+ /**
41
+ * ClusterManager - A cluster lifecycle management system
42
+ *
43
+ * The manager supports the following features:
44
+ * - Graceful shutdown with configurable timeout
45
+ * - Worker health monitoring with ping/pong mechanism
46
+ * - Automatic worker restart with configurable limits
47
+ * - Signal handling for shutdown triggers
48
+ * - Flexible primary and worker function handlers
49
+ */
50
+ class ClusterManager extends events_1.EventEmitter {
51
+ constructor(options = {}) {
52
+ super();
53
+ this.workers = new Map();
54
+ this.started = false;
55
+ this.isShuttingDown = false;
56
+ this.shutdownPromise = null;
57
+ this.healthCheckInterval = null;
58
+ this.signalHandlers = new Map();
59
+ this.options = (0, utils_1.validateAndDefaultOptions)(options);
60
+ this.setupSignalHandlers();
61
+ }
62
+ /**
63
+ * Starts the cluster manager
64
+ * In primary process: starts workers and health monitoring
65
+ * In worker process: executes worker function
66
+ */
67
+ async start() {
68
+ if (this.options.cluster.isPrimary) {
69
+ await this.startPrimary();
70
+ }
71
+ else {
72
+ await this.startWorker();
73
+ }
74
+ this.started = true;
75
+ }
76
+ /**
77
+ * Initiates graceful shutdown of the cluster
78
+ */
79
+ shutdown(signal) {
80
+ if (!this.started) {
81
+ return Promise.resolve();
82
+ }
83
+ if (this.shutdownPromise) {
84
+ return this.shutdownPromise;
85
+ }
86
+ this.isShuttingDown = true;
87
+ this.emit('shutdown:started', signal);
88
+ if (this.options.cluster.isPrimary) {
89
+ this.shutdownPromise = this.shutdownPrimary(signal);
90
+ }
91
+ else {
92
+ this.shutdownPromise = this.shutdownWorker(signal);
93
+ }
94
+ return this.shutdownPromise;
95
+ }
96
+ /**
97
+ * Sets up signal handlers for graceful shutdown
98
+ */
99
+ setupSignalHandlers() {
100
+ this.options.shutdownSignals.forEach((signal) => {
101
+ const handler = () => {
102
+ this.shutdown(signal);
103
+ };
104
+ this.signalHandlers.set(signal, handler);
105
+ process.on(signal, handler);
106
+ });
107
+ }
108
+ /**
109
+ * Removes signal handlers
110
+ */
111
+ removeSignalHandlers() {
112
+ Array.from(this.signalHandlers.entries()).forEach(([signal, handler]) => {
113
+ process.removeListener(signal, handler);
114
+ });
115
+ this.signalHandlers.clear();
116
+ }
117
+ /**
118
+ * Starts the primary process
119
+ */
120
+ async startPrimary() {
121
+ logger.info(`Primary process (pid: ${process.pid}) starting with ${this.options.numWorkers} workers`);
122
+ // Execute primary initialization function, any error will stop the cluster from starting
123
+ await this.options.primaryFn();
124
+ // Set up cluster event handlers
125
+ this.setupClusterEventHandlers();
126
+ // Spawn initial workers
127
+ for (let i = 0; i < this.options.numWorkers; i += 1) {
128
+ const workerId = i + 1; // Worker IDs start from 1
129
+ this.spawnWorker(workerId);
130
+ }
131
+ // Start health monitoring
132
+ this.startHealthMonitoring();
133
+ }
134
+ /**
135
+ * Starts a worker process
136
+ */
137
+ async startWorker() {
138
+ logger.info(`Worker ${this.getCurrentWorkerId()} (pid: ${process.pid}) starting`);
139
+ // Set up IPC message handlers
140
+ this.setupWorkerMessageHandlers();
141
+ // Execute worker initialization function, any error will be propagated
142
+ await this.options.workerFn();
143
+ }
144
+ /**
145
+ * Sets up cluster event handlers for the primary process
146
+ */
147
+ setupClusterEventHandlers() {
148
+ this.options.cluster.on('exit', (worker, code, signal) => {
149
+ this.handleWorkerExit(worker, code, signal);
150
+ });
151
+ this.options.cluster.on('online', (worker) => {
152
+ logger.info(`Worker ${this.getWorkerId(worker)} (pid: ${worker.process.pid}) is online`);
153
+ this.emit('worker:started', worker);
154
+ });
155
+ }
156
+ /**
157
+ * Sets up IPC message handlers for worker processes
158
+ */
159
+ setupWorkerMessageHandlers() {
160
+ process.on('message', (message) => {
161
+ switch (message.type) {
162
+ case 'ping':
163
+ this.handleWorkerPing(message);
164
+ break;
165
+ case 'shutdown':
166
+ this.shutdown(message.signal);
167
+ break;
168
+ default:
169
+ logger.warn(`ignoring unknown message type in worker ${process.pid}: ${message.type}`);
170
+ break;
171
+ }
172
+ });
173
+ }
174
+ /**
175
+ * Spawns a new worker and sets up its state
176
+ */
177
+ spawnWorker(id) {
178
+ const worker = this.options.cluster.fork({
179
+ WORKER_ID: id,
180
+ });
181
+ const workerState = {
182
+ id,
183
+ worker,
184
+ restartCount: 0,
185
+ lastPing: Date.now(),
186
+ pendingPing: false,
187
+ isShuttingDown: false,
188
+ };
189
+ this.workers.set(worker.id, workerState);
190
+ // Set up worker message handler
191
+ worker.on('message', (message) => {
192
+ this.handleWorkerMessage(worker, message);
193
+ });
194
+ return worker;
195
+ }
196
+ /**
197
+ * Handles messages from workers
198
+ */
199
+ handleWorkerMessage(worker, message) {
200
+ const workerState = this.workers.get(worker.id);
201
+ if (!workerState)
202
+ return;
203
+ switch (message.type) {
204
+ case 'pong':
205
+ workerState.lastPing = Date.now();
206
+ workerState.pendingPing = false;
207
+ break;
208
+ default:
209
+ logger.warn(`Received unknown message type from worker ${this.getWorkerId(worker)} (pid: ${worker.process.pid}): ${message.type}`);
210
+ break;
211
+ }
212
+ }
213
+ /**
214
+ * Handles ping messages in worker processes
215
+ */
216
+ handleWorkerPing(message) {
217
+ const pongMessage = {
218
+ type: 'pong',
219
+ timestamp: message.timestamp,
220
+ };
221
+ if (process.send) {
222
+ process.send(pongMessage);
223
+ }
224
+ }
225
+ /**
226
+ * Starts health monitoring for all workers
227
+ */
228
+ startHealthMonitoring() {
229
+ this.healthCheckInterval = setInterval(() => {
230
+ this.performHealthCheck();
231
+ }, this.options.pingFrequency);
232
+ }
233
+ /**
234
+ * Stops health monitoring
235
+ */
236
+ stopHealthMonitoring() {
237
+ if (this.healthCheckInterval) {
238
+ clearInterval(this.healthCheckInterval);
239
+ this.healthCheckInterval = null;
240
+ }
241
+ }
242
+ /**
243
+ * Performs health check on all workers
244
+ */
245
+ performHealthCheck() {
246
+ if (this.isShuttingDown)
247
+ return;
248
+ Array.from(this.workers.values())
249
+ .filter((workerState) => !workerState.isShuttingDown)
250
+ .forEach((workerState) => {
251
+ const timeSinceLastPing = Date.now() - workerState.lastPing;
252
+ if (workerState.pendingPing && timeSinceLastPing > this.options.pingTimeout) {
253
+ // Worker is stuck, handle it
254
+ this.handleStuckWorker(workerState);
255
+ }
256
+ else if (!workerState.pendingPing) {
257
+ // Send ping to worker
258
+ this.sendPingToWorker(workerState);
259
+ }
260
+ });
261
+ }
262
+ /**
263
+ * Sends a ping message to a worker
264
+ */
265
+ sendPingToWorker(workerState) {
266
+ const pingMessage = {
267
+ type: 'ping',
268
+ timestamp: Date.now(),
269
+ };
270
+ workerState.pendingPing = true;
271
+ try {
272
+ workerState.worker.send(pingMessage);
273
+ }
274
+ catch (error) {
275
+ logger.error(`Failed to send ping to worker ${workerState.id} (pid: ${workerState.worker.process.pid}): ${error instanceof Error ? error.message : String(error)}`);
276
+ }
277
+ }
278
+ /**
279
+ * Handles a stuck worker
280
+ */
281
+ handleStuckWorker(workerState) {
282
+ logger.error(`Worker ${workerState.id} (pid: ${workerState.worker.process.pid}) is stuck, killing it`);
283
+ this.emit('worker:stuck', workerState.worker);
284
+ // Remove worker state
285
+ this.workers.delete(workerState.worker.id);
286
+ // Kill the worker
287
+ workerState.worker.kill('SIGKILL');
288
+ // Determine if we should spawn a replacement
289
+ const shouldSpawn = this.options.stuckWorkerRespawnFunc(workerState.worker);
290
+ if (shouldSpawn && !this.isShuttingDown) {
291
+ logger.info(`Spawning replacement worker for stuck worker ${workerState.id} (pid: ${workerState.worker.process.pid})`);
292
+ const { restartCount } = workerState; // Preserve restart count
293
+ const newWorker = this.spawnWorker(workerState.id);
294
+ const newWorkerState = this.workers.get(newWorker.id);
295
+ if (newWorkerState) {
296
+ newWorkerState.restartCount = restartCount;
297
+ }
298
+ }
299
+ else {
300
+ logger.error(`Triggering cluster shutdown due to stuck worker ${workerState.id} (pid: ${workerState.worker.process.pid})`);
301
+ this.shutdown('STUCK_WORKER');
302
+ }
303
+ }
304
+ /**
305
+ * Handles worker exit events
306
+ */
307
+ handleWorkerExit(worker, code, signal) {
308
+ logger.info(`Worker ${this.getWorkerId(worker)} (pid: ${worker.process.pid}) died with code ${code} and signal ${signal}`);
309
+ this.emit('worker:died', worker, code, signal);
310
+ const workerState = this.workers.get(worker.id);
311
+ if (!workerState)
312
+ return;
313
+ this.workers.delete(worker.id);
314
+ // If we're shutting down or worker was killed intentionally, don't restart
315
+ if (this.isShuttingDown || workerState.isShuttingDown) {
316
+ return;
317
+ }
318
+ // Handle unexpected exit
319
+ this.handleUnexpectedWorkerExit(workerState);
320
+ }
321
+ getWorkerId(worker) {
322
+ return this.workers.get(worker.id)?.id ?? worker.id;
323
+ }
324
+ getCurrentWorkerId() {
325
+ const envWorkerId = process.env.WORKER_ID !== undefined ? Number(process.env.WORKER_ID) : undefined;
326
+ return envWorkerId ?? this.options.cluster.worker?.id ?? -1;
327
+ }
328
+ /**
329
+ * Handles unexpected worker exits with restart logic
330
+ */
331
+ handleUnexpectedWorkerExit(workerState) {
332
+ const restartCount = workerState.restartCount + 1;
333
+ if (restartCount <= this.options.restartMaxTimes) {
334
+ logger.error(`Restarting worker ${workerState.id} (pid: ${workerState.worker.process.pid}) (attempt ${restartCount}/${this.options.restartMaxTimes})`);
335
+ const newWorker = this.spawnWorker(workerState.id);
336
+ const newWorkerState = this.workers.get(newWorker.id);
337
+ if (newWorkerState) {
338
+ newWorkerState.restartCount = restartCount;
339
+ }
340
+ this.emit('worker:restarted', newWorker, workerState.restartCount);
341
+ }
342
+ else {
343
+ logger.error(`Restart limit (${this.options.restartMaxTimes}) exceeded for worker ${workerState.id} (pid: ${workerState.worker.process.pid}), shutting down cluster`);
344
+ this.emit('worker:restart-limit-exceeded', workerState.worker, workerState.restartCount);
345
+ this.shutdown('RESTART_LIMIT_EXCEEDED');
346
+ }
347
+ }
348
+ /**
349
+ * Shuts down the primary process
350
+ */
351
+ async shutdownPrimary(signal) {
352
+ logger.info(`Primary process (pid: ${process.pid}) shutting down (signal: ${signal ?? 'manual'})`);
353
+ this.stopHealthMonitoring();
354
+ this.removeSignalHandlers();
355
+ // Shutdown all workers
356
+ await this.shutdownAllWorkers(signal);
357
+ // Execute primary shutdown function
358
+ await (0, utils_1.safeExecute)(() => (0, utils_1.timeout)(this.options.primaryShutdownFn(signal), this.options.shutdownTimeout, 'primary shutdown timeout'), 'Error in primary shutdown function');
359
+ logger.info(`Primary process (pid: ${process.pid}) shutdown completed`);
360
+ this.emit('shutdown:completed');
361
+ process.exit(0);
362
+ }
363
+ /**
364
+ * Shuts down all workers gracefully
365
+ */
366
+ async shutdownAllWorkers(signal) {
367
+ if (this.workers.size === 0)
368
+ return;
369
+ logger.info(`Shutting down ${this.workers.size} workers...`);
370
+ // Mark all workers as shutting down and send shutdown message
371
+ Array.from(this.workers.values()).forEach((workerState) => {
372
+ workerState.isShuttingDown = true;
373
+ // Only send shutdown message if worker is still connected
374
+ if (!workerState.worker.isDead() && workerState.worker.process.connected) {
375
+ const shutdownMessage = {
376
+ type: 'shutdown',
377
+ signal,
378
+ };
379
+ try {
380
+ workerState.worker.send(shutdownMessage);
381
+ }
382
+ catch (error) {
383
+ // Worker IPC channel is already closed, which is fine
384
+ logger.warn(`Failed to send shutdown message to worker ${workerState.id} (pid: ${workerState.worker.process.pid}): ${error instanceof Error ? error.message : String(error)}`);
385
+ }
386
+ }
387
+ });
388
+ // Wait for workers to exit gracefully or timeout
389
+ try {
390
+ await (0, utils_1.timeout)(this.waitForAllWorkersToExit(), this.options.shutdownTimeout, 'Worker shutdown timeout');
391
+ }
392
+ catch (error) {
393
+ logger.error('Graceful shutdown for workers timed out, forcing shutdown');
394
+ this.forceKillAllWorkers();
395
+ }
396
+ }
397
+ /**
398
+ * Waits for all workers to exit
399
+ */
400
+ async waitForAllWorkersToExit() {
401
+ while (this.workers.size > 0) {
402
+ // eslint-disable-next-line no-await-in-loop
403
+ await (0, utils_1.delay)(100);
404
+ }
405
+ }
406
+ /**
407
+ * Force kills all remaining workers
408
+ */
409
+ forceKillAllWorkers() {
410
+ Array.from(this.workers.values()).forEach((workerState) => {
411
+ logger.error(`Force killing worker ${workerState.id} (pid: ${workerState.worker.process.pid})`);
412
+ workerState.worker.kill('SIGKILL');
413
+ });
414
+ this.workers.clear();
415
+ }
416
+ /**
417
+ * Shuts down a worker process
418
+ */
419
+ async shutdownWorker(signal) {
420
+ logger.info(`Worker ${this.getCurrentWorkerId()} (pid: ${process.pid}) shutting down (signal: ${signal ?? 'manual'})`);
421
+ this.removeSignalHandlers();
422
+ // Execute worker shutdown function
423
+ await (0, utils_1.safeExecute)(() => (0, utils_1.timeout)(this.options.workerShutdownFn(signal), this.options.shutdownTimeout, 'worker shutdown timeout'), `Error in worker ${this.getCurrentWorkerId()} (pid: ${process.pid}) shutdown function`);
424
+ logger.info(`Worker ${this.getCurrentWorkerId()} (pid: ${process.pid}) shutdown completed`);
425
+ process.exit(0);
426
+ }
427
+ /**
428
+ * Gets the current number of active workers
429
+ */
430
+ getWorkerCount() {
431
+ return this.workers.size;
432
+ }
433
+ /**
434
+ * Gets information about all workers
435
+ */
436
+ getWorkerInfo() {
437
+ return Array.from(this.workers.values()).map((state) => ({
438
+ id: state.id,
439
+ pid: state.worker.process.pid ?? -1,
440
+ restartCount: state.restartCount,
441
+ }));
442
+ }
443
+ /**
444
+ * Checks if the cluster is currently started
445
+ */
446
+ isStarted() {
447
+ return this.started;
448
+ }
449
+ /**
450
+ * Checks if the cluster is currently shutting down
451
+ */
452
+ isShutdown() {
453
+ return this.isShuttingDown;
454
+ }
455
+ }
456
+ exports.ClusterManager = ClusterManager;
457
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFuYWdlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jbHVzdGVyL21hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBR0EsbUNBQXNDO0FBQ3RDLGtEQUFvQztBQVVwQyxtQ0FBaUY7QUFFakY7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBYSxjQUFlLFNBQVEscUJBQVk7SUFlOUMsWUFBWSxVQUFpQyxFQUFFO1FBQzdDLEtBQUssRUFBRSxDQUFDO1FBYk8sWUFBTyxHQUFHLElBQUksR0FBRyxFQUF1QixDQUFDO1FBRWxELFlBQU8sR0FBRyxLQUFLLENBQUM7UUFFaEIsbUJBQWMsR0FBRyxLQUFLLENBQUM7UUFFdkIsb0JBQWUsR0FBeUIsSUFBSSxDQUFDO1FBRTdDLHdCQUFtQixHQUEwQixJQUFJLENBQUM7UUFFbEQsbUJBQWMsR0FBRyxJQUFJLEdBQUcsRUFBOEIsQ0FBQztRQUk3RCxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUEsaUNBQXlCLEVBQUMsT0FBTyxDQUFDLENBQUM7UUFDbEQsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7SUFDN0IsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxLQUFLLENBQUMsS0FBSztRQUNoQixJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ25DLE1BQU0sSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQzVCLENBQUM7YUFBTSxDQUFDO1lBQ04sTUFBTSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDM0IsQ0FBQztRQUNELElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDO0lBQ3RCLENBQUM7SUFFRDs7T0FFRztJQUNJLFFBQVEsQ0FBQyxNQUFlO1FBQzdCLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDbEIsT0FBTyxPQUFPLENBQUMsT0FBTyxF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QUMsQ0FBQztRQUM1RixPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xCLENBQUM7SUFFRDs7T0FFRztJQUNJLGNBQWM7UUFDbkIsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQztJQUMzQixDQUFDO0lBRUQ7O09BRUc7SUFDSSxhQUFhO1FBQ2xCLE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQ3ZELEVBQUUsRUFBRSxLQUFLLENBQUMsRUFBRTtZQUNaLEdBQUcsRUFBRSxLQUFLLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO1lBQ25DLFlBQVksRUFBRSxLQUFLLENBQUMsWUFBWTtTQUNqQyxDQUFDLENBQUMsQ0FBQztJQUNOLENBQUM7SUFFRDs7T0FFRztJQUNJLFNBQVM7UUFDZCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDdEIsQ0FBQztJQUVEOztPQUVHO0lBQ0ksVUFBVTtRQUNmLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQztJQUM3QixDQUFDO0NBQ0Y7QUE3Z0JELHdDQTZnQkMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBjbGFzcy1tZXRob2RzLXVzZS10aGlzICovXG4vKiBlc2xpbnQtZGlzYWJsZSBuby1wYXJhbS1yZWFzc2lnbiAqL1xuaW1wb3J0IHsgV29ya2VyIH0gZnJvbSAnY2x1c3Rlcic7XG5pbXBvcnQgeyBFdmVudEVtaXR0ZXIgfSBmcm9tICdldmVudHMnO1xuaW1wb3J0ICogYXMgbG9nZ2VyIGZyb20gJy4uL2xvZ2dlcic7XG5pbXBvcnQge1xuICBDbHVzdGVyTWFuYWdlck9wdGlvbnMsXG4gIENsdXN0ZXJNYW5hZ2VyRXZlbnRzLFxuICBXb3JrZXJTdGF0ZSxcbiAgSVBDTWVzc2FnZSxcbiAgUGluZ01lc3NhZ2UsXG4gIFBvbmdNZXNzYWdlLFxuICBTaHV0ZG93bk1lc3NhZ2UsXG59IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHsgZGVsYXksIHRpbWVvdXQsIHNhZmVFeGVjdXRlLCB2YWxpZGF0ZUFuZERlZmF1bHRPcHRpb25zIH0gZnJvbSAnLi91dGlscyc7XG5cbi8qKlxuICogQ2x1c3Rlck1hbmFnZXIgLSBBIGNsdXN0ZXIgbGlmZWN5Y2xlIG1hbmFnZW1lbnQgc3lzdGVtXG4gKlxuICogVGhlIG1hbmFnZXIgc3VwcG9ydHMgdGhlIGZvbGxvd2luZyBmZWF0dXJlczpcbiAqIC0gR3JhY2VmdWwgc2h1dGRvd24gd2l0aCBjb25maWd1cmFibGUgdGltZW91dFxuICogLSBXb3JrZXIgaGVhbHRoIG1vbml0b3Jpbmcgd2l0aCBwaW5nL3BvbmcgbWVjaGFuaXNtXG4gKiAtIEF1dG9tYXRpYyB3b3JrZXIgcmVzdGFydCB3aXRoIGNvbmZpZ3VyYWJsZSBsaW1pdHNcbiAqIC0gU2lnbmFsIGhhbmRsaW5nIGZvciBzaHV0ZG93biB0cmlnZ2Vyc1xuICogLSBGbGV4aWJsZSBwcmltYXJ5IGFuZCB3b3JrZXIgZnVuY3Rpb24gaGFuZGxlcnNcbiAqL1xuZXhwb3J0IGNsYXNzIENsdXN0ZXJNYW5hZ2VyIGV4dGVuZHMgRXZlbnRFbWl0dGVyIHtcbiAgcHJpdmF0ZSByZWFkb25seSBvcHRpb25zOiBSZXF1aXJlZDxDbHVzdGVyTWFuYWdlck9wdGlvbnM+O1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgd29ya2VycyA9IG5ldyBNYXA8bnVtYmVyLCBXb3JrZXJTdGF0ZT4oKTtcblxuICBwcml2YXRlIHN0YXJ0ZWQgPSBmYWxzZTtcblxuICBwcml2YXRlIGlzU2h1dHRpbmdEb3duID0gZmFsc2U7XG5cbiAgcHJpdmF0ZSBzaHV0ZG93blByb21pc2U6IFByb21pc2U8dm9pZD4gfCBudWxsID0gbnVsbDtcblxuICBwcml2YXRlIGhlYWx0aENoZWNrSW50ZXJ2YWw6IE5vZGVKUy5UaW1lb3V0IHwgbnVsbCA9IG51bGw7XG5cbiAgcHJpdmF0ZSBzaWduYWxIYW5kbGVycyA9IG5ldyBNYXA8Tm9kZUpTLlNpZ25hbHMsICgpID0+IHZvaWQ+KCk7XG5cbiAgY29uc3RydWN0b3Iob3B0aW9uczogQ2x1c3Rlck1hbmFnZXJPcHRpb25zID0ge30pIHtcbiAgICBzdXBlcigpO1xuICAgIHRoaXMub3B0aW9ucyA9IHZhbGlkYXRlQW5kRGVmYXVsdE9wdGlvbnMob3B0aW9ucyk7XG4gICAgdGhpcy5zZXR1cFNpZ25hbEhhbmRsZXJzKCk7XG4gIH1cblxuICAvKipcbiAgICogU3RhcnRzIHRoZSBjbHVzdGVyIG1hbmFnZXJcbiAgICogSW4gcHJpbWFyeSBwcm9jZXNzOiBzdGFydHMgd29ya2VycyBhbmQgaGVhbHRoIG1vbml0b3JpbmdcbiAgICogSW4gd29ya2VyIHByb2Nlc3M6IGV4ZWN1dGVzIHdvcmtlciBmdW5jdGlvblxuICAgKi9cbiAgcHVibGljIGFzeW5jIHN0YXJ0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLm9wdGlvbnMuY2x1c3Rlci5pc1ByaW1hcnkpIHtcbiAgICAgIGF3YWl0IHRoaXMuc3RhcnRQcmltYXJ5KCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGF3YWl0IHRoaXMuc3RhcnRXb3JrZXIoKTtcbiAgICB9XG4gICAgdGhpcy5zdGFydGVkID0gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0aWF0ZXMgZ3JhY2VmdWwgc2h1dGRvd24gb2YgdGhlIGNsdXN0ZXJcbiAgICovXG4gIHB1YmxpYyBzaHV0ZG93bihzaWduYWw/OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIXRoaXMuc3RhcnRlZCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnNodXRkb3duUHJvbWlzZSkge1xuICAgICAgcmV0dXJuIHRoaXMuc2h1dGRvd25Qcm9taXNlO1xuICAgIH1cblxuICAgIHRoaXMuaXNTaHV0dGluZ0Rvd24gPSB0cnVlO1xuICAgIHRoaXMuZW1pdCgnc2h1dGRvd246c3RhcnRlZCcsIHNpZ25hbCk7XG5cbiAgICBpZiAodGhpcy5vcHRpb25zLmNsdXN0ZXIuaXNQcmltYXJ5KSB7XG4gICAgICB0aGlzLnNodXRkb3duUHJvbWlzZSA9IHRoaXMuc2h1dGRvd25QcmltYXJ5KHNpZ25hbCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc2h1dGRvd25Qcm9taXNlID0gdGhpcy5zaHV0ZG93bldvcmtlcihzaWduYWwpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnNodXRkb3duUHJvbWlzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHVwIHNpZ25hbCBoYW5kbGVycyBmb3IgZ3JhY2VmdWwgc2h1dGRvd25cbiAgICovXG4gIHByaXZhdGUgc2V0dXBTaWduYWxIYW5kbGVycygpOiB2b2lkIHtcbiAgICB0aGlzLm9wdGlvbnMuc2h1dGRvd25TaWduYWxzLmZvckVhY2goKHNpZ25hbCkgPT4ge1xuICAgICAgY29uc3QgaGFuZGxlciA9ICgpID0+IHtcbiAgICAgICAgdGhpcy5zaHV0ZG93bihzaWduYWwpO1xuICAgICAgfTtcbiAgICAgIHRoaXMuc2lnbmFsSGFuZGxlcnMuc2V0KHNpZ25hbCwgaGFuZGxlcik7XG4gICAgICBwcm9jZXNzLm9uKHNpZ25hbCwgaGFuZGxlcik7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlcyBzaWduYWwgaGFuZGxlcnNcbiAgICovXG4gIHByaXZhdGUgcmVtb3ZlU2lnbmFsSGFuZGxlcnMoKTogdm9pZCB7XG4gICAgQXJyYXkuZnJvbSh0aGlzLnNpZ25hbEhhbmRsZXJzLmVudHJpZXMoKSkuZm9yRWFjaCgoW3NpZ25hbCwgaGFuZGxlcl0pID0+IHtcbiAgICAgIHByb2Nlc3MucmVtb3ZlTGlzdGVuZXIoc2lnbmFsLCBoYW5kbGVyKTtcbiAgICB9KTtcbiAgICB0aGlzLnNpZ25hbEhhbmRsZXJzLmNsZWFyKCk7XG4gIH1cblxuICAvKipcbiAgICogU3RhcnRzIHRoZSBwcmltYXJ5IHByb2Nlc3NcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgc3RhcnRQcmltYXJ5KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGxvZ2dlci5pbmZvKFxuICAgICAgYFByaW1hcnkgcHJvY2VzcyAocGlkOiAke3Byb2Nlc3MucGlkfSkgc3RhcnRpbmcgd2l0aCAke3RoaXMub3B0aW9ucy5udW1Xb3JrZXJzfSB3b3JrZXJzYCxcbiAgICApO1xuXG4gICAgLy8gRXhlY3V0ZSBwcmltYXJ5IGluaXRpYWxpemF0aW9uIGZ1bmN0aW9uLCBhbnkgZXJyb3Igd2lsbCBzdG9wIHRoZSBjbHVzdGVyIGZyb20gc3RhcnRpbmdcbiAgICBhd2FpdCB0aGlzLm9wdGlvbnMucHJpbWFyeUZuKCk7XG5cbiAgICAvLyBTZXQgdXAgY2x1c3RlciBldmVudCBoYW5kbGVyc1xuICAgIHRoaXMuc2V0dXBDbHVzdGVyRXZlbnRIYW5kbGVycygpO1xuXG4gICAgLy8gU3Bhd24gaW5pdGlhbCB3b3JrZXJzXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm9wdGlvbnMubnVtV29ya2VyczsgaSArPSAxKSB7XG4gICAgICBjb25zdCB3b3JrZXJJZCA9IGkgKyAxOyAvLyBXb3JrZXIgSURzIHN0YXJ0IGZyb20gMVxuICAgICAgdGhpcy5zcGF3bldvcmtlcih3b3JrZXJJZCk7XG4gICAgfVxuXG4gICAgLy8gU3RhcnQgaGVhbHRoIG1vbml0b3JpbmdcbiAgICB0aGlzLnN0YXJ0SGVhbHRoTW9uaXRvcmluZygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFN0YXJ0cyBhIHdvcmtlciBwcm9jZXNzXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHN0YXJ0V29ya2VyKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGxvZ2dlci5pbmZvKGBXb3JrZXIgJHt0aGlzLmdldEN1cnJlbnRXb3JrZXJJZCgpfSAocGlkOiAke3Byb2Nlc3MucGlkfSkgc3RhcnRpbmdgKTtcblxuICAgIC8vIFNldCB1cCBJUEMgbWVzc2FnZSBoYW5kbGVyc1xuICAgIHRoaXMuc2V0dXBXb3JrZXJNZXNzYWdlSGFuZGxlcnMoKTtcblxuICAgIC8vIEV4ZWN1dGUgd29ya2VyIGluaXRpYWxpemF0aW9uIGZ1bmN0aW9uLCBhbnkgZXJyb3Igd2lsbCBiZSBwcm9wYWdhdGVkXG4gICAgYXdhaXQgdGhpcy5vcHRpb25zLndvcmtlckZuKCk7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB1cCBjbHVzdGVyIGV2ZW50IGhhbmRsZXJzIGZvciB0aGUgcHJpbWFyeSBwcm9jZXNzXG4gICAqL1xuICBwcml2YXRlIHNldHVwQ2x1c3RlckV2ZW50SGFuZGxlcnMoKTogdm9pZCB7XG4gICAgdGhpcy5vcHRpb25zLmNsdXN0ZXIub24oJ2V4aXQnLCAod29ya2VyOiBXb3JrZXIsIGNvZGU6IG51bWJlciwgc2lnbmFsOiBzdHJpbmcpID0+IHtcbiAgICAgIHRoaXMuaGFuZGxlV29ya2VyRXhpdCh3b3JrZXIsIGNvZGUsIHNpZ25hbCk7XG4gICAgfSk7XG5cbiAgICB0aGlzLm9wdGlvbnMuY2x1c3Rlci5vbignb25saW5lJywgKHdvcmtlcjogV29ya2VyKSA9PiB7XG4gICAgICBsb2dnZXIuaW5mbyhgV29ya2VyICR7dGhpcy5nZXRXb3JrZXJJZCh3b3JrZXIpfSAocGlkOiAke3dvcmtlci5wcm9jZXNzLnBpZH0pIGlzIG9ubGluZWApO1xuICAgICAgdGhpcy5lbWl0KCd3b3JrZXI6c3RhcnRlZCcsIHdvcmtlcik7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB1cCBJUEMgbWVzc2FnZSBoYW5kbGVycyBmb3Igd29ya2VyIHByb2Nlc3Nlc1xuICAgKi9cbiAgcHJpdmF0ZSBzZXR1cFdvcmtlck1lc3NhZ2VIYW5kbGVycygpOiB2b2lkIHtcbiAgICBwcm9jZXNzLm9uKCdtZXNzYWdlJywgKG1lc3NhZ2U6IElQQ01lc3NhZ2UpID0+IHtcbiAgICAgIHN3aXRjaCAobWVzc2FnZS50eXBlKSB7XG4gICAgICAgIGNhc2UgJ3BpbmcnOlxuICAgICAgICAgIHRoaXMuaGFuZGxlV29ya2VyUGluZyhtZXNzYWdlKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnc2h1dGRvd24nOlxuICAgICAgICAgIHRoaXMuc2h1dGRvd24obWVzc2FnZS5zaWduYWwpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIGxvZ2dlci53YXJuKGBpZ25vcmluZyB1bmtub3duIG1lc3NhZ2UgdHlwZSBpbiB3b3JrZXIgJHtwcm9jZXNzLnBpZH06ICR7bWVzc2FnZS50eXBlfWApO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFNwYXducyBhIG5ldyB3b3JrZXIgYW5kIHNldHMgdXAgaXRzIHN0YXRlXG4gICAqL1xuICBwcml2YXRlIHNwYXduV29ya2VyKGlkOiBudW1iZXIpOiBXb3JrZXIge1xuICAgIGNvbnN0IHdvcmtlciA9IHRoaXMub3B0aW9ucy5jbHVzdGVyLmZvcmsoe1xuICAgICAgV09SS0VSX0lEOiBpZCxcbiAgICB9KTtcbiAgICBjb25zdCB3b3JrZXJTdGF0ZTogV29ya2VyU3RhdGUgPSB7XG4gICAgICBpZCxcbiAgICAgIHdvcmtlcixcbiAgICAgIHJlc3RhcnRDb3VudDogMCxcbiAgICAgIGxhc3RQaW5nOiBEYXRlLm5vdygpLFxuICAgICAgcGVuZGluZ1Bpbmc6IGZhbHNlLFxuICAgICAgaXNTaHV0dGluZ0Rvd246IGZhbHNlLFxuICAgIH07XG5cbiAgICB0aGlzLndvcmtlcnMuc2V0KHdvcmtlci5pZCwgd29ya2VyU3RhdGUpO1xuXG4gICAgLy8gU2V0IHVwIHdvcmtlciBtZXNzYWdlIGhhbmRsZXJcbiAgICB3b3JrZXIub24oJ21lc3NhZ2UnLCAobWVzc2FnZTogSVBDTWVzc2FnZSkgPT4ge1xuICAgICAgdGhpcy5oYW5kbGVXb3JrZXJNZXNzYWdlKHdvcmtlciwgbWVzc2FnZSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gd29ya2VyO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZXMgbWVzc2FnZXMgZnJvbSB3b3JrZXJzXG4gICAqL1xuICBwcml2YXRlIGhhbmRsZVdvcmtlck1lc3NhZ2Uod29ya2VyOiBXb3JrZXIsIG1lc3NhZ2U6IElQQ01lc3NhZ2UpOiB2b2lkIHtcbiAgICBjb25zdCB3b3JrZXJTdGF0ZSA9IHRoaXMud29ya2Vycy5nZXQod29ya2VyLmlkKTtcbiAgICBpZiAoIXdvcmtlclN0YXRlKSByZXR1cm47XG5cbiAgICBzd2l0Y2ggKG1lc3NhZ2UudHlwZSkge1xuICAgICAgY2FzZSAncG9uZyc6XG4gICAgICAgIHdvcmtlclN0YXRlLmxhc3RQaW5nID0gRGF0ZS5ub3coKTtcbiAgICAgICAgd29ya2VyU3RhdGUucGVuZGluZ1BpbmcgPSBmYWxzZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBsb2dnZXIud2FybihcbiAgICAgICAgICBgUmVjZWl2ZWQgdW5rbm93biBtZXNzYWdlIHR5cGUgZnJvbSB3b3JrZXIgJHt0aGlzLmdldFdvcmtlcklkKHdvcmtlcil9IChwaWQ6ICR7XG4gICAgICAgICAgICB3b3JrZXIucHJvY2Vzcy5waWRcbiAgICAgICAgICB9KTogJHttZXNzYWdlLnR5cGV9YCxcbiAgICAgICAgKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZXMgcGluZyBtZXNzYWdlcyBpbiB3b3JrZXIgcHJvY2Vzc2VzXG4gICAqL1xuICBwcml2YXRlIGhhbmRsZVdvcmtlclBpbmcobWVzc2FnZTogUGluZ01lc3NhZ2UpOiB2b2lkIHtcbiAgICBjb25zdCBwb25nTWVzc2FnZTogUG9uZ01lc3NhZ2UgPSB7XG4gICAgICB0eXBlOiAncG9uZycsXG4gICAgICB0aW1lc3RhbXA6IG1lc3NhZ2UudGltZXN0YW1wLFxuICAgIH07XG5cbiAgICBpZiAocHJvY2Vzcy5zZW5kKSB7XG4gICAgICBwcm9jZXNzLnNlbmQocG9uZ01lc3NhZ2UpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTdGFydHMgaGVhbHRoIG1vbml0b3JpbmcgZm9yIGFsbCB3b3JrZXJzXG4gICAqL1xuICBwcml2YXRlIHN0YXJ0SGVhbHRoTW9uaXRvcmluZygpOiB2b2lkIHtcbiAgICB0aGlzLmhlYWx0aENoZWNrSW50ZXJ2YWwgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICB0aGlzLnBlcmZvcm1IZWFsdGhDaGVjaygpO1xuICAgIH0sIHRoaXMub3B0aW9ucy5waW5nRnJlcXVlbmN5KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdG9wcyBoZWFsdGggbW9uaXRvcmluZ1xuICAgKi9cbiAgcHJpdmF0ZSBzdG9wSGVhbHRoTW9uaXRvcmluZygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5oZWFsdGhDaGVja0ludGVydmFsKSB7XG4gICAgICBjbGVhckludGVydmFsKHRoaXMuaGVhbHRoQ2hlY2tJbnRlcnZhbCk7XG4gICAgICB0aGlzLmhlYWx0aENoZWNrSW50ZXJ2YWwgPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtcyBoZWFsdGggY2hlY2sgb24gYWxsIHdvcmtlcnNcbiAgICovXG4gIHByaXZhdGUgcGVyZm9ybUhlYWx0aENoZWNrKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmlzU2h1dHRpbmdEb3duKSByZXR1cm47XG5cbiAgICBBcnJheS5mcm9tKHRoaXMud29ya2Vycy52YWx1ZXMoKSlcbiAgICAgIC5maWx0ZXIoKHdvcmtlclN0YXRlKSA9PiAhd29ya2VyU3RhdGUuaXNTaHV0dGluZ0Rvd24pXG4gICAgICAuZm9yRWFjaCgod29ya2VyU3RhdGUpID0+IHtcbiAgICAgICAgY29uc3QgdGltZVNpbmNlTGFzdFBpbmcgPSBEYXRlLm5vdygpIC0gd29ya2VyU3RhdGUubGFzdFBpbmc7XG5cbiAgICAgICAgaWYgKHdvcmtlclN0YXRlLnBlbmRpbmdQaW5nICYmIHRpbWVTaW5jZUxhc3RQaW5nID4gdGhpcy5vcHRpb25zLnBpbmdUaW1lb3V0KSB7XG4gICAgICAgICAgLy8gV29ya2VyIGlzIHN0dWNrLCBoYW5kbGUgaXRcbiAgICAgICAgICB0aGlzLmhhbmRsZVN0dWNrV29ya2VyKHdvcmtlclN0YXRlKTtcbiAgICAgICAgfSBlbHNlIGlmICghd29ya2VyU3RhdGUucGVuZGluZ1BpbmcpIHtcbiAgICAgICAgICAvLyBTZW5kIHBpbmcgdG8gd29ya2VyXG4gICAgICAgICAgdGhpcy5zZW5kUGluZ1RvV29ya2VyKHdvcmtlclN0YXRlKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogU2VuZHMgYSBwaW5nIG1lc3NhZ2UgdG8gYSB3b3JrZXJcbiAgICovXG4gIHByaXZhdGUgc2VuZFBpbmdUb1dvcmtlcih3b3JrZXJTdGF0ZTogV29ya2VyU3RhdGUpOiB2b2lkIHtcbiAgICBjb25zdCBwaW5nTWVzc2FnZTogUGluZ01lc3NhZ2UgPSB7XG4gICAgICB0eXBlOiAncGluZycsXG4gICAgICB0aW1lc3RhbXA6IERhdGUubm93KCksXG4gICAgfTtcblxuICAgIHdvcmtlclN0YXRlLnBlbmRpbmdQaW5nID0gdHJ1ZTtcbiAgICB0cnkge1xuICAgICAgd29ya2VyU3RhdGUud29ya2VyLnNlbmQocGluZ01lc3NhZ2UpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoXG4gICAgICAgIGBGYWlsZWQgdG8gc2VuZCBwaW5nIHRvIHdvcmtlciAke3dvcmtlclN0YXRlLmlkfSAocGlkOiAke1xuICAgICAgICAgIHdvcmtlclN0YXRlLndvcmtlci5wcm9jZXNzLnBpZFxuICAgICAgICB9KTogJHtlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcil9YCxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZXMgYSBzdHVjayB3b3JrZXJcbiAgICovXG4gIHByaXZhdGUgaGFuZGxlU3R1Y2tXb3JrZXIod29ya2VyU3RhdGU6IFdvcmtlclN0YXRlKTogdm9pZCB7XG4gICAgbG9nZ2VyLmVycm9yKFxuICAgICAgYFdvcmtlciAke3dvcmtlclN0YXRlLmlkfSAocGlkOiAke3dvcmtlclN0YXRlLndvcmtlci5wcm9jZXNzLnBpZH0pIGlzIHN0dWNrLCBraWxsaW5nIGl0YCxcbiAgICApO1xuICAgIHRoaXMuZW1pdCgnd29ya2VyOnN0dWNrJywgd29ya2VyU3RhdGUud29ya2VyKTtcblxuICAgIC8vIFJlbW92ZSB3b3JrZXIgc3RhdGVcbiAgICB0aGlzLndvcmtlcnMuZGVsZXRlKHdvcmtlclN0YXRlLndvcmtlci5pZCk7XG5cbiAgICAvLyBLaWxsIHRoZSB3b3JrZXJcbiAgICB3b3JrZXJTdGF0ZS53b3JrZXIua2lsbCgnU0lHS0lMTCcpO1xuXG4gICAgLy8gRGV0ZXJtaW5lIGlmIHdlIHNob3VsZCBzcGF3biBhIHJlcGxhY2VtZW50XG4gICAgY29uc3Qgc2hvdWxkU3Bhd24gPSB0aGlzLm9wdGlvbnMuc3R1Y2tXb3JrZXJSZXNwYXduRnVuYyh3b3JrZXJTdGF0ZS53b3JrZXIpO1xuXG4gICAgaWYgKHNob3VsZFNwYXduICYmICF0aGlzLmlzU2h1dHRpbmdEb3duKSB7XG4gICAgICBsb2dnZXIuaW5mbyhcbiAgICAgICAgYFNwYXduaW5nIHJlcGxhY2VtZW50IHdvcmtlciBmb3Igc3R1Y2sgd29ya2VyICR7d29ya2VyU3RhdGUuaWR9IChwaWQ6ICR7d29ya2VyU3RhdGUud29ya2VyLnByb2Nlc3MucGlkfSlgLFxuICAgICAgKTtcbiAgICAgIGNvbnN0IHsgcmVzdGFydENvdW50IH0gPSB3b3JrZXJTdGF0ZTsgLy8gUHJlc2VydmUgcmVzdGFydCBjb3VudFxuICAgICAgY29uc3QgbmV3V29ya2VyID0gdGhpcy5zcGF3bldvcmtlcih3b3JrZXJTdGF0ZS5pZCk7XG4gICAgICBjb25zdCBuZXdXb3JrZXJTdGF0ZSA9IHRoaXMud29ya2Vycy5nZXQobmV3V29ya2VyLmlkKTtcbiAgICAgIGlmIChuZXdXb3JrZXJTdGF0ZSkge1xuICAgICAgICBuZXdXb3JrZXJTdGF0ZS5yZXN0YXJ0Q291bnQgPSByZXN0YXJ0Q291bnQ7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvZ2dlci5lcnJvcihcbiAgICAgICAgYFRyaWdnZXJpbmcgY2x1c3RlciBzaHV0ZG93biBkdWUgdG8gc3R1Y2sgd29ya2VyICR7d29ya2VyU3RhdGUuaWR9IChwaWQ6ICR7d29ya2VyU3RhdGUud29ya2VyLnByb2Nlc3MucGlkfSlgLFxuICAgICAgKTtcbiAgICAgIHRoaXMuc2h1dGRvd24oJ1NUVUNLX1dPUktFUicpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGVzIHdvcmtlciBleGl0IGV2ZW50c1xuICAgKi9cbiAgcHJpdmF0ZSBoYW5kbGVXb3JrZXJFeGl0KHdvcmtlcjogV29ya2VyLCBjb2RlOiBudW1iZXIgfCBudWxsLCBzaWduYWw6IHN0cmluZyB8IG51bGwpOiB2b2lkIHtcbiAgICBsb2dnZXIuaW5mbyhcbiAgICAgIGBXb3JrZXIgJHt0aGlzLmdldFdvcmtlcklkKHdvcmtlcil9IChwaWQ6ICR7XG4gICAgICAgIHdvcmtlci5wcm9jZXNzLnBpZFxuICAgICAgfSkgZGllZCB3aXRoIGNvZGUgJHtjb2RlfSBhbmQgc2lnbmFsICR7c2lnbmFsfWAsXG4gICAgKTtcbiAgICB0aGlzLmVtaXQoJ3dvcmtlcjpkaWVkJywgd29ya2VyLCBjb2RlLCBzaWduYWwpO1xuXG4gICAgY29uc3Qgd29ya2VyU3RhdGUgPSB0aGlzLndvcmtlcnMuZ2V0KHdvcmtlci5pZCk7XG4gICAgaWYgKCF3b3JrZXJTdGF0ZSkgcmV0dXJuO1xuXG4gICAgdGhpcy53b3JrZXJzLmRlbGV0ZSh3b3JrZXIuaWQpO1xuXG4gICAgLy8gSWYgd2UncmUgc2h1dHRpbmcgZG93biBvciB3b3JrZXIgd2FzIGtpbGxlZCBpbnRlbnRpb25hbGx5LCBkb24ndCByZXN0YXJ0XG4gICAgaWYgKHRoaXMuaXNTaHV0dGluZ0Rvd24gfHwgd29ya2VyU3RhdGUuaXNTaHV0dGluZ0Rvd24pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBIYW5kbGUgdW5leHBlY3RlZCBleGl0XG4gICAgdGhpcy5oYW5kbGVVbmV4cGVjdGVkV29ya2VyRXhpdCh3b3JrZXJTdGF0ZSk7XG4gIH1cblxuICBwcml2YXRlIGdldFdvcmtlcklkKHdvcmtlcjogV29ya2VyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy53b3JrZXJzLmdldCh3b3JrZXIuaWQpPy5pZCA/PyB3b3JrZXIuaWQ7XG4gIH1cblxuICBwcml2YXRlIGdldEN1cnJlbnRXb3JrZXJJZCgpOiBudW1iZXIge1xuICAgIGNvbnN0IGVudldvcmtlcklkID1cbiAgICAgIHByb2Nlc3MuZW52LldPUktFUl9JRCAhPT0gdW5kZWZpbmVkID8gTnVtYmVyKHByb2Nlc3MuZW52LldPUktFUl9JRCkgOiB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIGVudldvcmtlcklkID8/IHRoaXMub3B0aW9ucy5jbHVzdGVyLndvcmtlcj8uaWQgPz8gLTE7XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlcyB1bmV4cGVjdGVkIHdvcmtlciBleGl0cyB3aXRoIHJlc3RhcnQgbG9naWNcbiAgICovXG4gIHByaXZhdGUgaGFuZGxlVW5leHBlY3RlZFdvcmtlckV4aXQod29ya2VyU3RhdGU6IFdvcmtlclN0YXRlKTogdm9pZCB7XG4gICAgY29uc3QgcmVzdGFydENvdW50ID0gd29ya2VyU3RhdGUucmVzdGFydENvdW50ICsgMTtcblxuICAgIGlmIChyZXN0YXJ0Q291bnQgPD0gdGhpcy5vcHRpb25zLnJlc3RhcnRNYXhUaW1lcykge1xuICAgICAgbG9nZ2VyLmVycm9yKFxuICAgICAgICBgUmVzdGFydGluZyB3b3JrZXIgJHt3b3JrZXJTdGF0ZS5pZH0gKHBpZDogJHt3b3JrZXJTdGF0ZS53b3JrZXIucHJvY2Vzcy5waWR9KSAoYXR0ZW1wdCAke3Jlc3RhcnRDb3VudH0vJHt0aGlzLm9wdGlvbnMucmVzdGFydE1heFRpbWVzfSlgLFxuICAgICAgKTtcbiAgICAgIGNvbnN0IG5ld1dvcmtlciA9IHRoaXMuc3Bhd25Xb3JrZXIod29ya2VyU3RhdGUuaWQpO1xuICAgICAgY29uc3QgbmV3V29ya2VyU3RhdGUgPSB0aGlzLndvcmtlcnMuZ2V0KG5ld1dvcmtlci5pZCk7XG4gICAgICBpZiAobmV3V29ya2VyU3RhdGUpIHtcbiAgICAgICAgbmV3V29ya2VyU3RhdGUucmVzdGFydENvdW50ID0gcmVzdGFydENvdW50O1xuICAgICAgfVxuICAgICAgdGhpcy5lbWl0KCd3b3JrZXI6cmVzdGFydGVkJywgbmV3V29ya2VyLCB3b3JrZXJTdGF0ZS5yZXN0YXJ0Q291bnQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBsb2dnZXIuZXJyb3IoXG4gICAgICAgIGBSZXN0YXJ0IGxpbWl0ICgke3RoaXMub3B0aW9ucy5yZXN0YXJ0TWF4VGltZXN9KSBleGNlZWRlZCBmb3Igd29ya2VyICR7d29ya2VyU3RhdGUuaWR9IChwaWQ6ICR7d29ya2VyU3RhdGUud29ya2VyLnByb2Nlc3MucGlkfSksIHNodXR0aW5nIGRvd24gY2x1c3RlcmAsXG4gICAgICApO1xuICAgICAgdGhpcy5lbWl0KCd3b3JrZXI6cmVzdGFydC1saW1pdC1leGNlZWRlZCcsIHdvcmtlclN0YXRlLndvcmtlciwgd29ya2VyU3RhdGUucmVzdGFydENvdW50KTtcbiAgICAgIHRoaXMuc2h1dGRvd24oJ1JFU1RBUlRfTElNSVRfRVhDRUVERUQnKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2h1dHMgZG93biB0aGUgcHJpbWFyeSBwcm9jZXNzXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHNodXRkb3duUHJpbWFyeShzaWduYWw/OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsb2dnZXIuaW5mbyhcbiAgICAgIGBQcmltYXJ5IHByb2Nlc3MgKHBpZDogJHtwcm9jZXNzLnBpZH0pIHNodXR0aW5nIGRvd24gKHNpZ25hbDogJHtzaWduYWwgPz8gJ21hbnVhbCd9KWAsXG4gICAgKTtcblxuICAgIHRoaXMuc3RvcEhlYWx0aE1vbml0b3JpbmcoKTtcbiAgICB0aGlzLnJlbW92ZVNpZ25hbEhhbmRsZXJzKCk7XG5cbiAgICAvLyBTaHV0ZG93biBhbGwgd29ya2Vyc1xuICAgIGF3YWl0IHRoaXMuc2h1dGRvd25BbGxXb3JrZXJzKHNpZ25hbCk7XG5cbiAgICAvLyBFeGVjdXRlIHByaW1hcnkgc2h1dGRvd24gZnVuY3Rpb25cbiAgICBhd2FpdCBzYWZlRXhlY3V0ZShcbiAgICAgICgpID0+XG4gICAgICAgIHRpbWVvdXQoXG4gICAgICAgICAgdGhpcy5vcHRpb25zLnByaW1hcnlTaHV0ZG93bkZuKHNpZ25hbCksXG4gICAgICAgICAgdGhpcy5vcHRpb25zLnNodXRkb3duVGltZW91dCxcbiAgICAgICAgICAncHJpbWFyeSBzaHV0ZG93biB0aW1lb3V0JyxcbiAgICAgICAgKSxcbiAgICAgICdFcnJvciBpbiBwcmltYXJ5IHNodXRkb3duIGZ1bmN0aW9uJyxcbiAgICApO1xuXG4gICAgbG9nZ2VyLmluZm8oYFByaW1hcnkgcHJvY2VzcyAocGlkOiAke3Byb2Nlc3MucGlkfSkgc2h1dGRvd24gY29tcGxldGVkYCk7XG4gICAgdGhpcy5lbWl0KCdzaHV0ZG93bjpjb21wbGV0ZWQnKTtcbiAgICBwcm9jZXNzLmV4aXQoMCk7XG4gIH1cblxuICAvKipcbiAgICogU2h1dHMgZG93biBhbGwgd29ya2VycyBncmFjZWZ1bGx5XG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHNodXRkb3duQWxsV29ya2VycyhzaWduYWw/OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy53b3JrZXJzLnNpemUgPT09IDApIHJldHVybjtcblxuICAgIGxvZ2dlci5pbmZvKGBTaHV0dGluZyBkb3duICR7dGhpcy53b3JrZXJzLnNpemV9IHdvcmtlcnMuLi5gKTtcblxuICAgIC8vIE1hcmsgYWxsIHdvcmtlcnMgYXMgc2h1dHRpbmcgZG93biBhbmQgc2VuZCBzaHV0ZG93biBtZXNzYWdlXG4gICAgQXJyYXkuZnJvbSh0aGlzLndvcmtlcnMudmFsdWVzKCkpLmZvckVhY2goKHdvcmtlclN0YXRlKSA9PiB7XG4gICAgICB3b3JrZXJTdGF0ZS5pc1NodXR0aW5nRG93biA9IHRydWU7XG4gICAgICAvLyBPbmx5IHNlbmQgc2h1dGRvd24gbWVzc2FnZSBpZiB3b3JrZXIgaXMgc3RpbGwgY29ubmVjdGVkXG4gICAgICBpZiAoIXdvcmtlclN0YXRlLndvcmtlci5pc0RlYWQoKSAmJiB3b3JrZXJTdGF0ZS53b3JrZXIucHJvY2Vzcy5jb25uZWN0ZWQpIHtcbiAgICAgICAgY29uc3Qgc2h1dGRvd25NZXNzYWdlOiBTaHV0ZG93bk1lc3NhZ2UgPSB7XG4gICAgICAgICAgdHlwZTogJ3NodXRkb3duJyxcbiAgICAgICAgICBzaWduYWwsXG4gICAgICAgIH07XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgd29ya2VyU3RhdGUud29ya2VyLnNlbmQoc2h1dGRvd25NZXNzYWdlKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAvLyBXb3JrZXIgSVBDIGNoYW5uZWwgaXMgYWxyZWFkeSBjbG9zZWQsIHdoaWNoIGlzIGZpbmVcbiAgICAgICAgICBsb2dnZXIud2FybihcbiAgICAgICAgICAgIGBGYWlsZWQgdG8gc2VuZCBzaHV0ZG93biBtZXNzYWdlIHRvIHdvcmtlciAke3dvcmtlclN0YXRlLmlkfSAocGlkOiAke1xuICAgICAgICAgICAgICB3b3JrZXJTdGF0ZS53b3JrZXIucHJvY2Vzcy5waWRcbiAgICAgICAgICAgIH0pOiAke2Vycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKX1gLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIFdhaXQgZm9yIHdvcmtlcnMgdG8gZXhpdCBncmFjZWZ1bGx5IG9yIHRpbWVvdXRcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGltZW91dChcbiAgICAgICAgdGhpcy53YWl0Rm9yQWxsV29ya2Vyc1RvRXhpdCgpLFxuICAgICAgICB0aGlzLm9wdGlvbnMuc2h1dGRvd25UaW1lb3V0LFxuICAgICAgICAnV29ya2VyIHNodXRkb3duIHRpbWVvdXQnLFxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgbG9nZ2VyLmVycm9yKCdHcmFjZWZ1bCBzaHV0ZG93biBmb3Igd29ya2VycyB0aW1lZCBvdXQsIGZvcmNpbmcgc2h1dGRvd24nKTtcbiAgICAgIHRoaXMuZm9yY2VLaWxsQWxsV29ya2VycygpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBXYWl0cyBmb3IgYWxsIHdvcmtlcnMgdG8gZXhpdFxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyB3YWl0Rm9yQWxsV29ya2Vyc1RvRXhpdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB3aGlsZSAodGhpcy53b3JrZXJzLnNpemUgPiAwKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYXdhaXQtaW4tbG9vcFxuICAgICAgYXdhaXQgZGVsYXkoMTAwKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRm9yY2Uga2lsbHMgYWxsIHJlbWFpbmluZyB3b3JrZXJzXG4gICAqL1xuICBwcml2YXRlIGZvcmNlS2lsbEFsbFdvcmtlcnMoKTogdm9pZCB7XG4gICAgQXJyYXkuZnJvbSh0aGlzLndvcmtlcnMudmFsdWVzKCkpLmZvckVhY2goKHdvcmtlclN0YXRlKSA9PiB7XG4gICAgICBsb2dnZXIuZXJyb3IoXG4gICAgICAgIGBGb3JjZSBraWxsaW5nIHdvcmtlciAke3dvcmtlclN0YXRlLmlkfSAocGlkOiAke3dvcmtlclN0YXRlLndvcmtlci5wcm9jZXNzLnBpZH0pYCxcbiAgICAgICk7XG4gICAgICB3b3JrZXJTdGF0ZS53b3JrZXIua2lsbCgnU0lHS0lMTCcpO1xuICAgIH0pO1xuICAgIHRoaXMud29ya2Vycy5jbGVhcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNodXRzIGRvd24gYSB3b3JrZXIgcHJvY2Vzc1xuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBzaHV0ZG93bldvcmtlcihzaWduYWw/OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsb2dnZXIuaW5mbyhcbiAgICAgIGBXb3JrZXIgJHt0aGlzLmdldEN1cnJlbnRXb3JrZXJJZCgpfSAocGlkOiAke3Byb2Nlc3MucGlkfSkgc2h1dHRpbmcgZG93biAoc2lnbmFsOiAke1xuICAgICAgICBzaWduYWwgPz8gJ21hbnVhbCdcbiAgICAgIH0pYCxcbiAgICApO1xuXG4gICAgdGhpcy5yZW1vdmVTaWduYWxIYW5kbGVycygpO1xuXG4gICAgLy8gRXhlY3V0ZSB3b3JrZXIgc2h1dGRvd24gZnVuY3Rpb25cbiAgICBhd2FpdCBzYWZlRXhlY3V0ZShcbiAgICAgICgpID0+XG4gICAgICAgIHRpbWVvdXQoXG4gICAgICAgICAgdGhpcy5vcHRpb25zLndvcmtlclNodXRkb3duRm4oc2lnbmFsKSxcbiAgICAgICAgICB0aGlzLm9wdGlvbnMuc2h1dGRvd25UaW1lb3V0LFxuICAgICAgICAgICd3b3JrZXIgc2h1dGRvd24gdGltZW91dCcsXG4gICAgICAgICksXG4gICAgICBgRXJyb3IgaW4gd29ya2VyICR7dGhpcy5nZXRDdXJyZW50V29ya2VySWQoKX0gKHBpZDogJHtwcm9jZXNzLnBpZH0pIHNodXRkb3duIGZ1bmN0aW9uYCxcbiAgICApO1xuXG4gICAgbG9nZ2VyLmluZm8oYFdvcmtlciAke3RoaXMuZ2V0Q3VycmVudFdvcmtlcklkKCl9IChwaWQ6ICR7cHJvY2Vzcy5waWR9KSBzaHV0ZG93biBjb21wbGV0ZWRgKTtcbiAgICBwcm9jZXNzLmV4aXQoMCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgY3VycmVudCBudW1iZXIgb2YgYWN0aXZlIHdvcmtlcnNcbiAgICovXG4gIHB1YmxpYyBnZXRXb3JrZXJDb3VudCgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLndvcmtlcnMuc2l6ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIGluZm9ybWF0aW9uIGFib3V0IGFsbCB3b3JrZXJzXG4gICAqL1xuICBwdWJsaWMgZ2V0V29ya2VySW5mbygpOiBBcnJheTx7IGlkOiBudW1iZXI7IHBpZDogbnVtYmVyOyByZXN0YXJ0Q291bnQ6IG51bWJlciB9PiB7XG4gICAgcmV0dXJuIEFycmF5LmZyb20odGhpcy53b3JrZXJzLnZhbHVlcygpKS5tYXAoKHN0YXRlKSA9PiAoe1xuICAgICAgaWQ6IHN0YXRlLmlkLFxuICAgICAgcGlkOiBzdGF0ZS53b3JrZXIucHJvY2Vzcy5waWQgPz8gLTEsXG4gICAgICByZXN0YXJ0Q291bnQ6IHN0YXRlLnJlc3RhcnRDb3VudCxcbiAgICB9KSk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIHRoZSBjbHVzdGVyIGlzIGN1cnJlbnRseSBzdGFydGVkXG4gICAqL1xuICBwdWJsaWMgaXNTdGFydGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnN0YXJ0ZWQ7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIHRoZSBjbHVzdGVyIGlzIGN1cnJlbnRseSBzaHV0dGluZyBkb3duXG4gICAqL1xuICBwdWJsaWMgaXNTaHV0ZG93bigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5pc1NodXR0aW5nRG93bjtcbiAgfVxufVxuXG4vLyBUeXBlLXNhZmUgZXZlbnQgZW1pdHRlciBpbnRlcmZhY2VcbmV4cG9ydCBpbnRlcmZhY2UgQ2x1c3Rlck1hbmFnZXJFbWl0dGVyIHtcbiAgb248SyBleHRlbmRzIGtleW9mIENsdXN0ZXJNYW5hZ2VyRXZlbnRzPihldmVudDogSywgbGlzdGVuZXI6IENsdXN0ZXJNYW5hZ2VyRXZlbnRzW0tdKTogdGhpcztcbiAgZW1pdDxLIGV4dGVuZHMga2V5b2YgQ2x1c3Rlck1hbmFnZXJFdmVudHM+KFxuICAgIGV2ZW50OiBLLFxuICAgIC4uLmFyZ3M6IFBhcmFtZXRlcnM8Q2x1c3Rlck1hbmFnZXJFdmVudHNbS10+XG4gICk6IGJvb2xlYW47XG59XG4iXX0=
@@ -0,0 +1,78 @@
1
+ import { Worker } from 'cluster';
2
+ /**
3
+ * Configuration options for ClusterManager
4
+ */
5
+ export interface ClusterManagerOptions {
6
+ cluster?: Cluster;
7
+ /** Function to execute in the primary process during start */
8
+ primaryFn?: () => void | Promise<void>;
9
+ /** Function to execute in the primary process after all workers have been shutdown and just before primary process shutdown */
10
+ primaryShutdownFn?: (signal?: string) => Promise<void>;
11
+ /** Function to execute in worker processes during start */
12
+ workerFn?: () => void | Promise<void>;
13
+ /** Function to execute in worker processes just before worker process shutdown */
14
+ workerShutdownFn?: (signal?: string) => Promise<void>;
15
+ /** Frequency of worker health checks in milliseconds (default: 10000) */
16
+ pingFrequency?: number;
17
+ /** Timeout for worker ping responses in milliseconds (default: 30000) */
18
+ pingTimeout?: number;
19
+ /** Callback to determine action when a stuck worker is killed, if true a new worker will be spawned, if false cluster will shutdown (default: true) */
20
+ stuckWorkerRespawnFunc?: (worker: Worker) => boolean;
21
+ /** Maximum number of times to restart a worker after it has exited unexpectedly (default: 3) */
22
+ restartMaxTimes?: number;
23
+ /** Signals that trigger shutdown (default: ['SIGINT', 'SIGTERM']) */
24
+ shutdownSignals?: NodeJS.Signals[];
25
+ /** Timeout for graceful worker shutdown in milliseconds (default: 30000) */
26
+ shutdownTimeout?: number;
27
+ /** Number of worker processes to spawn (default: number of CPU cores) */
28
+ numWorkers?: number;
29
+ }
30
+ export interface Cluster {
31
+ worker?: Worker | undefined;
32
+ readonly isPrimary: boolean;
33
+ fork(env?: any): Worker;
34
+ on(event: string, listener: (...args: any[]) => void): Cluster;
35
+ on(event: 'exit', listener: (worker: Worker, code: number, signal: string) => void): this;
36
+ on(event: 'online', listener: (worker: Worker) => void): this;
37
+ }
38
+ /**
39
+ * Internal worker state tracking
40
+ */
41
+ export interface WorkerState {
42
+ id: number;
43
+ worker: Worker;
44
+ restartCount: number;
45
+ lastPing: number;
46
+ pendingPing: boolean;
47
+ isShuttingDown: boolean;
48
+ }
49
+ /**
50
+ * Events emitted by ClusterManager
51
+ */
52
+ export interface ClusterManagerEvents {
53
+ 'worker:started': (worker: Worker) => void;
54
+ 'worker:died': (worker: Worker, code: number | null, signal: string | null) => void;
55
+ 'worker:stuck': (worker: Worker) => void;
56
+ 'worker:restarted': (worker: Worker, restartCount: number) => void;
57
+ 'worker:restart-limit-exceeded': (worker: Worker, restartCount: number) => void;
58
+ 'shutdown:started': (signal?: string) => void;
59
+ 'shutdown:completed': () => void;
60
+ error: (error: Error) => void;
61
+ }
62
+ /**
63
+ * Message types for inter-process communication
64
+ */
65
+ export interface PingMessage {
66
+ type: 'ping';
67
+ timestamp: number;
68
+ }
69
+ export interface PongMessage {
70
+ type: 'pong';
71
+ timestamp: number;
72
+ }
73
+ export interface ShutdownMessage {
74
+ type: 'shutdown';
75
+ signal?: string;
76
+ }
77
+ export type IPCMessage = PingMessage | PongMessage | ShutdownMessage;
78
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/cluster/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvC,+HAA+H;IAC/H,iBAAiB,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvD,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtC,kFAAkF;IAClF,gBAAgB,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtD,yEAAyE;IACzE,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,uJAAuJ;IACvJ,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAErD,gGAAgG;IAChG,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,qEAAqE;IACrE,eAAe,CAAC,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;IAEnC,4EAA4E;IAC5E,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,OAAO;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAE5B,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,MAAM,CAAC;IAExB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC;IAC/D,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAC1F,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;CAC/D;AACD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACpF,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,kBAAkB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACnE,+BAA+B,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAChF,kBAAkB,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,oBAAoB,EAAE,MAAM,IAAI,CAAC;IACjC,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,WAAW,GAAG,eAAe,CAAC"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY2x1c3Rlci90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgV29ya2VyIH0gZnJvbSAnY2x1c3Rlcic7XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBvcHRpb25zIGZvciBDbHVzdGVyTWFuYWdlclxuICovXG5leHBvcnQgaW50ZXJmYWNlIENsdXN0ZXJNYW5hZ2VyT3B0aW9ucyB7XG4gIGNsdXN0ZXI/OiBDbHVzdGVyO1xuXG4gIC8qKiBGdW5jdGlvbiB0byBleGVjdXRlIGluIHRoZSBwcmltYXJ5IHByb2Nlc3MgZHVyaW5nIHN0YXJ0ICovXG4gIHByaW1hcnlGbj86ICgpID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+O1xuXG4gIC8qKiBGdW5jdGlvbiB0byBleGVjdXRlIGluIHRoZSBwcmltYXJ5IHByb2Nlc3MgYWZ0ZXIgYWxsIHdvcmtlcnMgaGF2ZSBiZWVuIHNodXRkb3duIGFuZCBqdXN0IGJlZm9yZSBwcmltYXJ5IHByb2Nlc3Mgc2h1dGRvd24gKi9cbiAgcHJpbWFyeVNodXRkb3duRm4/OiAoc2lnbmFsPzogc3RyaW5nKSA9PiBQcm9taXNlPHZvaWQ+O1xuXG4gIC8qKiBGdW5jdGlvbiB0byBleGVjdXRlIGluIHdvcmtlciBwcm9jZXNzZXMgZHVyaW5nIHN0YXJ0ICovXG4gIHdvcmtlckZuPzogKCkgPT4gdm9pZCB8IFByb21pc2U8dm9pZD47XG5cbiAgLyoqIEZ1bmN0aW9uIHRvIGV4ZWN1dGUgaW4gd29ya2VyIHByb2Nlc3NlcyBqdXN0IGJlZm9yZSB3b3JrZXIgcHJvY2VzcyBzaHV0ZG93biAqL1xuICB3b3JrZXJTaHV0ZG93bkZuPzogKHNpZ25hbD86IHN0cmluZykgPT4gUHJvbWlzZTx2b2lkPjtcblxuICAvKiogRnJlcXVlbmN5IG9mIHdvcmtlciBoZWFsdGggY2hlY2tzIGluIG1pbGxpc2Vjb25kcyAoZGVmYXVsdDogMTAwMDApICovXG4gIHBpbmdGcmVxdWVuY3k/OiBudW1iZXI7XG5cbiAgLyoqIFRpbWVvdXQgZm9yIHdvcmtlciBwaW5nIHJlc3BvbnNlcyBpbiBtaWxsaXNlY29uZHMgKGRlZmF1bHQ6IDMwMDAwKSAqL1xuICBwaW5nVGltZW91dD86IG51bWJlcjtcblxuICAvKiogQ2FsbGJhY2sgdG8gZGV0ZXJtaW5lIGFjdGlvbiB3aGVuIGEgc3R1Y2sgd29ya2VyIGlzIGtpbGxlZCwgaWYgdHJ1ZSBhIG5ldyB3b3JrZXIgd2lsbCBiZSBzcGF3bmVkLCBpZiBmYWxzZSBjbHVzdGVyIHdpbGwgc2h1dGRvd24gKGRlZmF1bHQ6IHRydWUpICovXG4gIHN0dWNrV29ya2VyUmVzcGF3bkZ1bmM/OiAod29ya2VyOiBXb3JrZXIpID0+IGJvb2xlYW47XG5cbiAgLyoqIE1heGltdW0gbnVtYmVyIG9mIHRpbWVzIHRvIHJlc3RhcnQgYSB3b3JrZXIgYWZ0ZXIgaXQgaGFzIGV4aXRlZCB1bmV4cGVjdGVkbHkgKGRlZmF1bHQ6IDMpICovXG4gIHJlc3RhcnRNYXhUaW1lcz86IG51bWJlcjtcblxuICAvKiogU2lnbmFscyB0aGF0IHRyaWdnZXIgc2h1dGRvd24gKGRlZmF1bHQ6IFsnU0lHSU5UJywgJ1NJR1RFUk0nXSkgKi9cbiAgc2h1dGRvd25TaWduYWxzPzogTm9kZUpTLlNpZ25hbHNbXTtcblxuICAvKiogVGltZW91dCBmb3IgZ3JhY2VmdWwgd29ya2VyIHNodXRkb3duIGluIG1pbGxpc2Vjb25kcyAoZGVmYXVsdDogMzAwMDApICovXG4gIHNodXRkb3duVGltZW91dD86IG51bWJlcjtcblxuICAvKiogTnVtYmVyIG9mIHdvcmtlciBwcm9jZXNzZXMgdG8gc3Bhd24gKGRlZmF1bHQ6IG51bWJlciBvZiBDUFUgY29yZXMpICovXG4gIG51bVdvcmtlcnM/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2x1c3RlciB7XG4gIHdvcmtlcj86IFdvcmtlciB8IHVuZGVmaW5lZDtcbiAgcmVhZG9ubHkgaXNQcmltYXJ5OiBib29sZWFuO1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICBmb3JrKGVudj86IGFueSk6IFdvcmtlcjtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgb24oZXZlbnQ6IHN0cmluZywgbGlzdGVuZXI6ICguLi5hcmdzOiBhbnlbXSkgPT4gdm9pZCk6IENsdXN0ZXI7XG4gIG9uKGV2ZW50OiAnZXhpdCcsIGxpc3RlbmVyOiAod29ya2VyOiBXb3JrZXIsIGNvZGU6IG51bWJlciwgc2lnbmFsOiBzdHJpbmcpID0+IHZvaWQpOiB0aGlzO1xuICBvbihldmVudDogJ29ubGluZScsIGxpc3RlbmVyOiAod29ya2VyOiBXb3JrZXIpID0+IHZvaWQpOiB0aGlzO1xufVxuLyoqXG4gKiBJbnRlcm5hbCB3b3JrZXIgc3RhdGUgdHJhY2tpbmdcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBXb3JrZXJTdGF0ZSB7XG4gIGlkOiBudW1iZXI7XG4gIHdvcmtlcjogV29ya2VyO1xuICByZXN0YXJ0Q291bnQ6IG51bWJlcjsgLy8gTnVtYmVyIG9mIHRpbWVzIHRoZSB3b3JrZXIgaGFzIGJlZW4gcmVzdGFydGVkXG4gIGxhc3RQaW5nOiBudW1iZXI7IC8vIFRpbWVzdGFtcCBvZiB0aGUgbGFzdCBwaW5nIHJlY2VpdmVkIGZyb20gdGhlIHdvcmtlclxuICBwZW5kaW5nUGluZzogYm9vbGVhbjsgLy8gV2hldGhlciBhIHBpbmcgcmVzcG9uc2UgaXMgcGVuZGluZyBmcm9tIHRoZSB3b3JrZXJcbiAgaXNTaHV0dGluZ0Rvd246IGJvb2xlYW47IC8vIFdoZXRoZXIgdGhlIHdvcmtlciBpcyBpbiB0aGUgcHJvY2VzcyBvZiBzaHV0dGluZyBkb3duXG59XG5cbi8qKlxuICogRXZlbnRzIGVtaXR0ZWQgYnkgQ2x1c3Rlck1hbmFnZXJcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDbHVzdGVyTWFuYWdlckV2ZW50cyB7XG4gICd3b3JrZXI6c3RhcnRlZCc6ICh3b3JrZXI6IFdvcmtlcikgPT4gdm9pZDtcbiAgJ3dvcmtlcjpkaWVkJzogKHdvcmtlcjogV29ya2VyLCBjb2RlOiBudW1iZXIgfCBudWxsLCBzaWduYWw6IHN0cmluZyB8IG51bGwpID0+IHZvaWQ7XG4gICd3b3JrZXI6c3R1Y2snOiAod29ya2VyOiBXb3JrZXIpID0+IHZvaWQ7XG4gICd3b3JrZXI6cmVzdGFydGVkJzogKHdvcmtlcjogV29ya2VyLCByZXN0YXJ0Q291bnQ6IG51bWJlcikgPT4gdm9pZDtcbiAgJ3dvcmtlcjpyZXN0YXJ0LWxpbWl0LWV4Y2VlZGVkJzogKHdvcmtlcjogV29ya2VyLCByZXN0YXJ0Q291bnQ6IG51bWJlcikgPT4gdm9pZDtcbiAgJ3NodXRkb3duOnN0YXJ0ZWQnOiAoc2lnbmFsPzogc3RyaW5nKSA9PiB2b2lkO1xuICAnc2h1dGRvd246Y29tcGxldGVkJzogKCkgPT4gdm9pZDtcbiAgZXJyb3I6IChlcnJvcjogRXJyb3IpID0+IHZvaWQ7XG59XG5cbi8qKlxuICogTWVzc2FnZSB0eXBlcyBmb3IgaW50ZXItcHJvY2VzcyBjb21tdW5pY2F0aW9uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUGluZ01lc3NhZ2Uge1xuICB0eXBlOiAncGluZyc7XG4gIHRpbWVzdGFtcDogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFBvbmdNZXNzYWdlIHtcbiAgdHlwZTogJ3BvbmcnO1xuICB0aW1lc3RhbXA6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTaHV0ZG93bk1lc3NhZ2Uge1xuICB0eXBlOiAnc2h1dGRvd24nO1xuICBzaWduYWw/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCB0eXBlIElQQ01lc3NhZ2UgPSBQaW5nTWVzc2FnZSB8IFBvbmdNZXNzYWdlIHwgU2h1dGRvd25NZXNzYWdlO1xuIl19
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Utility functions for ClusterManager
3
+ */
4
+ /**
5
+ * Creates a promise that resolves after the specified timeout
6
+ */
7
+ export declare function delay(ms: number): Promise<void>;
8
+ /**
9
+ * Creates a promise that rejects after the specified timeout
10
+ */
11
+ export declare function timeout<T>(promise: Promise<T>, ms: number, errorMessage?: string): Promise<T>;
12
+ /**
13
+ * Safely executes an async function with error handling
14
+ */
15
+ export declare function safeExecute<T>(fn: () => T | Promise<T>, errorMessage: string): Promise<T | undefined>;
16
+ /**
17
+ * Validates ClusterManagerOptions and provides defaults
18
+ */
19
+ export declare function validateAndDefaultOptions(options: import('./types').ClusterManagerOptions): Required<import('./types').ClusterManagerOptions>;
20
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/cluster/utils.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/C;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAa7F;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,CAAC,EACjC,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EACxB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAOxB;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,OAAO,SAAS,EAAE,qBAAqB,GAC/C,QAAQ,CAAC,OAAO,SAAS,EAAE,qBAAqB,CAAC,CAgBnD"}
@@ -0,0 +1,106 @@
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
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.delay = delay;
40
+ exports.timeout = timeout;
41
+ exports.safeExecute = safeExecute;
42
+ exports.validateAndDefaultOptions = validateAndDefaultOptions;
43
+ const os_1 = require("os");
44
+ const cluster_1 = __importDefault(require("cluster"));
45
+ const logger = __importStar(require("../logger"));
46
+ /**
47
+ * Utility functions for ClusterManager
48
+ */
49
+ /**
50
+ * Creates a promise that resolves after the specified timeout
51
+ */
52
+ function delay(ms) {
53
+ return new Promise((resolve) => {
54
+ setTimeout(resolve, ms);
55
+ });
56
+ }
57
+ /**
58
+ * Creates a promise that rejects after the specified timeout
59
+ */
60
+ function timeout(promise, ms, errorMessage) {
61
+ let timeoutHandle;
62
+ const timeoutPromise = new Promise((_, reject) => {
63
+ timeoutHandle = setTimeout(() => {
64
+ reject(new Error(errorMessage ?? `Operation timed out after ${ms}ms`));
65
+ }, ms);
66
+ });
67
+ return Promise.race([
68
+ promise.finally(() => {
69
+ clearTimeout(timeoutHandle);
70
+ }),
71
+ timeoutPromise,
72
+ ]);
73
+ }
74
+ /**
75
+ * Safely executes an async function with error handling
76
+ */
77
+ async function safeExecute(fn, errorMessage) {
78
+ try {
79
+ return await fn();
80
+ }
81
+ catch (error) {
82
+ logger.error(`${errorMessage}:`, error);
83
+ return undefined;
84
+ }
85
+ }
86
+ /**
87
+ * Validates ClusterManagerOptions and provides defaults
88
+ */
89
+ function validateAndDefaultOptions(options) {
90
+ const numCPUs = (0, os_1.cpus)().length;
91
+ return {
92
+ cluster: options.cluster ?? cluster_1.default,
93
+ primaryFn: options.primaryFn ?? (() => { }),
94
+ primaryShutdownFn: options.primaryShutdownFn ?? (async () => { }),
95
+ workerFn: options.workerFn ?? (() => { }),
96
+ workerShutdownFn: options.workerShutdownFn ?? (async () => { }),
97
+ pingFrequency: options.pingFrequency ?? 10000,
98
+ pingTimeout: options.pingTimeout ?? 30000,
99
+ stuckWorkerRespawnFunc: options.stuckWorkerRespawnFunc ?? (() => true),
100
+ restartMaxTimes: options.restartMaxTimes ?? 3,
101
+ shutdownSignals: options.shutdownSignals ?? ['SIGINT', 'SIGTERM'],
102
+ shutdownTimeout: options.shutdownTimeout ?? 30000,
103
+ numWorkers: options.numWorkers ?? numCPUs,
104
+ };
105
+ }
106
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY2x1c3Rlci91dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQVdBLHNCQUlDO0FBS0QsMEJBYUM7QUFLRCxrQ0FVQztBQUtELDhEQWtCQztBQXZFRCwyQkFBMEI7QUFDMUIsc0RBQThCO0FBQzlCLGtEQUFvQztBQUVwQzs7R0FFRztBQUVIOztHQUVHO0FBQ0gsU0FBZ0IsS0FBSyxDQUFDLEVBQVU7SUFDOUIsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFO1FBQzdCLFVBQVUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDMUIsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFnQixPQUFPLENBQUksT0FBbUIsRUFBRSxFQUFVLEVBQUUsWUFBcUI7SUFDL0UsSUFBSSxhQUE2QixDQUFDO0lBQ2xDLE1BQU0sY0FBYyxHQUFHLElBQUksT0FBTyxDQUFRLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxFQUFFO1FBQ3RELGFBQWEsR0FBRyxVQUFVLENBQUMsR0FBRyxFQUFFO1lBQzlCLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQyxZQUFZLElBQUksNkJBQTZCLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUN6RSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDVCxDQUFDLENBQUMsQ0FBQztJQUNILE9BQU8sT0FBTyxDQUFDLElBQUksQ0FBQztRQUNsQixPQUFPLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRTtZQUNuQixZQUFZLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDOUIsQ0FBQyxDQUFDO1FBQ0YsY0FBYztLQUNmLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRDs7R0FFRztBQUNJLEtBQUssVUFBVSxXQUFXLENBQy9CLEVBQXdCLEVBQ3hCLFlBQW9CO0lBRXBCLElBQUksQ0FBQztRQUNILE9BQU8sTUFBTSxFQUFFLEVBQUUsQ0FBQztJQUNwQixDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxZQUFZLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUN4QyxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0FBQ0gsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBZ0IseUJBQXlCLENBQ3ZDLE9BQWdEO0lBRWhELE1BQU0sT0FBTyxHQUFHLElBQUEsU0FBSSxHQUFFLENBQUMsTUFBTSxDQUFDO0lBQzlCLE9BQU87UUFDTCxPQUFPLEVBQUUsT0FBTyxDQUFDLE9BQU8sSUFBSSxpQkFBTztRQUNuQyxTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVMsSUFBSSxDQUFDLEdBQVMsRUFBRSxHQUFFLENBQUMsQ0FBQztRQUNoRCxpQkFBaUIsRUFBRSxPQUFPLENBQUMsaUJBQWlCLElBQUksQ0FBQyxLQUFLLElBQW1CLEVBQUUsR0FBRSxDQUFDLENBQUM7UUFDL0UsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRLElBQUksQ0FBQyxHQUFTLEVBQUUsR0FBRSxDQUFDLENBQUM7UUFDOUMsZ0JBQWdCLEVBQUUsT0FBTyxDQUFDLGdCQUFnQixJQUFJLENBQUMsS0FBSyxJQUFtQixFQUFFLEdBQUUsQ0FBQyxDQUFDO1FBQzdFLGFBQWEsRUFBRSxPQUFPLENBQUMsYUFBYSxJQUFJLEtBQUs7UUFDN0MsV0FBVyxFQUFFLE9BQU8sQ0FBQyxXQUFXLElBQUksS0FBSztRQUN6QyxzQkFBc0IsRUFBRSxPQUFPLENBQUMsc0JBQXNCLElBQUksQ0FBQyxHQUFZLEVBQUUsQ0FBQyxJQUFJLENBQUM7UUFDL0UsZUFBZSxFQUFFLE9BQU8sQ0FBQyxlQUFlLElBQUksQ0FBQztRQUM3QyxlQUFlLEVBQUUsT0FBTyxDQUFDLGVBQWUsSUFBSSxDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUM7UUFDakUsZUFBZSxFQUFFLE9BQU8sQ0FBQyxlQUFlLElBQUksS0FBSztRQUNqRCxVQUFVLEVBQUUsT0FBTyxDQUFDLFVBQVUsSUFBSSxPQUFPO0tBQzFDLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3B1cyB9IGZyb20gJ29zJztcbmltcG9ydCBjbHVzdGVyIGZyb20gJ2NsdXN0ZXInO1xuaW1wb3J0ICogYXMgbG9nZ2VyIGZyb20gJy4uL2xvZ2dlcic7XG5cbi8qKlxuICogVXRpbGl0eSBmdW5jdGlvbnMgZm9yIENsdXN0ZXJNYW5hZ2VyXG4gKi9cblxuLyoqXG4gKiBDcmVhdGVzIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIGFmdGVyIHRoZSBzcGVjaWZpZWQgdGltZW91dFxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVsYXkobXM6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKTtcbiAgfSk7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIHByb21pc2UgdGhhdCByZWplY3RzIGFmdGVyIHRoZSBzcGVjaWZpZWQgdGltZW91dFxuICovXG5leHBvcnQgZnVuY3Rpb24gdGltZW91dDxUPihwcm9taXNlOiBQcm9taXNlPFQ+LCBtczogbnVtYmVyLCBlcnJvck1lc3NhZ2U/OiBzdHJpbmcpOiBQcm9taXNlPFQ+IHtcbiAgbGV0IHRpbWVvdXRIYW5kbGU6IE5vZGVKUy5UaW1lb3V0O1xuICBjb25zdCB0aW1lb3V0UHJvbWlzZSA9IG5ldyBQcm9taXNlPG5ldmVyPigoXywgcmVqZWN0KSA9PiB7XG4gICAgdGltZW91dEhhbmRsZSA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgcmVqZWN0KG5ldyBFcnJvcihlcnJvck1lc3NhZ2UgPz8gYE9wZXJhdGlvbiB0aW1lZCBvdXQgYWZ0ZXIgJHttc31tc2ApKTtcbiAgICB9LCBtcyk7XG4gIH0pO1xuICByZXR1cm4gUHJvbWlzZS5yYWNlKFtcbiAgICBwcm9taXNlLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXRIYW5kbGUpO1xuICAgIH0pLFxuICAgIHRpbWVvdXRQcm9taXNlLFxuICBdKTtcbn1cblxuLyoqXG4gKiBTYWZlbHkgZXhlY3V0ZXMgYW4gYXN5bmMgZnVuY3Rpb24gd2l0aCBlcnJvciBoYW5kbGluZ1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2FmZUV4ZWN1dGU8VD4oXG4gIGZuOiAoKSA9PiBUIHwgUHJvbWlzZTxUPixcbiAgZXJyb3JNZXNzYWdlOiBzdHJpbmcsXG4pOiBQcm9taXNlPFQgfCB1bmRlZmluZWQ+IHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgZm4oKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBsb2dnZXIuZXJyb3IoYCR7ZXJyb3JNZXNzYWdlfTpgLCBlcnJvcik7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuXG4vKipcbiAqIFZhbGlkYXRlcyBDbHVzdGVyTWFuYWdlck9wdGlvbnMgYW5kIHByb3ZpZGVzIGRlZmF1bHRzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZUFuZERlZmF1bHRPcHRpb25zKFxuICBvcHRpb25zOiBpbXBvcnQoJy4vdHlwZXMnKS5DbHVzdGVyTWFuYWdlck9wdGlvbnMsXG4pOiBSZXF1aXJlZDxpbXBvcnQoJy4vdHlwZXMnKS5DbHVzdGVyTWFuYWdlck9wdGlvbnM+IHtcbiAgY29uc3QgbnVtQ1BVcyA9IGNwdXMoKS5sZW5ndGg7XG4gIHJldHVybiB7XG4gICAgY2x1c3Rlcjogb3B0aW9ucy5jbHVzdGVyID8/IGNsdXN0ZXIsXG4gICAgcHJpbWFyeUZuOiBvcHRpb25zLnByaW1hcnlGbiA/PyAoKCk6IHZvaWQgPT4ge30pLFxuICAgIHByaW1hcnlTaHV0ZG93bkZuOiBvcHRpb25zLnByaW1hcnlTaHV0ZG93bkZuID8/IChhc3luYyAoKTogUHJvbWlzZTx2b2lkPiA9PiB7fSksXG4gICAgd29ya2VyRm46IG9wdGlvbnMud29ya2VyRm4gPz8gKCgpOiB2b2lkID0+IHt9KSxcbiAgICB3b3JrZXJTaHV0ZG93bkZuOiBvcHRpb25zLndvcmtlclNodXRkb3duRm4gPz8gKGFzeW5jICgpOiBQcm9taXNlPHZvaWQ+ID0+IHt9KSxcbiAgICBwaW5nRnJlcXVlbmN5OiBvcHRpb25zLnBpbmdGcmVxdWVuY3kgPz8gMTAwMDAsXG4gICAgcGluZ1RpbWVvdXQ6IG9wdGlvbnMucGluZ1RpbWVvdXQgPz8gMzAwMDAsXG4gICAgc3R1Y2tXb3JrZXJSZXNwYXduRnVuYzogb3B0aW9ucy5zdHVja1dvcmtlclJlc3Bhd25GdW5jID8/ICgoKTogYm9vbGVhbiA9PiB0cnVlKSxcbiAgICByZXN0YXJ0TWF4VGltZXM6IG9wdGlvbnMucmVzdGFydE1heFRpbWVzID8/IDMsXG4gICAgc2h1dGRvd25TaWduYWxzOiBvcHRpb25zLnNodXRkb3duU2lnbmFscyA/PyBbJ1NJR0lOVCcsICdTSUdURVJNJ10sXG4gICAgc2h1dGRvd25UaW1lb3V0OiBvcHRpb25zLnNodXRkb3duVGltZW91dCA/PyAzMDAwMCxcbiAgICBudW1Xb3JrZXJzOiBvcHRpb25zLm51bVdvcmtlcnMgPz8gbnVtQ1BVcyxcbiAgfTtcbn1cbiJdfQ==
package/build/index.d.ts CHANGED
@@ -8,5 +8,6 @@ export * from './network';
8
8
  export * from './utils';
9
9
  export * from './constants';
10
10
  export * from './sdks';
11
+ export * from './cluster';
11
12
  export { setValue };
12
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,iBAAiB,CAAC;AAEvC,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,qBAAqB,CAAC;AACpC,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,QAAQ,CAAC;AACvB,OAAO,EAAE,QAAQ,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,iBAAiB,CAAC;AAEvC,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,qBAAqB,CAAC;AACpC,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,QAAQ,CAAC;AACvB,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,CAAC"}
package/build/index.js CHANGED
@@ -29,4 +29,5 @@ __exportStar(require("./network"), exports);
29
29
  __exportStar(require("./utils"), exports);
30
30
  __exportStar(require("./constants"), exports);
31
31
  __exportStar(require("./sdks"), exports);
32
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxnRUFBdUM7QUFXOUIsbUJBWEYsbUJBQVEsQ0FXRTtBQVRqQiwwQ0FBd0I7QUFDeEIseUNBQXVCO0FBQ3ZCLDJDQUF5QjtBQUN6QiwyQ0FBeUI7QUFDekIsc0RBQW9DO0FBQ3BDLDRDQUEwQjtBQUMxQiwwQ0FBd0I7QUFDeEIsOENBQTRCO0FBQzVCLHlDQUF1QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBzZXRWYWx1ZSBmcm9tICcuL2xpYi9zZXQtdmFsdWUnO1xuXG5leHBvcnQgKiBmcm9tICcuL3R5cGVzJztcbmV4cG9ydCAqIGZyb20gJy4vdGFncyc7XG5leHBvcnQgKiBmcm9tICcuL2Vycm9ycyc7XG5leHBvcnQgKiBmcm9tICcuL2xvZ2dlcic7XG5leHBvcnQgKiBmcm9tICcuL3N0cnVjdHVyZWQtbG9nZ2VyJztcbmV4cG9ydCAqIGZyb20gJy4vbmV0d29yayc7XG5leHBvcnQgKiBmcm9tICcuL3V0aWxzJztcbmV4cG9ydCAqIGZyb20gJy4vY29uc3RhbnRzJztcbmV4cG9ydCAqIGZyb20gJy4vc2Rrcyc7XG5leHBvcnQgeyBzZXRWYWx1ZSB9O1xuIl19
32
+ __exportStar(require("./cluster"), exports);
33
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxnRUFBdUM7QUFZOUIsbUJBWkYsbUJBQVEsQ0FZRTtBQVZqQiwwQ0FBd0I7QUFDeEIseUNBQXVCO0FBQ3ZCLDJDQUF5QjtBQUN6QiwyQ0FBeUI7QUFDekIsc0RBQW9DO0FBQ3BDLDRDQUEwQjtBQUMxQiwwQ0FBd0I7QUFDeEIsOENBQTRCO0FBQzVCLHlDQUF1QjtBQUN2Qiw0Q0FBMEIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgc2V0VmFsdWUgZnJvbSAnLi9saWIvc2V0LXZhbHVlJztcblxuZXhwb3J0ICogZnJvbSAnLi90eXBlcyc7XG5leHBvcnQgKiBmcm9tICcuL3RhZ3MnO1xuZXhwb3J0ICogZnJvbSAnLi9lcnJvcnMnO1xuZXhwb3J0ICogZnJvbSAnLi9sb2dnZXInO1xuZXhwb3J0ICogZnJvbSAnLi9zdHJ1Y3R1cmVkLWxvZ2dlcic7XG5leHBvcnQgKiBmcm9tICcuL25ldHdvcmsnO1xuZXhwb3J0ICogZnJvbSAnLi91dGlscyc7XG5leHBvcnQgKiBmcm9tICcuL2NvbnN0YW50cyc7XG5leHBvcnQgKiBmcm9tICcuL3Nka3MnO1xuZXhwb3J0ICogZnJvbSAnLi9jbHVzdGVyJztcbmV4cG9ydCB7IHNldFZhbHVlIH07XG4iXX0=
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rudderstack/integrations-lib",
3
- "version": "0.2.38",
3
+ "version": "0.2.40",
4
4
  "description": "",
5
5
  "main": "build/index.js",
6
6
  "module": "build/index.js",