@eggjs/cluster 4.0.0-beta.34 → 4.0.0-beta.36

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 (35) hide show
  1. package/dist/agent_worker.d.ts +1 -1
  2. package/dist/agent_worker.js +50 -65
  3. package/dist/app_worker.d.ts +1 -1
  4. package/dist/app_worker.js +127 -165
  5. package/dist/error/ClusterAgentWorkerError.d.ts +12 -9
  6. package/dist/error/ClusterAgentWorkerError.js +22 -19
  7. package/dist/error/ClusterWorkerExceptionError.d.ts +9 -6
  8. package/dist/error/ClusterWorkerExceptionError.js +17 -14
  9. package/dist/index.d.ts +20 -15
  10. package/dist/index.js +20 -16
  11. package/dist/master.d.ts +89 -86
  12. package/dist/master.js +425 -556
  13. package/dist/utils/messenger.d.ts +93 -89
  14. package/dist/utils/messenger.js +143 -178
  15. package/dist/utils/mode/base/agent.d.ts +42 -35
  16. package/dist/utils/mode/base/agent.js +63 -65
  17. package/dist/utils/mode/base/app.d.ts +53 -45
  18. package/dist/utils/mode/base/app.js +77 -80
  19. package/dist/utils/mode/impl/process/agent.d.ts +20 -16
  20. package/dist/utils/mode/impl/process/agent.js +95 -105
  21. package/dist/utils/mode/impl/process/app.d.ts +23 -19
  22. package/dist/utils/mode/impl/process/app.js +116 -118
  23. package/dist/utils/mode/impl/worker_threads/agent.d.ts +20 -16
  24. package/dist/utils/mode/impl/worker_threads/agent.js +78 -85
  25. package/dist/utils/mode/impl/worker_threads/app.d.ts +28 -24
  26. package/dist/utils/mode/impl/worker_threads/app.js +128 -137
  27. package/dist/utils/options.d.ts +79 -76
  28. package/dist/utils/options.js +55 -80
  29. package/dist/utils/terminate.js +50 -70
  30. package/dist/utils/worker_manager.d.ts +28 -24
  31. package/dist/utils/worker_manager.js +68 -74
  32. package/package.json +33 -34
  33. package/dist/error/index.d.ts +0 -2
  34. package/dist/error/index.js +0 -3
  35. package/dist/utils/terminate.d.ts +0 -6
@@ -1,86 +1,79 @@
1
- import workerThreads, {} from 'node:worker_threads';
2
- import {} from 'graceful-process';
3
- import { BaseAgentUtils, BaseAgentWorker } from "../../base/agent.js";
4
1
  import { ClusterAgentWorkerError } from "../../../../error/ClusterAgentWorkerError.js";
5
- export class AgentThreadWorker extends BaseAgentWorker {
6
- get workerId() {
7
- return this.instance.threadId;
8
- }
9
- send(message) {
10
- this.instance.postMessage(message);
11
- }
12
- static send(message) {
13
- message.senderWorkerId = String(workerThreads.threadId);
14
- workerThreads.parentPort.postMessage(message);
15
- }
16
- static kill() {
17
- // in worker_threads, process.exit
18
- // does not stop the whole program, just the single thread
19
- process.exit(1);
20
- }
21
- static gracefulExit(options) {
22
- const { beforeExit } = options;
23
- process.on('exit', async (code) => {
24
- if (typeof beforeExit === 'function') {
25
- await beforeExit();
26
- }
27
- process.exit(code);
28
- });
29
- }
30
- }
31
- export class AgentThreadUtils extends BaseAgentUtils {
32
- #worker;
33
- #id = 0;
34
- instance;
35
- fork() {
36
- this.startTime = Date.now();
37
- // start agent worker
38
- const argv = [JSON.stringify(this.options)];
39
- const agentPath = this.getAgentWorkerFile();
40
- const worker = (this.#worker = new workerThreads.Worker(agentPath, {
41
- argv,
42
- }));
43
- // wrap agent worker
44
- const agentWorker = (this.instance = new AgentThreadWorker(worker));
45
- this.emit('agent_forked', agentWorker);
46
- agentWorker.status = 'starting';
47
- agentWorker.id = ++this.#id;
48
- this.log('[master] agent_worker#%s:%s start with worker_threads', agentWorker.id, agentWorker.workerId);
49
- worker.on('message', (msg) => {
50
- if (typeof msg === 'string') {
51
- msg = {
52
- action: msg,
53
- data: msg,
54
- };
55
- }
56
- msg.from = 'agent';
57
- this.messenger.send(msg);
58
- });
59
- worker.on('error', (err) => {
60
- this.logger.error(new ClusterAgentWorkerError(agentWorker.id, agentWorker.workerId, agentWorker.status, err));
61
- });
62
- // agent exit message
63
- worker.once('exit', (code, signal) => {
64
- this.messenger.send({
65
- action: 'agent-exit',
66
- data: {
67
- code,
68
- signal,
69
- },
70
- to: 'master',
71
- from: 'agent',
72
- });
73
- });
74
- }
75
- clean() {
76
- this.#worker.removeAllListeners();
77
- }
78
- async kill() {
79
- if (this.#worker) {
80
- this.log(`[master] kill agent worker#${this.#id} (worker_threads) by worker.terminate()`);
81
- this.clean();
82
- await this.#worker.terminate();
83
- }
84
- }
85
- }
86
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWdlbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvdXRpbHMvbW9kZS9pbXBsL3dvcmtlcl90aHJlYWRzL2FnZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sYUFBYSxFQUFFLEVBQWUsTUFBTSxxQkFBcUIsQ0FBQztBQUVqRSxPQUFPLEVBQXVDLE1BQU0sa0JBQWtCLENBQUM7QUFFdkUsT0FBTyxFQUFFLGNBQWMsRUFBRSxlQUFlLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUV0RSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSw4Q0FBOEMsQ0FBQztBQUV2RixNQUFNLE9BQU8saUJBQWtCLFNBQVEsZUFBdUI7SUFDNUQsSUFBSSxRQUFRO1FBQ1YsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQztJQUNoQyxDQUFDO0lBRUQsSUFBSSxDQUFDLE9BQW9CO1FBQ3ZCLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFFRCxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQW9CO1FBQzlCLE9BQU8sQ0FBQyxjQUFjLEdBQUcsTUFBTSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN4RCxhQUFhLENBQUMsVUFBVyxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNqRCxDQUFDO0lBRUQsTUFBTSxDQUFDLElBQUk7UUFDVCxrQ0FBa0M7UUFDbEMsMERBQTBEO1FBQzFELE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbEIsQ0FBQztJQUVELE1BQU0sQ0FBQyxZQUFZLENBQUMsT0FBNEI7UUFDOUMsTUFBTSxFQUFFLFVBQVUsRUFBRSxHQUFHLE9BQU8sQ0FBQztRQUMvQixPQUFPLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEVBQUU7WUFDaEMsSUFBSSxPQUFP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
2
+ import { BaseAgentUtils, BaseAgentWorker } from "../../base/agent.js";
3
+ import workerThreads from "node:worker_threads";
4
+ import "graceful-process";
5
+
6
+ //#region src/utils/mode/impl/worker_threads/agent.ts
7
+ var AgentThreadWorker = class extends BaseAgentWorker {
8
+ get workerId() {
9
+ return this.instance.threadId;
10
+ }
11
+ send(message) {
12
+ this.instance.postMessage(message);
13
+ }
14
+ static send(message) {
15
+ message.senderWorkerId = String(workerThreads.threadId);
16
+ workerThreads.parentPort.postMessage(message);
17
+ }
18
+ static kill() {
19
+ process.exit(1);
20
+ }
21
+ static gracefulExit(options) {
22
+ const { beforeExit } = options;
23
+ process.on("exit", async (code) => {
24
+ if (typeof beforeExit === "function") await beforeExit();
25
+ process.exit(code);
26
+ });
27
+ }
28
+ };
29
+ var AgentThreadUtils = class extends BaseAgentUtils {
30
+ #worker;
31
+ #id = 0;
32
+ instance;
33
+ fork() {
34
+ this.startTime = Date.now();
35
+ const argv = [JSON.stringify(this.options)];
36
+ const agentPath = this.getAgentWorkerFile();
37
+ const worker = this.#worker = new workerThreads.Worker(agentPath, { argv });
38
+ const agentWorker = this.instance = new AgentThreadWorker(worker);
39
+ this.emit("agent_forked", agentWorker);
40
+ agentWorker.status = "starting";
41
+ agentWorker.id = ++this.#id;
42
+ this.log("[master] agent_worker#%s:%s start with worker_threads", agentWorker.id, agentWorker.workerId);
43
+ worker.on("message", (msg) => {
44
+ if (typeof msg === "string") msg = {
45
+ action: msg,
46
+ data: msg
47
+ };
48
+ msg.from = "agent";
49
+ this.messenger.send(msg);
50
+ });
51
+ worker.on("error", (err) => {
52
+ this.logger.error(new ClusterAgentWorkerError(agentWorker.id, agentWorker.workerId, agentWorker.status, err));
53
+ });
54
+ worker.once("exit", (code, signal) => {
55
+ this.messenger.send({
56
+ action: "agent-exit",
57
+ data: {
58
+ code,
59
+ signal
60
+ },
61
+ to: "master",
62
+ from: "agent"
63
+ });
64
+ });
65
+ }
66
+ clean() {
67
+ this.#worker.removeAllListeners();
68
+ }
69
+ async kill() {
70
+ if (this.#worker) {
71
+ this.log(`[master] kill agent worker#${this.#id} (worker_threads) by worker.terminate()`);
72
+ this.clean();
73
+ await this.#worker.terminate();
74
+ }
75
+ }
76
+ };
77
+
78
+ //#endregion
79
+ export { AgentThreadUtils, AgentThreadWorker };
@@ -1,26 +1,30 @@
1
- import { Worker as ThreadWorker } from 'node:worker_threads';
2
- import type { Options as gracefulExitOptions } from 'graceful-process';
3
- import { BaseAppWorker, BaseAppUtils } from '../../base/app.ts';
4
- import type { MessageBody } from '../../../messenger.ts';
5
- export declare class AppThreadWorker extends BaseAppWorker<ThreadWorker> {
6
- #private;
7
- constructor(instance: ThreadWorker, id: number);
8
- get id(): number;
9
- get workerId(): number;
10
- get state(): string;
11
- set state(val: string);
12
- get exitedAfterDisconnect(): boolean;
13
- get exitCode(): number;
14
- send(message: MessageBody): void;
15
- clean(): void;
16
- static get workerId(): number;
17
- static on(event: string, listener: (...args: any[]) => void): void;
18
- static send(message: MessageBody): void;
19
- static kill(): void;
20
- static gracefulExit(options: gracefulExitOptions): void;
1
+ import { BaseAppUtils, BaseAppWorker } from "../../base/app.js";
2
+ import { MessageBody } from "../../../messenger.js";
3
+ import { Worker } from "node:worker_threads";
4
+ import { Options } from "graceful-process";
5
+
6
+ //#region src/utils/mode/impl/worker_threads/app.d.ts
7
+ declare class AppThreadWorker extends BaseAppWorker<Worker> {
8
+ #private;
9
+ constructor(instance: Worker, id: number);
10
+ get id(): number;
11
+ get workerId(): number;
12
+ get state(): string;
13
+ set state(val: string);
14
+ get exitedAfterDisconnect(): boolean;
15
+ get exitCode(): number;
16
+ send(message: MessageBody): void;
17
+ clean(): void;
18
+ static get workerId(): number;
19
+ static on(event: string, listener: (...args: any[]) => void): void;
20
+ static send(message: MessageBody): void;
21
+ static kill(): void;
22
+ static gracefulExit(options: Options): void;
21
23
  }
22
- export declare class AppThreadUtils extends BaseAppUtils {
23
- #private;
24
- fork(): this;
25
- kill(): Promise<void>;
24
+ declare class AppThreadUtils extends BaseAppUtils {
25
+ #private;
26
+ fork(): this;
27
+ kill(): Promise<void>;
26
28
  }
29
+ //#endregion
30
+ export { AppThreadUtils, AppThreadWorker };
@@ -1,137 +1,128 @@
1
- import { setTimeout as sleep } from 'node:timers/promises';
2
- import { Worker as ThreadWorker, threadId, parentPort } from 'node:worker_threads';
3
- import { BaseAppWorker, BaseAppUtils } from "../../base/app.js";
4
- export class AppThreadWorker extends BaseAppWorker {
5
- #state = 'none';
6
- #id;
7
- constructor(instance, id) {
8
- super(instance);
9
- this.#id = id;
10
- }
11
- get id() {
12
- return this.#id;
13
- }
14
- get workerId() {
15
- return this.instance.threadId;
16
- }
17
- get state() {
18
- return this.#state;
19
- }
20
- set state(val) {
21
- this.#state = val;
22
- }
23
- get exitedAfterDisconnect() {
24
- return true;
25
- }
26
- get exitCode() {
27
- return 0;
28
- // return this.instance.exitCode;
29
- }
30
- send(message) {
31
- this.instance.postMessage(message);
32
- }
33
- clean() {
34
- this.instance.removeAllListeners();
35
- }
36
- // static methods use on src/app_worker.ts
37
- static get workerId() {
38
- return threadId;
39
- }
40
- static on(event, listener) {
41
- parentPort.on(event, listener);
42
- }
43
- static send(message) {
44
- message.senderWorkerId = String(threadId);
45
- parentPort.postMessage(message);
46
- }
47
- static kill() {
48
- process.exit(1);
49
- }
50
- static gracefulExit(options) {
51
- process.on('exit', async (code) => {
52
- if (typeof options.beforeExit === 'function') {
53
- await options.beforeExit();
54
- }
55
- process.exit(code);
56
- });
57
- }
58
- }
59
- export class AppThreadUtils extends BaseAppUtils {
60
- #workers = [];
61
- #forkSingle(appPath, options, id) {
62
- // start app worker
63
- const worker = new ThreadWorker(appPath, options);
64
- this.#workers.push(worker);
65
- // wrap app worker
66
- const appWorker = new AppThreadWorker(worker, id);
67
- this.emit('worker_forked', appWorker);
68
- appWorker.disableRefork = true;
69
- worker.on('message', (msg) => {
70
- if (typeof msg === 'string') {
71
- msg = {
72
- action: msg,
73
- data: msg,
74
- };
75
- }
76
- msg.from = 'app';
77
- this.messenger.send(msg);
78
- });
79
- this.log('[master] app_worker#%s (tid:%s) start', appWorker.id, appWorker.workerId);
80
- // send debug message, due to `brk` scene, send here instead of app_worker.js
81
- let debugPort = process.debugPort;
82
- if (this.options.isDebug) {
83
- debugPort++;
84
- this.messenger.send({
85
- to: 'parent',
86
- from: 'app',
87
- action: 'debug',
88
- data: {
89
- debugPort,
90
- pid: appWorker.workerId,
91
- workerId: appWorker.workerId,
92
- },
93
- });
94
- }
95
- // handle worker exit
96
- worker.on('exit', async (code) => {
97
- appWorker.state = 'dead';
98
- this.messenger.send({
99
- action: 'app-exit',
100
- data: {
101
- workerId: appWorker.workerId,
102
- code,
103
- },
104
- to: 'master',
105
- from: 'app',
106
- });
107
- // refork app worker
108
- await sleep(1000);
109
- this.#forkSingle(appPath, options, id);
110
- });
111
- }
112
- fork() {
113
- this.startTime = Date.now();
114
- this.startSuccessCount = 0;
115
- const ports = this.options.ports ?? [];
116
- if (!ports.length) {
117
- ports.push(this.options.port);
118
- }
119
- this.options.workers = ports.length;
120
- let i = 0;
121
- do {
122
- const options = Object.assign({}, this.options, { port: ports[i] });
123
- const argv = [JSON.stringify(options)];
124
- this.#forkSingle(this.getAppWorkerFile(), { argv }, ++i);
125
- } while (i < ports.length);
126
- return this;
127
- }
128
- async kill() {
129
- for (const worker of this.#workers) {
130
- const id = Reflect.get(worker, 'id');
131
- this.log(`[master] kill app worker#${id} (worker_threads) by worker.terminate()`);
132
- worker.removeAllListeners();
133
- worker.terminate();
134
- }
135
- }
136
- }
137
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL3V0aWxzL21vZGUvaW1wbC93b3JrZXJfdGhyZWFkcy9hcHAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsSUFBSSxLQUFLLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUMzRCxPQUFPLEVBQUUsTUFBTSxJQUFJLFlBQVksRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFzQixNQUFNLHFCQUFxQixDQUFDO0FBSXZHLE9BQU8sRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFHaEUsTUFBTSxPQUFPLGVBQWdCLFNBQVEsYUFBMkI7SUFDOUQsTUFBTSxHQUFHLE1BQU0sQ0FBQztJQUNoQixHQUFHLENBQVM7SUFFWixZQUFZLFFBQXNCLEVBQUUsRUFBVTtRQUM1QyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDaEIsSUFBSSxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUM7SUFDaEIsQ0FBQztJQUVELElBQUksRUFBRTtRQUNKLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQztJQUNsQixDQUFDO0lBRUQsSUFBSSxRQUFRO1FBQ1YsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQztJQUNoQyxDQUFDO0lBRUQsSUFBSSxLQUFLO1FBQ1AsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDO0lBQ3JCLENBQUM7SUFFRCxJQUFJLEtBQUssQ0FBQyxHQUFXO1FBQ25CLElBQUksQ0FBQyxNQUFNLEdBQUcsR0FBRyxDQUFDO0lBQ3BCLENBQUM7SUFFRCxJQUFJLHFCQUFxQjtRQUN2QixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxJQUFJLFFBQVE7UUFDVixPQUFPLENBQUMsQ0FBQztRQUNULGlDQUFpQztJQUNuQyxDQUFDO0lBRUQsSUFBSSxDQUFDLE9BQW9CO1FBQ3ZCLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFFRCxLQUFLO1FBQ0gsSUFBSSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO0lBQ3JDLENBQUM7SUFFRCwwQ0FBMEM7SUFFMUMsTUFBTSxLQUFLLFFBQVE7UUFDakIsT0FBTyxRQUFRLENBQUM7SUFDbEIsQ0FBQztJQUVELE1BQU0sQ0FBQyxFQUFFLENBQUMsS0FBYSxFQUFFLFFBQWtDO1FBQ3pELFVBQVcsQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ2xDLENBQUM7SUFFRCxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQW9CO1FBQzlCLE9BQU8sQ0FBQyxjQUFjLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzFDLFVBQVcsQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUVELE1BQU0sQ0FBQyxJQUFJO1FBQ1QsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNsQixDQUFDO0lBRUQsTUFBTSxDQUFDLFlBQVksQ0FBQyxPQUE0QjtRQUM5QyxPQUFPLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEVBQUU7WUFDaEMsSUFBSSxPQUFPLE9BQU8sQ0FBQyxVQUFVLEtBQUssVUFBVSxFQUFFLENBQUM7Z0JBQzdDLE1BQU0sT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQzdCLENBQUM7WUFDRCxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3JCLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztDQUNGO0FBRUQsTUFBTSxPQUFPLGNBQWUsU0FBUSxZQUFZO0lBQzlDLFFBQVEsR0FBbUIsRUFBRSxDQUFDO0lBRTlCLFdBQVcsQ0FBQyxPQUFlLEVBQUUsT0FBc0IsRUFBRSxFQUFVO1FBQzdELG1CQUFtQjtRQUNuQixNQUFNLE1BQU0sR0FBRyxJQUFJLFlBQVksQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDbEQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFM0Isa0JBQWtCO1FBQ2xCLE1BQU0sU0FBUyxHQUFHLElBQUksZUFBZSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQztRQUNsRCxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUN0QyxTQUFTLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQztRQUMvQixNQUFNLENBQUMsRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUFDLEdBQWdCLEVBQUUsRUFBRTtZQUN4QyxJQUFJLE9BQU8sR0FBRyxLQUFLLFFBQVEsRUFBRSxDQUFDO2dCQUM1QixHQUFHLEdBQUc7b0JBQ0osTUFBTSxFQUFFLEdBQUc7b0JBQ1gsSUFBSSxFQUFFLEdBQUc7aUJBQ1YsQ0FBQztZQUNKLENBQUM7WUFDRCxHQUFHLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQztZQUNqQixJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUMzQixDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxHQUFHLENBQUMsdUNBQXVDLEVBQUUsU0FBUyxDQUFDLEVBQUUsRUFBRSxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFcEYsNkVBQTZFO1FBQzdFLElBQUksU0FBUyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUM7UUFDbEMsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3pCLFNBQVMsRUFBRSxDQUFDO1lBQ1osSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUM7Z0JBQ2xCLEVBQUUsRUFBRSxRQUFRO2dCQUNaLElBQUksRUFBRSxLQUFLO2dCQUNYLE1BQU0sRUFBRSxPQUFPO2dCQUNmLElBQUksRUFBRTtvQkFDSixTQUFTO29CQUNULEdBQUcsRUFBRSxTQUFTLENBQUMsUUFBUTtvQkFDdkIsUUFBUSxFQUFFLFNBQVMsQ0FBQyxRQUFRO2lCQUM3QjthQUNGLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCxxQkFBcUI7UUFDckIsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxFQUFFO1lBQy9CLFNBQVMsQ0FBQyxLQUFLLEdBQUcsTUFBTSxDQUFDO1lBQ3pCLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDO2dCQUNsQixNQUFNLEVBQUUsVUFBVTtnQkFDbEIsSUFBSSxFQUFFO29CQUNKLFFBQVEsRUFBRSxTQUFTLENBQUMsUUFBUTtvQkFDNUIsSUFBSTtpQkFDTDtnQkFDRCxFQUFFLEVBQUUsUUFBUTtnQkFDWixJQUFJLEVBQUUsS0FBSzthQUNaLENBQUMsQ0FBQztZQUVILG9CQUFvQjtZQUNwQixNQUFNLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNsQixJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDekMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsSUFBSTtRQUNGLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQzVCLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxDQUFDLENBQUM7UUFFM0IsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDO1FBQ3ZDLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDbEIsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUssQ0FBQyxDQUFDO1FBQ2pDLENBQUM7UUFDRCxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDO1FBQ3BDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNWLEdBQUcsQ0FBQztZQUNGLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUUsRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNwRSxNQUFNLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUN2QyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUMzRCxDQUFDLFFBQVEsQ0FBQyxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUU7UUFFM0IsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsS0FBSyxDQUFDLElBQUk7UUFDUixLQUFLLE1BQU0sTUFBTSxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUNuQyxNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztZQUNyQyxJQUFJLENBQUMsR0FBRyxDQUFDLDRCQUE0QixFQUFFLHlDQUF5QyxDQUFDLENBQUM7WUFDbEYsTUFBTSxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDNUIsTUFBTSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ3JCLENBQUM7SUFDSCxDQUFDO0NBQ0YifQ==
1
+ import { BaseAppUtils, BaseAppWorker } from "../../base/app.js";
2
+ import { Worker, parentPort, threadId } from "node:worker_threads";
3
+ import { setTimeout } from "node:timers/promises";
4
+
5
+ //#region src/utils/mode/impl/worker_threads/app.ts
6
+ var AppThreadWorker = class extends BaseAppWorker {
7
+ #state = "none";
8
+ #id;
9
+ constructor(instance, id) {
10
+ super(instance);
11
+ this.#id = id;
12
+ }
13
+ get id() {
14
+ return this.#id;
15
+ }
16
+ get workerId() {
17
+ return this.instance.threadId;
18
+ }
19
+ get state() {
20
+ return this.#state;
21
+ }
22
+ set state(val) {
23
+ this.#state = val;
24
+ }
25
+ get exitedAfterDisconnect() {
26
+ return true;
27
+ }
28
+ get exitCode() {
29
+ return 0;
30
+ }
31
+ send(message) {
32
+ this.instance.postMessage(message);
33
+ }
34
+ clean() {
35
+ this.instance.removeAllListeners();
36
+ }
37
+ static get workerId() {
38
+ return threadId;
39
+ }
40
+ static on(event, listener) {
41
+ parentPort.on(event, listener);
42
+ }
43
+ static send(message) {
44
+ message.senderWorkerId = String(threadId);
45
+ parentPort.postMessage(message);
46
+ }
47
+ static kill() {
48
+ process.exit(1);
49
+ }
50
+ static gracefulExit(options) {
51
+ process.on("exit", async (code) => {
52
+ if (typeof options.beforeExit === "function") await options.beforeExit();
53
+ process.exit(code);
54
+ });
55
+ }
56
+ };
57
+ var AppThreadUtils = class extends BaseAppUtils {
58
+ #workers = [];
59
+ #forkSingle(appPath, options, id) {
60
+ const worker = new Worker(appPath, options);
61
+ this.#workers.push(worker);
62
+ const appWorker = new AppThreadWorker(worker, id);
63
+ this.emit("worker_forked", appWorker);
64
+ appWorker.disableRefork = true;
65
+ worker.on("message", (msg) => {
66
+ if (typeof msg === "string") msg = {
67
+ action: msg,
68
+ data: msg
69
+ };
70
+ msg.from = "app";
71
+ this.messenger.send(msg);
72
+ });
73
+ this.log("[master] app_worker#%s (tid:%s) start", appWorker.id, appWorker.workerId);
74
+ let debugPort = process.debugPort;
75
+ if (this.options.isDebug) {
76
+ debugPort++;
77
+ this.messenger.send({
78
+ to: "parent",
79
+ from: "app",
80
+ action: "debug",
81
+ data: {
82
+ debugPort,
83
+ pid: appWorker.workerId,
84
+ workerId: appWorker.workerId
85
+ }
86
+ });
87
+ }
88
+ worker.on("exit", async (code) => {
89
+ appWorker.state = "dead";
90
+ this.messenger.send({
91
+ action: "app-exit",
92
+ data: {
93
+ workerId: appWorker.workerId,
94
+ code
95
+ },
96
+ to: "master",
97
+ from: "app"
98
+ });
99
+ await setTimeout(1e3);
100
+ this.#forkSingle(appPath, options, id);
101
+ });
102
+ }
103
+ fork() {
104
+ this.startTime = Date.now();
105
+ this.startSuccessCount = 0;
106
+ const ports = this.options.ports ?? [];
107
+ if (!ports.length) ports.push(this.options.port);
108
+ this.options.workers = ports.length;
109
+ let i = 0;
110
+ do {
111
+ const options = Object.assign({}, this.options, { port: ports[i] });
112
+ const argv = [JSON.stringify(options)];
113
+ this.#forkSingle(this.getAppWorkerFile(), { argv }, ++i);
114
+ } while (i < ports.length);
115
+ return this;
116
+ }
117
+ async kill() {
118
+ for (const worker of this.#workers) {
119
+ const id = Reflect.get(worker, "id");
120
+ this.log(`[master] kill app worker#${id} (worker_threads) by worker.terminate()`);
121
+ worker.removeAllListeners();
122
+ worker.terminate();
123
+ }
124
+ }
125
+ };
126
+
127
+ //#endregion
128
+ export { AppThreadUtils, AppThreadWorker };