@eggjs/cluster 3.0.0-beta.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.
Files changed (96) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +92 -0
  3. package/dist/commonjs/agent_worker.d.ts +1 -0
  4. package/dist/commonjs/agent_worker.js +65 -0
  5. package/dist/commonjs/app_worker.d.ts +1 -0
  6. package/dist/commonjs/app_worker.js +151 -0
  7. package/dist/commonjs/dirname.d.ts +1 -0
  8. package/dist/commonjs/dirname.js +17 -0
  9. package/dist/commonjs/error/ClusterAgentWorkerError.d.ts +10 -0
  10. package/dist/commonjs/error/ClusterAgentWorkerError.js +23 -0
  11. package/dist/commonjs/error/ClusterWorkerExceptionError.d.ts +7 -0
  12. package/dist/commonjs/error/ClusterWorkerExceptionError.js +18 -0
  13. package/dist/commonjs/error/index.d.ts +2 -0
  14. package/dist/commonjs/error/index.js +19 -0
  15. package/dist/commonjs/index.d.ts +17 -0
  16. package/dist/commonjs/index.js +37 -0
  17. package/dist/commonjs/master.d.ts +90 -0
  18. package/dist/commonjs/master.js +544 -0
  19. package/dist/commonjs/package.json +3 -0
  20. package/dist/commonjs/utils/messenger.d.ts +87 -0
  21. package/dist/commonjs/utils/messenger.js +183 -0
  22. package/dist/commonjs/utils/mode/base/agent.d.ts +38 -0
  23. package/dist/commonjs/utils/mode/base/agent.js +68 -0
  24. package/dist/commonjs/utils/mode/base/app.d.ts +48 -0
  25. package/dist/commonjs/utils/mode/base/app.js +81 -0
  26. package/dist/commonjs/utils/mode/impl/process/agent.d.ts +18 -0
  27. package/dist/commonjs/utils/mode/impl/process/agent.js +107 -0
  28. package/dist/commonjs/utils/mode/impl/process/app.d.ts +20 -0
  29. package/dist/commonjs/utils/mode/impl/process/app.js +134 -0
  30. package/dist/commonjs/utils/mode/impl/worker_threads/agent.d.ts +18 -0
  31. package/dist/commonjs/utils/mode/impl/worker_threads/agent.js +90 -0
  32. package/dist/commonjs/utils/mode/impl/worker_threads/app.d.ts +25 -0
  33. package/dist/commonjs/utils/mode/impl/worker_threads/app.js +156 -0
  34. package/dist/commonjs/utils/options.d.ts +80 -0
  35. package/dist/commonjs/utils/options.js +81 -0
  36. package/dist/commonjs/utils/terminate.d.ts +6 -0
  37. package/dist/commonjs/utils/terminate.js +89 -0
  38. package/dist/commonjs/utils/worker_manager.d.ts +25 -0
  39. package/dist/commonjs/utils/worker_manager.js +76 -0
  40. package/dist/esm/agent_worker.d.ts +1 -0
  41. package/dist/esm/agent_worker.js +63 -0
  42. package/dist/esm/app_worker.d.ts +1 -0
  43. package/dist/esm/app_worker.js +146 -0
  44. package/dist/esm/dirname.d.ts +1 -0
  45. package/dist/esm/dirname.js +11 -0
  46. package/dist/esm/error/ClusterAgentWorkerError.d.ts +10 -0
  47. package/dist/esm/error/ClusterAgentWorkerError.js +19 -0
  48. package/dist/esm/error/ClusterWorkerExceptionError.d.ts +7 -0
  49. package/dist/esm/error/ClusterWorkerExceptionError.js +14 -0
  50. package/dist/esm/error/index.d.ts +2 -0
  51. package/dist/esm/error/index.js +3 -0
  52. package/dist/esm/index.d.ts +17 -0
  53. package/dist/esm/index.js +19 -0
  54. package/dist/esm/master.d.ts +90 -0
  55. package/dist/esm/master.js +537 -0
  56. package/dist/esm/package.json +3 -0
  57. package/dist/esm/utils/messenger.d.ts +87 -0
  58. package/dist/esm/utils/messenger.js +176 -0
  59. package/dist/esm/utils/mode/base/agent.d.ts +38 -0
  60. package/dist/esm/utils/mode/base/agent.js +60 -0
  61. package/dist/esm/utils/mode/base/app.d.ts +48 -0
  62. package/dist/esm/utils/mode/base/app.js +73 -0
  63. package/dist/esm/utils/mode/impl/process/agent.d.ts +18 -0
  64. package/dist/esm/utils/mode/impl/process/agent.js +102 -0
  65. package/dist/esm/utils/mode/impl/process/app.d.ts +20 -0
  66. package/dist/esm/utils/mode/impl/process/app.js +126 -0
  67. package/dist/esm/utils/mode/impl/worker_threads/agent.d.ts +18 -0
  68. package/dist/esm/utils/mode/impl/worker_threads/agent.js +82 -0
  69. package/dist/esm/utils/mode/impl/worker_threads/app.d.ts +25 -0
  70. package/dist/esm/utils/mode/impl/worker_threads/app.js +151 -0
  71. package/dist/esm/utils/options.d.ts +80 -0
  72. package/dist/esm/utils/options.js +75 -0
  73. package/dist/esm/utils/terminate.d.ts +6 -0
  74. package/dist/esm/utils/terminate.js +86 -0
  75. package/dist/esm/utils/worker_manager.d.ts +25 -0
  76. package/dist/esm/utils/worker_manager.js +72 -0
  77. package/dist/package.json +4 -0
  78. package/package.json +94 -0
  79. package/src/agent_worker.ts +75 -0
  80. package/src/app_worker.ts +170 -0
  81. package/src/dirname.ts +11 -0
  82. package/src/error/ClusterAgentWorkerError.ts +19 -0
  83. package/src/error/ClusterWorkerExceptionError.ts +17 -0
  84. package/src/error/index.ts +2 -0
  85. package/src/index.ts +26 -0
  86. package/src/master.ts +641 -0
  87. package/src/utils/messenger.ts +199 -0
  88. package/src/utils/mode/base/agent.ts +90 -0
  89. package/src/utils/mode/base/app.ts +115 -0
  90. package/src/utils/mode/impl/process/agent.ts +118 -0
  91. package/src/utils/mode/impl/process/app.ts +146 -0
  92. package/src/utils/mode/impl/worker_threads/agent.ts +98 -0
  93. package/src/utils/mode/impl/worker_threads/app.ts +180 -0
  94. package/src/utils/options.ts +169 -0
  95. package/src/utils/terminate.ts +97 -0
  96. package/src/utils/worker_manager.ts +87 -0
@@ -0,0 +1,537 @@
1
+ import os from 'node:os';
2
+ import v8 from 'node:v8';
3
+ import util from 'node:util';
4
+ import path from 'node:path';
5
+ import fs from 'node:fs';
6
+ import net from 'node:net';
7
+ import { ReadyEventEmitter } from 'get-ready';
8
+ import { detectPort } from 'detect-port';
9
+ import { reload } from 'cluster-reload';
10
+ import { EggConsoleLogger as ConsoleLogger } from 'egg-logger';
11
+ import { readJSONSync } from 'utility';
12
+ import terminalLink from 'terminal-link';
13
+ import { parseOptions } from './utils/options.js';
14
+ import { WorkerManager } from './utils/worker_manager.js';
15
+ import { Messenger } from './utils/messenger.js';
16
+ import { AgentProcessUtils as ProcessAgentWorker, } from './utils/mode/impl/process/agent.js';
17
+ import { AppProcessUtils as ProcessAppWorker } from './utils/mode/impl/process/app.js';
18
+ import { AgentThreadUtils as WorkerThreadsAgentWorker, } from './utils/mode/impl/worker_threads/agent.js';
19
+ import { AppThreadUtils as WorkerThreadsAppWorker } from './utils/mode/impl/worker_threads/app.js';
20
+ import { ClusterWorkerExceptionError } from './error/ClusterWorkerExceptionError.js';
21
+ export class Master extends ReadyEventEmitter {
22
+ options;
23
+ isStarted = false;
24
+ workerManager;
25
+ messenger;
26
+ isProduction;
27
+ agentWorkerIndex = 0;
28
+ closed = false;
29
+ logger;
30
+ agentWorker;
31
+ appWorker;
32
+ #logMethod;
33
+ #realPort;
34
+ #protocol;
35
+ #appAddress;
36
+ constructor(options) {
37
+ super();
38
+ this.#start(options)
39
+ .catch(err => {
40
+ this.ready(err);
41
+ });
42
+ }
43
+ async #start(options) {
44
+ this.options = await parseOptions(options);
45
+ this.workerManager = new WorkerManager();
46
+ this.messenger = new Messenger(this, this.workerManager);
47
+ this.isProduction = isProduction(this.options);
48
+ this.#realPort = this.options.port;
49
+ this.#protocol = this.options.https ? 'https' : 'http';
50
+ // app started or not
51
+ this.isStarted = false;
52
+ this.logger = new ConsoleLogger({ level: process.env.EGG_MASTER_LOGGER_LEVEL ?? 'INFO' });
53
+ this.#logMethod = 'info';
54
+ if (this.options.env === 'local' || process.env.NODE_ENV === 'development') {
55
+ this.#logMethod = 'debug';
56
+ }
57
+ // get the real framework info
58
+ const frameworkPath = this.options.framework;
59
+ const frameworkPkg = readJSONSync(path.join(frameworkPath, 'package.json'));
60
+ // set app & agent worker impl
61
+ if (this.options.startMode === 'worker_threads') {
62
+ this.startByWorkerThreads();
63
+ }
64
+ else {
65
+ this.startByProcess();
66
+ }
67
+ this.log(`[master] =================== ${frameworkPkg.name} start =====================`);
68
+ this.logger.info(`[master] node version ${process.version}`);
69
+ /* istanbul ignore next */
70
+ if ('alinode' in process) {
71
+ this.logger.info(`[master] alinode version ${process.alinode}`);
72
+ }
73
+ this.logger.info(`[master] ${frameworkPkg.name} version ${frameworkPkg.version}`);
74
+ if (this.isProduction) {
75
+ this.logger.info('[master] start with options:%s%s', os.EOL, JSON.stringify(this.options, null, 2));
76
+ }
77
+ else {
78
+ this.log('[master] start with options: %j', this.options);
79
+ }
80
+ this.log('[master] start with env: isProduction: %s, EGG_SERVER_ENV: %s, NODE_ENV: %s', this.isProduction, this.options.env, process.env.NODE_ENV);
81
+ const startTime = Date.now();
82
+ this.ready(() => {
83
+ this.isStarted = true;
84
+ const stickyMsg = this.options.sticky ? ' with STICKY MODE!' : '';
85
+ const startedURL = terminalLink(this.#appAddress, this.#appAddress, { fallback: false });
86
+ this.logger.info('[master] %s started on %s (%sms)%s', frameworkPkg.name, startedURL, Date.now() - startTime, stickyMsg);
87
+ if (this.options.debugPort) {
88
+ const url = getAddress({
89
+ port: this.options.debugPort,
90
+ protocol: 'http',
91
+ });
92
+ const debugPortURL = terminalLink(url, url, { fallback: false });
93
+ this.logger.info('[master] %s started debug port on %s', frameworkPkg.name, debugPortURL);
94
+ }
95
+ const action = 'egg-ready';
96
+ this.messenger.send({
97
+ action,
98
+ to: 'parent',
99
+ data: {
100
+ port: this.#realPort,
101
+ debugPort: this.options.debugPort,
102
+ address: this.#appAddress,
103
+ protocol: this.#protocol,
104
+ },
105
+ });
106
+ this.messenger.send({
107
+ action,
108
+ to: 'app',
109
+ data: this.options,
110
+ });
111
+ this.messenger.send({
112
+ action,
113
+ to: 'agent',
114
+ data: this.options,
115
+ });
116
+ // start check agent and worker status
117
+ if (this.isProduction) {
118
+ this.workerManager.startCheck();
119
+ }
120
+ });
121
+ this.on('agent-exit', this.onAgentExit.bind(this));
122
+ this.on('agent-start', this.onAgentStart.bind(this));
123
+ this.on('app-exit', this.onAppExit.bind(this));
124
+ this.on('app-start', this.onAppStart.bind(this));
125
+ this.on('reload-worker', this.onReload.bind(this));
126
+ // fork app workers after agent started
127
+ this.once('agent-start', this.forkAppWorkers.bind(this));
128
+ // get the real port from options and app.config
129
+ // app worker will send after loading
130
+ this.on('realport', ({ port, protocol }) => {
131
+ if (port) {
132
+ this.#realPort = port;
133
+ }
134
+ if (protocol) {
135
+ this.#protocol = protocol;
136
+ }
137
+ });
138
+ // https://nodejs.org/api/process.html#process_signal_events
139
+ // https://en.wikipedia.org/wiki/Unix_signal
140
+ // kill(2) Ctrl-C
141
+ process.once('SIGINT', this.onSignal.bind(this, 'SIGINT'));
142
+ // kill(3) Ctrl-\
143
+ process.once('SIGQUIT', this.onSignal.bind(this, 'SIGQUIT'));
144
+ // kill(15) default
145
+ process.once('SIGTERM', this.onSignal.bind(this, 'SIGTERM'));
146
+ process.once('exit', this.onExit.bind(this));
147
+ // write pid to file if provided
148
+ if (this.options.pidFile) {
149
+ fs.mkdirSync(path.dirname(this.options.pidFile), { recursive: true });
150
+ fs.writeFileSync(this.options.pidFile, process.pid.toString(), 'utf-8');
151
+ }
152
+ this.detectPorts()
153
+ .then(() => {
154
+ this.forkAgentWorker();
155
+ });
156
+ // exit when agent or worker exception
157
+ this.workerManager.on('exception', (count) => {
158
+ const err = new ClusterWorkerExceptionError(count.agent, count.worker);
159
+ this.logger.error(err);
160
+ process.exit(1);
161
+ });
162
+ }
163
+ startByProcess() {
164
+ this.agentWorker = new ProcessAgentWorker(this.options, {
165
+ log: this.log.bind(this),
166
+ logger: this.logger,
167
+ messenger: this.messenger,
168
+ });
169
+ this.appWorker = new ProcessAppWorker(this.options, {
170
+ log: this.log.bind(this),
171
+ logger: this.logger,
172
+ messenger: this.messenger,
173
+ isProduction: this.isProduction,
174
+ });
175
+ }
176
+ startByWorkerThreads() {
177
+ this.agentWorker = new WorkerThreadsAgentWorker(this.options, {
178
+ log: this.log.bind(this),
179
+ logger: this.logger,
180
+ messenger: this.messenger,
181
+ });
182
+ this.appWorker = new WorkerThreadsAppWorker(this.options, {
183
+ log: this.log.bind(this),
184
+ logger: this.logger,
185
+ messenger: this.messenger,
186
+ isProduction: this.isProduction,
187
+ });
188
+ }
189
+ async detectPorts() {
190
+ // Detect cluster client port
191
+ try {
192
+ const clusterPort = await detectPort();
193
+ this.options.clusterPort = clusterPort;
194
+ // If sticky mode, detect worker port
195
+ if (this.options.sticky) {
196
+ const stickyWorkerPort = await detectPort();
197
+ this.options.stickyWorkerPort = stickyWorkerPort;
198
+ }
199
+ }
200
+ catch (err) {
201
+ this.logger.error(err);
202
+ process.exit(1);
203
+ }
204
+ }
205
+ log(msg, ...args) {
206
+ this.logger[this.#logMethod](msg, ...args);
207
+ }
208
+ startMasterSocketServer(cb) {
209
+ // Create the outside facing server listening on our port.
210
+ net.createServer({
211
+ pauseOnConnect: true,
212
+ }, connection => {
213
+ // We received a connection and need to pass it to the appropriate
214
+ // worker. Get the worker for this connection's source IP and pass
215
+ // it the connection.
216
+ /* istanbul ignore next */
217
+ if (!connection.remoteAddress) {
218
+ // This will happen when a client sends an RST(which is set to 1) right
219
+ // after the three-way handshake to the server.
220
+ // Read https://en.wikipedia.org/wiki/TCP_reset_attack for more details.
221
+ connection.destroy();
222
+ }
223
+ else {
224
+ const worker = this.stickyWorker(connection.remoteAddress);
225
+ worker.instance.send('sticky-session:connection', connection);
226
+ }
227
+ }).listen(this.#realPort, cb);
228
+ }
229
+ stickyWorker(ip) {
230
+ const workerNumbers = this.options.workers;
231
+ const ws = this.workerManager.listWorkerIds();
232
+ let s = '';
233
+ for (let i = 0; i < ip.length; i++) {
234
+ if (!isNaN(parseInt(ip[i]))) {
235
+ s += ip[i];
236
+ }
237
+ }
238
+ const pid = ws[Number(s) % workerNumbers];
239
+ return this.workerManager.getWorker(pid);
240
+ }
241
+ forkAgentWorker() {
242
+ this.agentWorker.on('agent_forked', (agent) => {
243
+ this.workerManager.setAgent(agent);
244
+ });
245
+ this.agentWorker.fork();
246
+ }
247
+ forkAppWorkers() {
248
+ this.appWorker.on('worker_forked', (worker) => {
249
+ this.workerManager.setWorker(worker);
250
+ });
251
+ this.appWorker.fork();
252
+ }
253
+ /**
254
+ * close agent worker, App Worker will closed by cluster
255
+ *
256
+ * https://www.exratione.com/2013/05/die-child-process-die/
257
+ * make sure Agent Worker exit before master exit
258
+ *
259
+ * @param {number} timeout - kill agent timeout
260
+ * @return {Promise} -
261
+ */
262
+ async killAgentWorker(timeout) {
263
+ await this.agentWorker.kill(timeout);
264
+ }
265
+ async killAppWorkers(timeout) {
266
+ await this.appWorker.kill(timeout);
267
+ }
268
+ /**
269
+ * Agent Worker exit handler
270
+ * Will exit during startup, and refork during running.
271
+ */
272
+ onAgentExit(data) {
273
+ if (this.closed)
274
+ return;
275
+ this.messenger.send({
276
+ action: 'egg-pids',
277
+ to: 'app',
278
+ data: [],
279
+ });
280
+ const agentWorker = this.agentWorker;
281
+ this.workerManager.deleteAgent();
282
+ const err = new Error(util.format('[master] agent_worker#%s:%s died (code: %s, signal: %s)', agentWorker.instance.id, agentWorker.instance.workerId, data.code, data.signal));
283
+ err.name = 'AgentWorkerDiedError';
284
+ this.logger.error(err);
285
+ // remove all listeners to avoid memory leak
286
+ agentWorker.clean();
287
+ if (this.isStarted) {
288
+ this.log('[master] try to start a new agent_worker after 1s ...');
289
+ setTimeout(() => {
290
+ this.logger.info('[master] new agent_worker starting...');
291
+ this.forkAgentWorker();
292
+ }, 1000);
293
+ this.messenger.send({
294
+ action: 'agent-worker-died',
295
+ to: 'parent',
296
+ });
297
+ }
298
+ else {
299
+ this.logger.error('[master] agent_worker#%s:%s start fail, exiting with code:1', agentWorker.instance.id, agentWorker.instance.workerId);
300
+ process.exit(1);
301
+ }
302
+ }
303
+ onAgentStart() {
304
+ this.agentWorker.instance.status = 'started';
305
+ // Send egg-ready when agent is started after launched
306
+ if (this.appWorker.isAllWorkerStarted) {
307
+ this.messenger.send({
308
+ action: 'egg-ready',
309
+ to: 'agent',
310
+ data: this.options,
311
+ });
312
+ }
313
+ this.messenger.send({
314
+ action: 'egg-pids',
315
+ to: 'app',
316
+ data: [this.agentWorker.instance.workerId],
317
+ });
318
+ // should send current worker pids when agent restart
319
+ if (this.isStarted) {
320
+ this.messenger.send({
321
+ action: 'egg-pids',
322
+ to: 'agent',
323
+ data: this.workerManager.getListeningWorkerIds(),
324
+ });
325
+ }
326
+ this.messenger.send({
327
+ action: 'agent-start',
328
+ to: 'app',
329
+ });
330
+ this.logger.info('[master] agent_worker#%s:%s started (%sms)', this.agentWorker.instance.id, this.agentWorker.instance.workerId, Date.now() - this.agentWorker.startTime);
331
+ }
332
+ /**
333
+ * App Worker exit handler
334
+ */
335
+ onAppExit(data) {
336
+ if (this.closed)
337
+ return;
338
+ const worker = this.workerManager.getWorker(data.workerId);
339
+ if (!worker.isDevReload) {
340
+ const signal = data.signal;
341
+ const message = util.format('[master] app_worker#%s:%s died (code: %s, signal: %s, suicide: %s, state: %s), current workers: %j', worker.id, worker.workerId, worker.exitCode, signal, worker.exitedAfterDisconnect, worker.state, this.workerManager.listWorkerIds());
342
+ if (this.options.isDebug && signal === 'SIGKILL') {
343
+ // exit if died during debug
344
+ this.logger.error(message);
345
+ this.logger.error('[master] worker kill by debugger, exiting...');
346
+ setTimeout(() => this.close(), 10);
347
+ }
348
+ else {
349
+ const err = new Error(message);
350
+ err.name = 'AppWorkerDiedError';
351
+ this.logger.error(err);
352
+ }
353
+ }
354
+ // remove all listeners to avoid memory leak
355
+ worker.clean();
356
+ this.workerManager.deleteWorker(data.workerId);
357
+ // send message to agent with alive workers
358
+ this.messenger.send({
359
+ action: 'egg-pids',
360
+ to: 'agent',
361
+ data: this.workerManager.getListeningWorkerIds(),
362
+ });
363
+ if (this.appWorker.isAllWorkerStarted) {
364
+ // cfork will only refork at production mode
365
+ this.messenger.send({
366
+ action: 'app-worker-died',
367
+ to: 'parent',
368
+ });
369
+ }
370
+ else {
371
+ // exit if died during startup
372
+ this.logger.error('[master] app_worker#%s:%s start fail, exiting with code:1', worker.id, worker.workerId);
373
+ process.exit(1);
374
+ }
375
+ }
376
+ /**
377
+ * after app worker
378
+ */
379
+ onAppStart(data) {
380
+ const address = data.address;
381
+ // worker should listen stickyWorkerPort when sticky mode
382
+ if (this.options.sticky) {
383
+ if (String(address.port) !== String(this.options.stickyWorkerPort)) {
384
+ return;
385
+ }
386
+ // worker should listen REALPORT when not sticky mode
387
+ }
388
+ else if (this.options.startMode !== 'worker_threads' &&
389
+ !isUnixSock(address) &&
390
+ (String(address.port) !== String(this.#realPort))) {
391
+ return;
392
+ }
393
+ // send message to agent with alive workers
394
+ this.messenger.send({
395
+ action: 'egg-pids',
396
+ to: 'agent',
397
+ data: this.workerManager.getListeningWorkerIds(),
398
+ });
399
+ this.appWorker.startSuccessCount++;
400
+ const worker = this.workerManager.getWorker(data.workerId);
401
+ const remain = this.appWorker.isAllWorkerStarted ? 0 : this.options.workers - this.appWorker.startSuccessCount;
402
+ this.log('[master] app_worker#%s:%s started at %s, remain %s (%sms)', worker.id, worker.workerId, address.port, remain, Date.now() - this.appWorker.startTime);
403
+ // Send egg-ready when app is started after launched
404
+ if (this.appWorker.isAllWorkerStarted) {
405
+ this.messenger.send({
406
+ action: 'egg-ready',
407
+ to: 'app',
408
+ data: this.options,
409
+ });
410
+ }
411
+ // if app is started, it should enable this worker
412
+ if (this.appWorker.isAllWorkerStarted) {
413
+ worker.disableRefork = false;
414
+ }
415
+ if (this.appWorker.isAllWorkerStarted || this.appWorker.startSuccessCount < this.options.workers) {
416
+ return;
417
+ }
418
+ this.appWorker.isAllWorkerStarted = true;
419
+ // enable all workers when app started
420
+ for (const worker of this.workerManager.listWorkers()) {
421
+ worker.disableRefork = false;
422
+ }
423
+ address.protocol = this.#protocol;
424
+ address.port = this.options.sticky ? this.#realPort : address.port;
425
+ this.#appAddress = getAddress(address);
426
+ if (this.options.sticky) {
427
+ this.startMasterSocketServer(err => {
428
+ if (err) {
429
+ return this.ready(err);
430
+ }
431
+ this.ready(true);
432
+ });
433
+ }
434
+ else {
435
+ this.ready(true);
436
+ }
437
+ }
438
+ /**
439
+ * master exit handler
440
+ */
441
+ onExit(code) {
442
+ if (this.options.pidFile && fs.existsSync(this.options.pidFile)) {
443
+ try {
444
+ fs.unlinkSync(this.options.pidFile);
445
+ }
446
+ catch (err) {
447
+ /* istanbul ignore next */
448
+ this.logger.error('[master] delete pidFile %s fail with %s', this.options.pidFile, err.message);
449
+ }
450
+ }
451
+ // istanbul can't cover here
452
+ // https://github.com/gotwarlost/istanbul/issues/567
453
+ const level = code === 0 ? 'info' : 'error';
454
+ this.logger[level]('[master] exit with code:%s', code);
455
+ }
456
+ onSignal(signal) {
457
+ if (this.closed)
458
+ return;
459
+ this.logger.info('[master] master is killed by signal %s, closing', signal);
460
+ // logger more info
461
+ const { used_heap_size, heap_size_limit } = v8.getHeapStatistics();
462
+ this.logger.info('[master] system memory: total %s, free %s', os.totalmem(), os.freemem());
463
+ this.logger.info('[master] process info: heap_limit %s, heap_used %s', heap_size_limit, used_heap_size);
464
+ this.close();
465
+ }
466
+ /**
467
+ * reload workers, for develop purpose
468
+ */
469
+ onReload() {
470
+ this.log('[master] reload %s workers...', this.options.workers);
471
+ for (const worker of this.workerManager.listWorkers()) {
472
+ worker.isDevReload = true;
473
+ }
474
+ reload(this.options.workers);
475
+ }
476
+ async close() {
477
+ this.closed = true;
478
+ try {
479
+ await this._doClose();
480
+ this.log('[master] close done, exiting with code:0');
481
+ process.exit(0);
482
+ }
483
+ catch (e) {
484
+ this.logger.error('[master] close with error: ', e);
485
+ process.exit(1);
486
+ }
487
+ }
488
+ async _doClose() {
489
+ // kill app workers
490
+ // kill agent worker
491
+ // exit itself
492
+ const legacyTimeout = process.env.EGG_MASTER_CLOSE_TIMEOUT || '5000';
493
+ const appTimeout = parseInt(process.env.EGG_APP_CLOSE_TIMEOUT || legacyTimeout);
494
+ const agentTimeout = parseInt(process.env.EGG_AGENT_CLOSE_TIMEOUT || legacyTimeout);
495
+ this.logger.info('[master] send kill SIGTERM to app workers, will exit with code:0 after %sms', appTimeout);
496
+ this.logger.info('[master] wait %sms', appTimeout);
497
+ try {
498
+ await this.killAppWorkers(appTimeout);
499
+ }
500
+ catch (e) {
501
+ this.logger.error('[master] app workers exit error: ', e);
502
+ }
503
+ this.logger.info('[master] send kill SIGTERM to agent worker, will exit with code:0 after %sms', agentTimeout);
504
+ this.logger.info('[master] wait %sms', agentTimeout);
505
+ try {
506
+ await this.killAgentWorker(agentTimeout);
507
+ }
508
+ catch (e) /* istanbul ignore next */ {
509
+ this.logger.error('[master] agent worker exit error: ', e);
510
+ }
511
+ }
512
+ }
513
+ function isProduction(options) {
514
+ if (options.env) {
515
+ return options.env !== 'local' && options.env !== 'unittest';
516
+ }
517
+ return process.env.NODE_ENV === 'production';
518
+ }
519
+ function getAddress({ addressType, address, port, protocol, }) {
520
+ // unix sock
521
+ // https://nodejs.org/api/cluster.html#cluster_event_listening_1
522
+ if (addressType === -1) {
523
+ return address;
524
+ }
525
+ let hostname = address;
526
+ if (!hostname && process.env.HOST && process.env.HOST !== '0.0.0.0') {
527
+ hostname = process.env.HOST;
528
+ }
529
+ if (!hostname) {
530
+ hostname = '127.0.0.1';
531
+ }
532
+ return `${protocol}://${hostname}:${port}`;
533
+ }
534
+ function isUnixSock(address) {
535
+ return address.addressType === -1;
536
+ }
537
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFzdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21hc3Rlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDekIsT0FBTyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3pCLE9BQU8sSUFBSSxNQUFNLFdBQVcsQ0FBQztBQUM3QixPQUFPLElBQUksTUFBTSxXQUFXLENBQUM7QUFDN0IsT0FBTyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3pCLE9BQU8sR0FBRyxNQUFNLFVBQVUsQ0FBQztBQUMzQixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDOUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN6QyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEMsT0FBTyxFQUFFLGdCQUFnQixJQUFJLGFBQWEsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUMvRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3ZDLE9BQU8sWUFBWSxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQUUsWUFBWSxFQUF3QyxNQUFNLG9CQUFvQixDQUFDO0FBQ3hGLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDakQsT0FBTyxFQUNlLGlCQUFpQixJQUFJLGtCQUFrQixHQUM1RCxNQUFNLG9DQUFvQyxDQUFDO0FBQzVDLE9BQU8sRUFBb0IsZUFBZSxJQUFJLGdCQUFnQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFDekcsT0FBTyxFQUNjLGdCQUFnQixJQUFJLHdCQUF3QixHQUNoRSxNQUFNLDJDQUEyQyxDQUFDO0FBQ25ELE9BQU8sRUFBbUIsY0FBYyxJQUFJLHNCQUFzQixFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFDcEgsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0sd0NBQXdDLENBQUM7QUFPckYsTUFBTSxPQUFPLE1BQU8sU0FBUSxpQkFBaUI7SUFDM0MsT0FBTyxDQUFnQjtJQUN2QixTQUFTLEdBQUcsS0FBSyxDQUFDO0lBQ2xCLGFBQWEsQ0FBZ0I7SUFDN0IsU0FBUyxDQUFZO0lBQ3JCLFlBQVksQ0FBVTtJQUN0QixnQkFBZ0IsR0FBRyxDQUFDLENBQUM7SUFDckIsTUFBTSxHQUFHLEtBQUssQ0FBQztJQUNmLE1BQU0sQ0FBZ0I7SUFDdEIsV0FBVyxDQUFnRDtJQUMzRCxTQUFTLENBQTRDO0lBQ3JELFVBQVUsQ0FBbUI7SUFDN0IsU0FBUyxDQUFVO0lBQ25CLFNBQVMsQ0FBUztJQUNsQixXQUFXLENBQVM7SUFFcEIsWUFBWSxPQUF3QjtRQUNsQyxLQUFLLEVBQUUsQ0FBQztRQUNSLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDO2FBQ2pCLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRTtZQUNYLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDbEIsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQsS0FBSyxDQUFDLE1BQU0sQ0FBQyxPQUF3QjtRQUNuQyxJQUFJLENBQUMsT0FBTyxHQUFHLE1BQU0sWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzNDLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxhQUFhLEVBQUUsQ0FBQztRQUN6QyxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksU0FBUyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDekQsSUFBSSxDQUFDLFlBQVksR0FBRyxZQUFZLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQy9DLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUM7UUFDbkMsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7UUFFdkQscUJBQXFCO1FBQ3JCLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxhQUFhLENBQUMsRUFBRSxLQUFLLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyx1QkFBdUIsSUFBSSxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQzFGLElBQUksQ0FBQyxVQUFVLEdBQUcsTUFBTSxDQUFDO1FBQ3pCLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEtBQUssT0FBTyxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxLQUFLLGFBQWEsRUFBRSxDQUFDO1lBQzNFLElBQUksQ0FBQyxVQUFVLEdBQUcsT0FBTyxDQUFDO1FBQzVCLENBQUM7UUFFRCw4QkFBOEI7UUFDOUIsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUM7UUFDN0MsTUFBTSxZQUFZLEdBQUcsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLGNBQWMsQ0FBQyxDQUFDLENBQUM7UUFFNUUsOEJBQThCO1FBQzlCLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEtBQUssZ0JBQWdCLEVBQUUsQ0FBQztZQUNoRCxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztRQUM5QixDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN4QixDQUFDO1FBRUQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxnQ0FBZ0MsWUFBWSxDQUFDLElBQUksOEJBQThCLENBQUMsQ0FBQztRQUMxRixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyx5QkFBeUIsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDN0QsMEJBQTBCO1FBQzFCLElBQUksU0FBUyxJQUFJLE9BQU8sRUFBRSxDQUFDO1lBQ3pCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLDRCQUE0QixPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUNsRSxDQUFDO1FBQ0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsWUFBWSxZQUFZLENBQUMsSUFBSSxZQUFZLFlBQVksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBRWxGLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3RCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGtDQUFrQyxFQUNqRCxFQUFFLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNuRCxDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksQ0FBQyxHQUFHLENBQUMsaUNBQWlDLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzVELENBQUM7UUFDRCxJQUFJLENBQUMsR0FBRyxDQUFDLDZFQUE2RSxFQUNwRixJQUFJLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFN0QsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBRTdCLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFO1lBQ2QsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7WUFDdEIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLG9CQUFvQixDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDbEUsTUFBTSxVQUFVLEdBQUcsWUFBWSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLFdBQVcsRUFBRSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1lBQ3pGLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLG9DQUFvQyxFQUNuRCxZQUFZLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQ3BFLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDM0IsTUFBTSxHQUFHLEdBQUcsVUFBVSxDQUFDO29CQUNyQixJQUFJLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTO29CQUM1QixRQUFRLEVBQUUsTUFBTTtpQkFDakIsQ0FBQyxDQUFDO2dCQUNILE1BQU0sWUFBWSxHQUFHLFlBQVksQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7Z0JBQ2pFLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLHNDQUFzQyxFQUFFLFlBQVksQ0FBQyxJQUFJLEVBQUUsWUFBWSxDQUFDLENBQUM7WUFDNUYsQ0FBQztZQUVELE1BQU0sTUFBTSxHQUFHLFdBQVcsQ0FBQztZQUMzQixJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQztnQkFDbEIsTUFBTTtnQkFDTixFQUFFLEVBQUUsUUFBUTtnQkFDWixJQUFJLEVBQUU7b0JBQ0osSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTO29CQUNwQixTQUFTLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTO29CQUNqQyxPQUFPLEVBQUUsSUFBSSxDQUFDLFdBQVc7b0JBQ3pCLFFBQVEsRUFBRSxJQUFJLENBQUMsU0FBUztpQkFDekI7YUFDRixDQUFDLENBQUM7WUFDSCxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQztnQkFDbEIsTUFBTTtnQkFDTixFQUFFLEVBQUUsS0FBSztnQkFDVCxJQUFJLEVBQUUsSUFBSSxDQUFDLE9BQU87YUFDbkIsQ0FBQyxDQUFDO1lBQ0gsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUM7Z0JBQ2xCLE1BQU07Z0JBQ04sRUFBRSxFQUFFLE9BQU87Z0JBQ1gsSUFBSSxFQUFFLElBQUksQ0FBQyxPQUFPO2FBQ25CLENBQUMsQ0FBQztZQUVILHNDQUFzQztZQUN0QyxJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztnQkFDdEIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNsQyxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsRUFBRSxDQUFDLFlBQVksRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ25ELElBQUksQ0FBQyxFQUFFLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDckQsSUFBSSxDQUFDLEVBQUUsQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUMvQyxJQUFJLENBQUMsRUFBRSxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ2pELElBQUksQ0FBQyxFQUFFLENBQUMsZUFBZSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFHbkQsdUNBQXVDO1FBQ3ZDLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDekQsZ0RBQWdEO1FBQ2hELHFDQUFxQztRQUNyQyxJQUFJLENBQUMsRUFBRSxDQUFDLFVBQVUsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUFFLEVBQUU7WUFDekMsSUFBSSxJQUFJLEVBQUUsQ0FBQztnQkFDVCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztZQUN4QixDQUFDO1lBQ0QsSUFBSSxRQUFRLEVBQUUsQ0FBQztnQkFDYixJQUFJLENBQUMsU0FBUyxHQUFHLFFBQVEsQ0FBQztZQUM1QixDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7UUFFSCw0REFBNEQ7UUFDNUQsNENBQTRDO1FBQzVDLGlCQUFpQjtRQUNqQixPQUFPLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQztRQUMzRCxpQkFBaUI7UUFDakIsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUM7UUFDN0QsbUJBQW1CO1FBQ25CLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDO1FBRTdELE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFFN0MsZ0NBQWdDO1FBQ2hDLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUN6QixFQUFFLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1lBQ3RFLEVBQUUsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUMxRSxDQUFDO1FBRUQsSUFBSSxDQUFDLFdBQVcsRUFBRTthQUNmLElBQUksQ0FBQyxHQUFHLEVBQUU7WUFDVCxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7UUFDekIsQ0FBQyxDQUFDLENBQUM7UUFFTCxzQ0FBc0M7UUFDdEMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUMsS0FHbkMsRUFBRSxFQUFFO1lBQ0gsTUFBTSxHQUFHLEdBQUcsSUFBSSwyQkFBMkIsQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUN2RSxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN2QixPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xCLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELGNBQWM7UUFDWixJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksa0JBQWtCLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUN0RCxHQUFHLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO1lBQ3hCLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTTtZQUNuQixTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7U0FDMUIsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLGdCQUFnQixDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDbEQsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztZQUN4QixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07WUFDbkIsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTO1lBQ3pCLFlBQVksRUFBRSxJQUFJLENBQUMsWUFBWTtTQUNoQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsb0JBQW9CO1FBQ2xCLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQzVELEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7WUFDeEIsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO1lBQ25CLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUztTQUMxQixDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksc0JBQXNCLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUN4RCxHQUFHLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO1lBQ3hCLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTTtZQUNuQixTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7WUFDekIsWUFBWSxFQUFFLElBQUksQ0FBQyxZQUFZO1NBQ2hDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxLQUFLLENBQUMsV0FBVztRQUNmLDZCQUE2QjtRQUM3QixJQUFJLENBQUM7WUFDSCxNQUFNLFdBQVcsR0FBRyxNQUFNLFVBQVUsRUFBRSxDQUFDO1lBQ3ZDLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztZQUN2QyxxQ0FBcUM7WUFDckMsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUN4QixNQUFNLGdCQUFnQixHQUFHLE1BQU0sVUFBVSxFQUFFLENBQUM7Z0JBQzVDLElBQUksQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLEdBQUcsZ0JBQWdCLENBQUM7WUFDbkQsQ0FBQztRQUNILENBQUM7UUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1lBQ2IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDdkIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNsQixDQUFDO0lBQ0gsQ0FBQztJQUVELEdBQUcsQ0FBQyxHQUFXLEVBQUUsR0FBRyxJQUFXO1FBQzdCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFFRCx1QkFBdUIsQ0FBQyxFQUF5QjtRQUMvQywwREFBMEQ7UUFDMUQsR0FBRyxDQUFDLFlBQVksQ0FBQztZQUNmLGNBQWMsRUFBRSxJQUFJO1NBQ3JCLEVBQUUsVUFBVSxDQUFDLEVBQUU7WUFDZCxrRUFBa0U7WUFDbEUsa0VBQWtFO1lBQ2xFLHFCQUFxQjtZQUVyQiwwQkFBMEI7WUFDMUIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLEVBQUUsQ0FBQztnQkFDOUIsdUVBQXVFO2dCQUN2RSwrQ0FBK0M7Z0JBQy9DLHdFQUF3RTtnQkFDeEUsVUFBVSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3ZCLENBQUM7aUJBQU0sQ0FBQztnQkFDTixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQXFCLENBQUM7Z0JBQy9FLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLDJCQUEyQixFQUFFLFVBQVUsQ0FBQyxDQUFDO1lBQ2hFLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNoQyxDQUFDO0lBRUQsWUFBWSxDQUFDLEVBQVU7UUFDckIsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUM7UUFDM0MsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUU5QyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDWCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ25DLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDNUIsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNiLENBQUM7UUFDSCxDQUFDO1FBQ0QsTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxhQUFhLENBQUMsQ0FBQztRQUMxQyxPQUFPLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBRSxDQUFDO0lBQzVDLENBQUM7SUFFRCxlQUFlO1FBQ2IsSUFBSSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsY0FBYyxFQUFFLENBQUMsS0FBNkMsRUFBRSxFQUFFO1lBQ3BGLElBQUksQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3JDLENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUMxQixDQUFDO0lBRUQsY0FBYztRQUNaLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLGVBQWUsRUFBRSxDQUFDLE1BQTBDLEVBQUUsRUFBRTtZQUNoRixJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN2QyxDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDeEIsQ0FBQztJQUVEOzs7Ozs7OztPQVFHO0lBQ0gsS0FBSyxDQUFDLGVBQWUsQ0FBQyxPQUFlO1FBQ25DLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUVELEtBQUssQ0FBQyxjQUFjLENBQUMsT0FBZTtRQUNsQyxNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFFRDs7O09BR0c7SUFDSCxXQUFXLENBQUMsSUFLWDtRQUNDLElBQUksSUFBSSxDQUFDLE1BQU07WUFBRSxPQUFPO1FBRXhCLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDO1lBQ2xCLE1BQU0sRUFBRSxVQUFVO1lBQ2xCLEVBQUUsRUFBRSxLQUFLO1lBQ1QsSUFBSSxFQUFFLEVBQUU7U0FDVCxDQUFDLENBQUM7UUFDSCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxhQUFhLENBQUMsV0FBVyxFQUFFLENBQUM7UUFFakMsTUFBTSxHQUFHLEdBQUcsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyx5REFBeUQsRUFDekYsV0FBVyxDQUFDLFFBQVEsQ0FBQyxFQUFFLEVBQUUsV0FBVyxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztRQUNuRixHQUFHLENBQUMsSUFBSSxHQUFHLHNCQUFzQixDQUFDO1FBQ2xDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRXZCLDRDQUE0QztRQUM1QyxXQUFXLENBQUMsS0FBSyxFQUFFLENBQUM7UUFFcEIsSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDbkIsSUFBSSxDQUFDLEdBQUcsQ0FBQyx1REFBdUQsQ0FBQyxDQUFDO1lBQ2xFLFVBQVUsQ0FBQyxHQUFHLEVBQUU7Z0JBQ2QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsdUNBQXVDLENBQUMsQ0FBQztnQkFDMUQsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ3pCLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUNULElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDO2dCQUNsQixNQUFNLEVBQUUsbUJBQW1CO2dCQUMzQixFQUFFLEVBQUUsUUFBUTthQUNiLENBQUMsQ0FBQztRQUNMLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsNkRBQTZELEVBQzdFLFdBQVcsQ0FBQyxRQUFRLENBQUMsRUFBRSxFQUFFLFdBQVcsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDMUQsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNsQixDQUFDO0lBQ0gsQ0FBQztJQUVELFlBQVk7UUFDVixJQUFJLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDO1FBRTdDLHNEQUFzRDtRQUN0RCxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztZQUN0QyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQztnQkFDbEIsTUFBTSxFQUFFLFdBQVc7Z0JBQ25CLEVBQUUsRUFBRSxPQUFPO2dCQUNYLElBQUksRUFBRSxJQUFJLENBQUMsT0FBTzthQUNuQixDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUM7WUFDbEIsTUFBTSxFQUFFLFVBQVU7WUFDbEIsRUFBRSxFQUFFLEtBQUs7WUFDVCxJQUFJLEVBQUUsQ0FBRSxJQUFJLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUU7U0FDN0MsQ0FBQyxDQUFDO1FBQ0gscURBQXFEO1FBQ3JELElBQUksSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ25CLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDO2dCQUNsQixNQUFNLEVBQUUsVUFBVTtnQkFDbEIsRUFBRSxFQUFFLE9BQU87Z0JBQ1gsSUFBSSxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMscUJBQXFCLEVBQUU7YUFDakQsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDO1lBQ2xCLE1BQU0sRUFBRSxhQUFhO1lBQ3JCLEVBQUUsRUFBRSxLQUFLO1NBQ1YsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsNENBQTRDLEVBQzNELElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDL0csQ0FBQztJQUVEOztPQUVHO0lBQ0gsU0FBUyxDQUFDLElBSVQ7UUFDQyxJQUFJLElBQUksQ0FBQyxNQUFNO1lBQUUsT0FBTztRQUV4QixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFFLENBQUM7UUFDNUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUN4QixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO1lBQzNCLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQ3pCLG9HQUFvRyxFQUNwRyxNQUFNLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQ25ELE1BQU0sQ0FBQyxxQkFBcUIsRUFBRSxNQUFNLENBQUMsS0FBSyxFQUMxQyxJQUFJLENBQUMsYUFBYSxDQUFDLGFBQWEsRUFBRSxDQUNuQyxDQUFDO1lBQ0YsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sSUFBSSxNQUFNLEtBQUssU0FBUyxFQUFFLENBQUM7Z0JBQ2pELDRCQUE0QjtnQkFDNUIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQzNCLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLDhDQUE4QyxDQUFDLENBQUM7Z0JBQ2xFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDckMsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLE1BQU0sR0FBRyxHQUFHLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUMvQixHQUFHLENBQUMsSUFBSSxHQUFHLG9CQUFvQixDQUFDO2dCQUNoQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN6QixDQUFDO1FBQ0gsQ0FBQztRQUVELDRDQUE0QztRQUM1QyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDZixJQUFJLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDL0MsMkNBQTJDO1FBQzNDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDO1lBQ2xCLE1BQU0sRUFBRSxVQUFVO1lBQ2xCLEVBQUUsRUFBRSxPQUFPO1lBQ1gsSUFBSSxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMscUJBQXFCLEVBQUU7U0FDakQsQ0FBQyxDQUFDO1FBRUgsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDdEMsNENBQTRDO1lBQzVDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDO2dCQUNsQixNQUFNLEVBQUUsaUJBQWlCO2dCQUN6QixFQUFFLEVBQUUsUUFBUTthQUNiLENBQUMsQ0FBQztRQUNMLENBQUM7YUFBTSxDQUFDO1lBQ04sOEJBQThCO1lBQzlCLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLDJEQUEyRCxFQUMzRSxNQUFNLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM5QixPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xCLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxVQUFVLENBQUMsSUFHVjtRQUNDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUM7UUFFN0IseURBQXlEO1FBQ3pELElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUN4QixJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxDQUFDO2dCQUNuRSxPQUFPO1lBQ1QsQ0FBQztZQUNELHFEQUFxRDtRQUN2RCxDQUFDO2FBQU0sSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsS0FBSyxnQkFBZ0I7WUFDcEQsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDO1lBQ3BCLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNwRCxPQUFPO1FBQ1QsQ0FBQztRQUVELDJDQUEyQztRQUMzQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQztZQUNsQixNQUFNLEVBQUUsVUFBVTtZQUNsQixFQUFFLEVBQUUsT0FBTztZQUNYLElBQUksRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLHFCQUFxQixFQUFFO1NBQ2pELENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxTQUFTLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUVuQyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFFLENBQUM7UUFDNUQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLGlCQUFpQixDQUFDO1FBQy9HLElBQUksQ0FBQyxHQUFHLENBQUMsMkRBQTJELEVBQ2xFLE1BQU0sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLFFBQVEsRUFBRSxPQUFPLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFDaEQsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUM7UUFFekMsb0RBQW9EO1FBQ3BELElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1lBQ3RDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDO2dCQUNsQixNQUFNLEVBQUUsV0FBVztnQkFDbkIsRUFBRSxFQUFFLEtBQUs7Z0JBQ1QsSUFBSSxFQUFFLElBQUksQ0FBQyxPQUFPO2FBQ25CLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCxrREFBa0Q7UUFDbEQsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDdEMsTUFBTSxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUM7UUFDL0IsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxrQkFBa0IsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDakcsT0FBTztRQUNULENBQUM7UUFFRCxJQUFJLENBQUMsU0FBUyxDQUFDLGtCQUFrQixHQUFHLElBQUksQ0FBQztRQUV6QyxzQ0FBc0M7UUFDdEMsS0FBSyxNQUFNLE1BQU0sSUFBSSxJQUFJLENBQUMsYUFBYSxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUM7WUFDdEQsTUFBTSxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUM7UUFDL0IsQ0FBQztRQUVELE9BQU8sQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQztRQUNsQyxPQUFPLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBVSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDO1FBQ3BFLElBQUksQ0FBQyxXQUFXLEdBQUcsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRXZDLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUN4QixJQUFJLENBQUMsdUJBQXVCLENBQUMsR0FBRyxDQUFDLEVBQUU7Z0JBQ2pDLElBQUksR0FBRyxFQUFFLENBQUM7b0JBQ1IsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUN6QixDQUFDO2dCQUNELElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDbkIsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDbkIsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBQyxJQUFZO1FBQ2pCLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLElBQUksRUFBRSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDaEUsSUFBSSxDQUFDO2dCQUNILEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN0QyxDQUFDO1lBQUMsT0FBTyxHQUFRLEVBQUUsQ0FBQztnQkFDbEIsMEJBQTBCO2dCQUMxQixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyx5Q0FBeUMsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDbEcsQ0FBQztRQUNILENBQUM7UUFDRCw0QkFBNEI7UUFDNUIsb0RBQW9EO1FBQ3BELE1BQU0sS0FBSyxHQUFHLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO1FBQzVDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsNEJBQTRCLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDekQsQ0FBQztJQUVELFFBQVEsQ0FBQyxNQUFjO1FBQ3JCLElBQUksSUFBSSxDQUFDLE1BQU07WUFBRSxPQUFPO1FBRXhCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGlEQUFpRCxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQzVFLG1CQUFtQjtRQUNuQixNQUFNLEVBQUUsY0FBYyxFQUFFLGVBQWUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQ25FLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLDJDQUEyQyxFQUFFLEVBQUUsQ0FBQyxRQUFRLEVBQUUsRUFBRSxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUMzRixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxvREFBb0QsRUFBRSxlQUFlLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFFeEcsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ2YsQ0FBQztJQUVEOztPQUVHO0lBQ0gsUUFBUTtRQUNOLElBQUksQ0FBQyxHQUFHLENBQUMsK0JBQStCLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNoRSxLQUFLLE1BQU0sTUFBTSxJQUFJLElBQUksQ0FBQyxhQUFhLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQztZQUN0RCxNQUFNLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQztRQUM1QixDQUFDO1FBQ0QsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDL0IsQ0FBQztJQUVELEtBQUssQ0FBQyxLQUFLO1FBQ1QsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUM7UUFDbkIsSUFBSSxDQUFDO1lBQ0gsTUFBTSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDdEIsSUFBSSxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsQ0FBQyxDQUFDO1lBQ3JELE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbEIsQ0FBQztRQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDWCxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyw2QkFBNkIsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUNwRCxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xCLENBQUM7SUFDSCxDQUFDO0lBRUQsS0FBSyxDQUFDLFFBQVE7UUFDWixtQkFBbUI7UUFDbkIsb0JBQW9CO1FBQ3BCLGNBQWM7UUFDZCxNQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLHdCQUF3QixJQUFJLE1BQU0sQ0FBQztRQUNyRSxNQUFNLFVBQVUsR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxxQkFBcUIsSUFBSSxhQUFhLENBQUMsQ0FBQztRQUNoRixNQUFNLFlBQVksR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyx1QkFBdUIsSUFBSSxhQUFhLENBQUMsQ0FBQztRQUNwRixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyw2RUFBNkUsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUM1RyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUNuRCxJQUFJLENBQUM7WUFDSCxNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDeEMsQ0FBQztRQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDWCxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxtQ0FBbUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUM1RCxDQUFDO1FBQ0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsOEVBQThFLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDL0csSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDckQsSUFBSSxDQUFDO1lBQ0gsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQzNDLENBQUM7UUFBQyxPQUFPLENBQUMsRUFBRSwwQkFBMEIsQ0FBQyxDQUFDO1lBQ3RDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLG9DQUFvQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzdELENBQUM7SUFDSCxDQUFDO0NBQ0Y7QUFFRCxTQUFTLFlBQVksQ0FBQyxPQUF1QjtJQUMzQyxJQUFJLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNoQixPQUFPLE9BQU8sQ0FBQyxHQUFHLEtBQUssT0FBTyxJQUFJLE9BQU8sQ0FBQyxHQUFHLEtBQUssVUFBVSxDQUFDO0lBQy9ELENBQUM7SUFDRCxPQUFPLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxLQUFLLFlBQVksQ0FBQztBQUMvQyxDQUFDO0FBVUQsU0FBUyxVQUFVLENBQUMsRUFDbEIsV0FBVyxFQUNYLE9BQU8sRUFDUCxJQUFJLEVBQ0osUUFBUSxHQUNTO0lBQ2pCLFlBQVk7SUFDWixnRUFBZ0U7SUFDaEUsSUFBSSxXQUFXLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUN2QixPQUFPLE9BQVEsQ0FBQztJQUNsQixDQUFDO0lBRUQsSUFBSSxRQUFRLEdBQUcsT0FBTyxDQUFDO0lBQ3ZCLElBQUksQ0FBQyxRQUFRLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDcEUsUUFBUSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDO0lBQzlCLENBQUM7SUFDRCxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDZCxRQUFRLEdBQUcsV0FBVyxDQUFDO0lBQ3pCLENBQUM7SUFDRCxPQUFPLEdBQUcsUUFBUSxNQUFNLFFBQVEsSUFBSSxJQUFJLEVBQUUsQ0FBQztBQUM3QyxDQUFDO0FBRUQsU0FBUyxVQUFVLENBQUMsT0FBeUI7SUFDM0MsT0FBTyxPQUFPLENBQUMsV0FBVyxLQUFLLENBQUMsQ0FBQyxDQUFDO0FBQ3BDLENBQUMifQ==
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
@@ -0,0 +1,87 @@
1
+ import type { Master } from '../master.js';
2
+ import type { WorkerManager } from './worker_manager.js';
3
+ export type MessageCharacter = 'agent' | 'app' | 'master' | 'parent';
4
+ export interface MessageBody {
5
+ action: string;
6
+ data?: unknown;
7
+ to?: MessageCharacter;
8
+ from?: MessageCharacter;
9
+ receiverPid?: string;
10
+ }
11
+ /**
12
+ * master messenger, provide communication between parent, master, agent and app.
13
+ *
14
+ * ┌────────┐
15
+ * │ parent │
16
+ * /└────────┘\
17
+ * / | \
18
+ * / ┌────────┐ \
19
+ * / │ master │ \
20
+ * / └────────┘ \
21
+ * / / \ \
22
+ * ┌───────┐ ┌───────┐
23
+ * │ agent │ ------- │ app │
24
+ * └───────┘ └───────┘
25
+ *
26
+ *
27
+ * in app worker
28
+ *
29
+ * ```js
30
+ * process.send({
31
+ * action: 'xxx',
32
+ * data: '',
33
+ * to: 'agent/master/parent', // default to agent
34
+ * });
35
+ * ```
36
+ *
37
+ * in agent worker
38
+ *
39
+ * ```js
40
+ * process.send({
41
+ * action: 'xxx',
42
+ * data: '',
43
+ * to: 'app/master/parent', // default to app
44
+ * });
45
+ * ```
46
+ *
47
+ * in parent
48
+ *
49
+ * ```js
50
+ * process.send({
51
+ * action: 'xxx',
52
+ * data: '',
53
+ * to: 'app/agent/master', // default to master
54
+ * });
55
+ * ```
56
+ */
57
+ export declare class Messenger {
58
+ #private;
59
+ constructor(master: Master, workerManager: WorkerManager);
60
+ /**
61
+ * send message
62
+ * @param {Object} data message body
63
+ * - {String} from from who
64
+ * - {String} to to who
65
+ */
66
+ send(data: MessageBody): void;
67
+ /**
68
+ * send message to master self
69
+ * @param {Object} data message body
70
+ */
71
+ sendToMaster(data: MessageBody): void;
72
+ /**
73
+ * send message to parent process
74
+ * @param {Object} data message body
75
+ */
76
+ sendToParent(data: MessageBody): void;
77
+ /**
78
+ * send message to app worker
79
+ * @param {Object} data message body
80
+ */
81
+ sendToAppWorker(data: MessageBody): void;
82
+ /**
83
+ * send message to agent worker
84
+ * @param {Object} data message body
85
+ */
86
+ sendToAgentWorker(data: MessageBody): void;
87
+ }