@eggjs/cluster 4.0.0-beta.35 → 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 +49 -64
  3. package/dist/app_worker.d.ts +1 -1
  4. package/dist/app_worker.js +126 -164
  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 +423 -554
  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 +94 -104
  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 +77 -84
  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 +32 -33
  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,80 +1,83 @@
1
- import { type SecureContextOptions } from 'node:tls';
2
- export interface ClusterHTTPSSecureOptions {
3
- key: SecureContextOptions['key'];
4
- cert: SecureContextOptions['cert'];
5
- ca?: SecureContextOptions['ca'];
6
- passphrase?: SecureContextOptions['passphrase'];
1
+ import { SecureContextOptions } from "node:tls";
2
+
3
+ //#region src/utils/options.d.ts
4
+ interface ClusterHTTPSSecureOptions {
5
+ key: SecureContextOptions["key"];
6
+ cert: SecureContextOptions["cert"];
7
+ ca?: SecureContextOptions["ca"];
8
+ passphrase?: SecureContextOptions["passphrase"];
7
9
  }
8
- export type ClusterStartMode = 'process' | 'worker_threads';
10
+ type ClusterStartMode = "process" | "worker_threads";
9
11
  /** Cluster start options */
10
- export interface ClusterOptions {
11
- /**
12
- * specify framework that can be absolute path or npm package
13
- */
14
- framework?: string;
15
- /**
16
- * @deprecated please use framework instead
17
- */
18
- customEgg?: string;
19
- /** directory of application, default to `process.cwd()` */
20
- baseDir?: string;
21
- /**
22
- * numbers of app workers, default to `os.cpus().length`
23
- */
24
- workers?: number | string;
25
- /**
26
- * listening port, default to `7001`(http) or `8443`(https)
27
- */
28
- port?: number | string | null;
29
- /**
30
- * listening a debug port on http protocol
31
- */
32
- debugPort?: number;
33
- /**
34
- * https options, { key, cert, ca }, full path
35
- */
36
- https?: ClusterHTTPSSecureOptions | boolean;
37
- /**
38
- * @deprecated please use `options.https.key` instead
39
- */
40
- key?: ClusterHTTPSSecureOptions['key'];
41
- /**
42
- * @deprecated please use `options.https.cert` instead
43
- */
44
- cert?: ClusterHTTPSSecureOptions['cert'];
45
- /**
46
- * will inject into worker/agent process
47
- */
48
- require?: string | string[];
49
- /**
50
- * will save master pid to this file
51
- */
52
- pidFile?: string;
53
- /**
54
- * custom env, default is `process.env.EGG_SERVER_ENV`
55
- */
56
- env?: string;
57
- /**
58
- * default is `'process'`, use `'worker_threads'` to start the app & agent worker by worker_threads
59
- */
60
- startMode?: ClusterStartMode;
61
- /**
62
- * startup port of each app worker, such as: `[7001, 7002, 7003]`, only effects when the startMode is `'worker_threads'`
63
- */
64
- ports?: number[];
65
- /**
66
- * sticky mode server
67
- */
68
- sticky?: boolean;
69
- /** customized plugins, for unittest */
70
- plugins?: object;
71
- isDebug?: boolean;
12
+ interface ClusterOptions {
13
+ /**
14
+ * specify framework that can be absolute path or npm package
15
+ */
16
+ framework?: string;
17
+ /**
18
+ * @deprecated please use framework instead
19
+ */
20
+ customEgg?: string;
21
+ /** directory of application, default to `process.cwd()` */
22
+ baseDir?: string;
23
+ /**
24
+ * numbers of app workers, default to `os.cpus().length`
25
+ */
26
+ workers?: number | string;
27
+ /**
28
+ * listening port, default to `7001`(http) or `8443`(https)
29
+ */
30
+ port?: number | string | null;
31
+ /**
32
+ * listening a debug port on http protocol
33
+ */
34
+ debugPort?: number;
35
+ /**
36
+ * https options, { key, cert, ca }, full path
37
+ */
38
+ https?: ClusterHTTPSSecureOptions | boolean;
39
+ /**
40
+ * @deprecated please use `options.https.key` instead
41
+ */
42
+ key?: ClusterHTTPSSecureOptions["key"];
43
+ /**
44
+ * @deprecated please use `options.https.cert` instead
45
+ */
46
+ cert?: ClusterHTTPSSecureOptions["cert"];
47
+ /**
48
+ * will inject into worker/agent process
49
+ */
50
+ require?: string | string[];
51
+ /**
52
+ * will save master pid to this file
53
+ */
54
+ pidFile?: string;
55
+ /**
56
+ * custom env, default is `process.env.EGG_SERVER_ENV`
57
+ */
58
+ env?: string;
59
+ /**
60
+ * default is `'process'`, use `'worker_threads'` to start the app & agent worker by worker_threads
61
+ */
62
+ startMode?: ClusterStartMode;
63
+ /**
64
+ * startup port of each app worker, such as: `[7001, 7002, 7003]`, only effects when the startMode is `'worker_threads'`
65
+ */
66
+ ports?: number[];
67
+ /**
68
+ * sticky mode server
69
+ */
70
+ sticky?: boolean;
71
+ /** customized plugins, for unittest */
72
+ plugins?: object;
73
+ isDebug?: boolean;
72
74
  }
73
- export interface ParsedClusterOptions extends ClusterOptions {
74
- port?: number;
75
- baseDir: string;
76
- workers: number;
77
- framework: string;
78
- startMode: ClusterStartMode;
75
+ interface ParsedClusterOptions extends ClusterOptions {
76
+ port?: number;
77
+ baseDir: string;
78
+ workers: number;
79
+ framework: string;
80
+ startMode: ClusterStartMode;
79
81
  }
80
- export declare function parseOptions(options?: ClusterOptions): Promise<ParsedClusterOptions>;
82
+ //#endregion
83
+ export { ClusterHTTPSSecureOptions, ClusterOptions, ClusterStartMode, ParsedClusterOptions };
@@ -1,81 +1,56 @@
1
- import assert from 'node:assert';
2
- import fs from 'node:fs';
3
- import os from 'node:os';
4
- import path from 'node:path';
5
- import {} from 'node:tls';
6
- import { debuglog } from 'node:util';
7
- import { getFrameworkPath, importModule } from '@eggjs/utils';
8
- const debug = debuglog('egg/cluster/utils/options');
9
- export async function parseOptions(options) {
10
- options = {
11
- baseDir: process.cwd(),
12
- port: options?.https ? 8443 : undefined,
13
- startMode: 'process',
14
- // ports: [],
15
- env: process.env.EGG_SERVER_ENV,
16
- ...options,
17
- };
18
- const pkgPath = path.join(options.baseDir, 'package.json');
19
- assert(fs.existsSync(pkgPath), `${pkgPath} should exist`);
20
- options.framework = getFrameworkPath({
21
- baseDir: options.baseDir,
22
- // compatible customEgg only when call startCluster directly without framework
23
- framework: options.framework ?? options.customEgg,
24
- });
25
- debug('[parseOptions] %o', options);
26
- const egg = await importModule(options.framework, {
27
- paths: [options.baseDir],
28
- });
29
- assert(egg.Application, `should define Application in ${options.framework}`);
30
- assert(egg.Agent, `should define Agent in ${options.framework}`);
31
- if (options.https === true) {
32
- // Keep compatible options.key, options.cert
33
- console.warn('[@eggjs/cluster:deprecated] [master] Please use `https: { key, cert, ca }` instead of `https: true`');
34
- options.https = {
35
- key: options.key,
36
- cert: options.cert,
37
- };
38
- }
39
- // https
40
- if (options.https) {
41
- assert(options.https.key, 'options.https.key should exists');
42
- if (typeof options.https.key === 'string') {
43
- assert(fs.existsSync(options.https.key), 'options.https.key file should exists');
44
- }
45
- assert(options.https.cert, 'options.https.cert should exists');
46
- if (typeof options.https.cert === 'string') {
47
- assert(fs.existsSync(options.https.cert), 'options.https.cert file should exists');
48
- }
49
- if (typeof options.https.ca === 'string') {
50
- assert(fs.existsSync(options.https.ca), 'options.https.ca file should exists');
51
- }
52
- }
53
- if (options.port && typeof options.port === 'string') {
54
- options.port = parseInt(options.port);
55
- }
56
- if (options.port === null) {
57
- options.port = undefined;
58
- }
59
- if (options.workers && typeof options.workers === 'string') {
60
- options.workers = parseInt(options.workers);
61
- }
62
- if (!options.workers) {
63
- options.workers = os.cpus().length;
64
- }
65
- if (options.require) {
66
- if (typeof options.require === 'string') {
67
- options.require = [options.require];
68
- }
69
- }
70
- // don't print deprecated message in production env.
71
- // it will print to stderr.
72
- if (process.env.NODE_ENV === 'production') {
73
- process.env.NO_DEPRECATION = '*';
74
- }
75
- const isDebug = process.execArgv.some((argv) => argv.includes('--debug') || argv.includes('--inspect'));
76
- if (isDebug) {
77
- options.isDebug = isDebug;
78
- }
79
- return options;
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { debuglog } from "node:util";
5
+ import assert from "node:assert";
6
+ import { getFrameworkPath, importModule } from "@eggjs/utils";
7
+
8
+ //#region src/utils/options.ts
9
+ const debug = debuglog("egg/cluster/utils/options");
10
+ async function parseOptions(options) {
11
+ options = {
12
+ baseDir: process.cwd(),
13
+ port: options?.https ? 8443 : void 0,
14
+ startMode: "process",
15
+ env: process.env.EGG_SERVER_ENV,
16
+ ...options
17
+ };
18
+ const pkgPath = path.join(options.baseDir, "package.json");
19
+ assert(fs.existsSync(pkgPath), `${pkgPath} should exist`);
20
+ options.framework = getFrameworkPath({
21
+ baseDir: options.baseDir,
22
+ framework: options.framework ?? options.customEgg
23
+ });
24
+ debug("[parseOptions] %o", options);
25
+ const egg = await importModule(options.framework, { paths: [options.baseDir] });
26
+ assert(egg.Application, `should define Application in ${options.framework}`);
27
+ assert(egg.Agent, `should define Agent in ${options.framework}`);
28
+ if (options.https === true) {
29
+ console.warn("[@eggjs/cluster:deprecated] [master] Please use `https: { key, cert, ca }` instead of `https: true`");
30
+ options.https = {
31
+ key: options.key,
32
+ cert: options.cert
33
+ };
34
+ }
35
+ if (options.https) {
36
+ assert(options.https.key, "options.https.key should exists");
37
+ if (typeof options.https.key === "string") assert(fs.existsSync(options.https.key), "options.https.key file should exists");
38
+ assert(options.https.cert, "options.https.cert should exists");
39
+ if (typeof options.https.cert === "string") assert(fs.existsSync(options.https.cert), "options.https.cert file should exists");
40
+ if (typeof options.https.ca === "string") assert(fs.existsSync(options.https.ca), "options.https.ca file should exists");
41
+ }
42
+ if (options.port && typeof options.port === "string") options.port = parseInt(options.port);
43
+ if (options.port === null) options.port = void 0;
44
+ if (options.workers && typeof options.workers === "string") options.workers = parseInt(options.workers);
45
+ if (!options.workers) options.workers = os.cpus().length;
46
+ if (options.require) {
47
+ if (typeof options.require === "string") options.require = [options.require];
48
+ }
49
+ if (process.env.NODE_ENV === "production") process.env.NO_DEPRECATION = "*";
50
+ const isDebug = process.execArgv.some((argv) => argv.includes("--debug") || argv.includes("--inspect"));
51
+ if (isDebug) options.isDebug = isDebug;
52
+ return options;
80
53
  }
81
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3B0aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9vcHRpb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sTUFBTSxNQUFNLGFBQWEsQ0FBQztBQUNqQyxPQUFPLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDekIsT0FBTyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3pCLE9BQU8sSUFBSSxNQUFNLFdBQVcsQ0FBQztBQUM3QixPQUFPLEVBQTZCLE1BQU0sVUFBVSxDQUFDO0FBQ3JELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFckMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLFlBQVksRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUU5RCxNQUFNLEtBQUssR0FBRyxRQUFRLENBQUMsMkJBQTJCLENBQUMsQ0FBQztBQW9GcEQsTUFBTSxDQUFDLEtBQUssVUFBVSxZQUFZLENBQUMsT0FBd0I7SUFDekQsT0FBTyxHQUFHO1FBQ1IsT0FBTyxFQUFFLE9BQU8sQ0FBQyxHQUFHLEVBQUU7UUFDdEIsSUFBSSxFQUFFLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsU0FBUztRQUN2QyxTQUFTLEVBQUUsU0FBUztRQUNwQixhQUFhO1FBQ2IsR0FBRyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYztRQUMvQixHQUFHLE9BQU87S0FDWCxDQUFDO0lBRUYsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBUSxFQUFFLGNBQWMsQ0FBQyxDQUFDO0lBQzVELE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEdBQUcsT0FBTyxlQUFlLENBQUMsQ0FBQztJQUUxRCxPQUFPLENBQUMsU0FBUyxHQUFHLGdCQUFnQixDQUFDO1FBQ25DLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBUTtRQUN6Qiw4RUFBOEU7UUFDOUUsU0FBUyxFQUFFLE9BQU8sQ0FBQyxTQUFTLElBQUksT0FBTyxDQUFDLFNBQVM7S0FDbEQsQ0FBQyxDQUFDO0lBQ0gsS0FBSyxDQUFDLG1CQUFtQixFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBRXBDLE1BQU0sR0FBRyxHQUFHLE1BQU0sWUFBWSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUU7UUFDaEQsS0FBSyxFQUFFLENBQUMsT0FBTyxDQUFDLE9BQVEsQ0FBQztLQUMxQixDQUFDLENBQUM7SUFDSCxNQUFNLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxnQ0FBZ0MsT0FBTyxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUM7SUFDN0UsTUFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsMEJBQTBCLE9BQU8sQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDO0lBRWpFLElBQUksT0FBTyxDQUFDLEtBQUssS0FBSyxJQUFJLEVBQUUsQ0FBQztRQUMzQiw0Q0FBNEM7UUFDNUMsT0FBTyxDQUFDLElBQUksQ0FBQyxxR0FBcUcsQ0FBQyxDQUFDO1FBQ3BILE9BQU8sQ0FBQyxLQUFLLEdBQUc7WUFDZCxHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUc7WUFDaEIsSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJO1NBQ25CLENBQUM7SUFDSixDQUFDO0lBRUQsUUFBUTtJQUNSLElBQUksT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2xCLE1BQU0sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxpQ0FBaUMsQ0FBQyxDQUFDO1FBQzdELElBQUksT0FBTyxPQUFPLENBQUMsS0FBSyxDQUFDLEdBQUcsS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUMxQyxNQUFNLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLHNDQUFzQyxDQUFDLENBQUM7UUFDbkYsQ0FBQztRQUNELE1BQU0sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxrQ0FBa0MsQ0FBQyxDQUFDO1FBQy9ELElBQUksT0FBTyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUMzQyxNQUFNLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLHVDQUF1QyxDQUFDLENBQUM7UUFDckYsQ0FBQztRQUNELElBQUksT0FBTyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUN6QyxNQUFNLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxFQUFFLHFDQUFxQyxDQUFDLENBQUM7UUFDakYsQ0FBQztJQUNILENBQUM7SUFFRCxJQUFJLE9BQU8sQ0FBQyxJQUFJLElBQUksT0FBTyxPQUFPLENBQUMsSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQ3JELE9BQU8sQ0FBQyxJQUFJLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN4QyxDQUFDO0lBQ0QsSUFBSSxPQUFPLENBQUMsSUFBSSxLQUFLLElBQUksRUFBRSxDQUFDO1FBQzFCLE9BQU8sQ0FBQyxJQUFJLEdBQUcsU0FBUyxDQUFDO0lBQzNCLENBQUM7SUFFRCxJQUFJLE9BQU8sQ0FBQyxPQUFPLElBQUksT0FBTyxPQUFPLENBQUMsT0FBTyxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQzNELE9BQU8sQ0FBQyxPQUFPLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM5QyxDQUFDO0lBQ0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNyQixPQUFPLENBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxNQUFNLENBQUM7SUFDckMsQ0FBQztJQUVELElBQUksT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3BCLElBQUksT0FBTyxPQUFPLENBQUMsT0FBTyxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ3hDLE9BQU8sQ0FBQyxPQUFPLEdBQUcsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDdEMsQ0FBQztJQUNILENBQUM7SUFFRCxvREFBb0Q7SUFDcEQsMkJBQTJCO0lBQzNCLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEtBQUssWUFBWSxFQUFFLENBQUM7UUFDMUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxjQUFjLEdBQUcsR0FBRyxDQUFDO0lBQ25DLENBQUM7SUFFRCxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7SUFDeEcsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUNaLE9BQU8sQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO0lBQzVCLENBQUM7SUFFRCxPQUFPLE9BQStCLENBQUM7QUFDekMsQ0FBQyJ9
54
+
55
+ //#endregion
56
+ export { parseOptions };
@@ -1,81 +1,61 @@
1
- import { ChildProcess } from 'node:child_process';
2
- import { once } from 'node:events';
3
- import { setTimeout as sleep } from 'node:timers/promises';
4
- import { debuglog } from 'node:util';
5
- import { pstree } from '@fengmk2/ps-tree';
6
- const debug = debuglog('egg/cluster/utils/terminate');
7
- export async function terminate(subProcess, timeout) {
8
- const pid = subProcess.process?.pid ?? subProcess.pid;
9
- const childPids = await getChildPids(pid);
10
- await Promise.all([killProcess(subProcess, timeout), killChildren(childPids, timeout)]);
1
+ import { debuglog } from "node:util";
2
+ import { ChildProcess } from "node:child_process";
3
+ import { once } from "node:events";
4
+ import { setTimeout } from "node:timers/promises";
5
+ import { pstree } from "@fengmk2/ps-tree";
6
+
7
+ //#region src/utils/terminate.ts
8
+ const debug = debuglog("egg/cluster/utils/terminate");
9
+ async function terminate(subProcess, timeout) {
10
+ const childPids = await getChildPids(subProcess.process?.pid ?? subProcess.pid);
11
+ await Promise.all([killProcess(subProcess, timeout), killChildren(childPids, timeout)]);
11
12
  }
12
- // kill process, if SIGTERM not work, try SIGKILL
13
13
  async function killProcess(subProcess, timeout) {
14
- // https://github.com/nodejs/node/pull/34312
15
- (subProcess.process ?? subProcess).kill('SIGTERM');
16
- await Promise.race([once(subProcess, 'exit'), sleep(timeout)]);
17
- if (subProcess.killed) {
18
- return;
19
- }
20
- // SIGKILL: http://man7.org/linux/man-pages/man7/signal.7.html
21
- // worker: https://github.com/nodejs/node/blob/master/lib/internal/cluster/worker.js#L22
22
- // subProcess.kill is wrapped to subProcess.destroy, it will wait to disconnected.
23
- (subProcess.process ?? subProcess).kill('SIGKILL');
14
+ (subProcess.process ?? subProcess).kill("SIGTERM");
15
+ await Promise.race([once(subProcess, "exit"), setTimeout(timeout)]);
16
+ if (subProcess.killed) return;
17
+ (subProcess.process ?? subProcess).kill("SIGKILL");
24
18
  }
25
- // kill all children processes, if SIGTERM not work, try SIGKILL
26
19
  async function killChildren(childrenPids, timeout) {
27
- if (childrenPids.length === 0) {
28
- return;
29
- }
30
- kill(childrenPids, 'SIGTERM');
31
- const start = Date.now();
32
- // if timeout is 1000, it will check twice.
33
- const checkInterval = 400;
34
- let unterminated = [];
35
- while (Date.now() - start < timeout - checkInterval) {
36
- await sleep(checkInterval);
37
- unterminated = getUnterminatedProcesses(childrenPids);
38
- if (unterminated.length === 0) {
39
- return;
40
- }
41
- }
42
- kill(unterminated, 'SIGKILL');
20
+ if (childrenPids.length === 0) return;
21
+ kill(childrenPids, "SIGTERM");
22
+ const start = Date.now();
23
+ const checkInterval = 400;
24
+ let unterminated = [];
25
+ while (Date.now() - start < timeout - checkInterval) {
26
+ await setTimeout(checkInterval);
27
+ unterminated = getUnterminatedProcesses(childrenPids);
28
+ if (unterminated.length === 0) return;
29
+ }
30
+ kill(unterminated, "SIGKILL");
43
31
  }
44
32
  async function getChildPids(pid) {
45
- let childrenPids = [];
46
- try {
47
- const children = await pstree(pid);
48
- childrenPids = children.map((c) => parseInt(c.PID));
49
- }
50
- catch (err) {
51
- // if get children error, just ignore it
52
- debug('pstree %s error: %s, ignore it', pid, err);
53
- }
54
- return childrenPids;
33
+ let childrenPids = [];
34
+ try {
35
+ childrenPids = (await pstree(pid)).map((c) => parseInt(c.PID));
36
+ } catch (err) {
37
+ debug("pstree %s error: %s, ignore it", pid, err);
38
+ }
39
+ return childrenPids;
55
40
  }
56
41
  function kill(pids, signal) {
57
- for (const pid of pids) {
58
- try {
59
- process.kill(pid, signal);
60
- }
61
- catch (err) {
62
- // ignore
63
- debug('kill %s error: %s, signal: %s, ignore it', pid, err, signal);
64
- }
65
- }
42
+ for (const pid of pids) try {
43
+ process.kill(pid, signal);
44
+ } catch (err) {
45
+ debug("kill %s error: %s, signal: %s, ignore it", pid, err, signal);
46
+ }
66
47
  }
67
48
  function getUnterminatedProcesses(pids) {
68
- return pids.filter((pid) => {
69
- try {
70
- // success means it's still alive
71
- process.kill(pid, 0);
72
- return true;
73
- }
74
- catch (err) {
75
- // error means it's dead
76
- debug('kill %s error: %s, it still alive', pid, err);
77
- return false;
78
- }
79
- });
49
+ return pids.filter((pid) => {
50
+ try {
51
+ process.kill(pid, 0);
52
+ return true;
53
+ } catch (err) {
54
+ debug("kill %s error: %s, it still alive", pid, err);
55
+ return false;
56
+ }
57
+ });
80
58
  }
81
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVybWluYXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL3Rlcm1pbmF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDbEQsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNuQyxPQUFPLEVBQUUsVUFBVSxJQUFJLEtBQUssRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzNELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFckMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRTFDLE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO0FBTXRELE1BQU0sQ0FBQyxLQUFLLFVBQVUsU0FBUyxDQUFDLFVBQXNCLEVBQUUsT0FBZTtJQUNyRSxNQUFNLEdBQUcsR0FBRyxVQUFVLENBQUMsT0FBTyxFQUFFLEdBQUcsSUFBSSxVQUFVLENBQUMsR0FBRyxDQUFDO0lBQ3RELE1BQU0sU0FBUyxHQUFHLE1BQU0sWUFBWSxDQUFDLEdBQUksQ0FBQyxDQUFDO0lBQzNDLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLEVBQUUsWUFBWSxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDMUYsQ0FBQztBQUVELGlEQUFpRDtBQUNqRCxLQUFLLFVBQVUsV0FBVyxDQUFDLFVBQXNCLEVBQUUsT0FBZTtJQUNoRSw0Q0FBNEM7SUFDNUMsQ0FBQyxVQUFVLENBQUMsT0FBTyxJQUFJLFVBQVUsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNuRCxNQUFNLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxFQUFFLEtBQUss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
59
+
60
+ //#endregion
61
+ export { terminate };
@@ -1,25 +1,29 @@
1
- import { EventEmitter } from 'node:events';
2
- import { BaseAgentWorker } from './mode/base/agent.ts';
3
- import { BaseAppWorker } from './mode/base/app.ts';
4
- export declare class WorkerManager extends EventEmitter {
5
- agent: BaseAgentWorker | null;
6
- workers: Map<number, BaseAppWorker>;
7
- exception: number;
8
- timer: NodeJS.Timeout;
9
- constructor();
10
- getWorkers(): number[];
11
- setAgent(agent: BaseAgentWorker): void;
12
- getAgent(): BaseAgentWorker | null;
13
- deleteAgent(): void;
14
- setWorker(worker: BaseAppWorker): void;
15
- getWorker(workerId: number): BaseAppWorker | undefined;
16
- deleteWorker(workerId: number): void;
17
- listWorkerIds(): number[];
18
- listWorkers(): BaseAppWorker[];
19
- getListeningWorkerIds(): number[];
20
- count(): {
21
- agent: number;
22
- worker: number;
23
- };
24
- startCheck(): void;
1
+ import { BaseAgentWorker } from "./mode/base/agent.js";
2
+ import { BaseAppWorker } from "./mode/base/app.js";
3
+ import { EventEmitter } from "node:events";
4
+
5
+ //#region src/utils/worker_manager.d.ts
6
+ declare class WorkerManager extends EventEmitter {
7
+ agent: BaseAgentWorker | null;
8
+ workers: Map<number, BaseAppWorker>;
9
+ exception: number;
10
+ timer: NodeJS.Timeout;
11
+ constructor();
12
+ getWorkers(): number[];
13
+ setAgent(agent: BaseAgentWorker): void;
14
+ getAgent(): BaseAgentWorker | null;
15
+ deleteAgent(): void;
16
+ setWorker(worker: BaseAppWorker): void;
17
+ getWorker(workerId: number): BaseAppWorker | undefined;
18
+ deleteWorker(workerId: number): void;
19
+ listWorkerIds(): number[];
20
+ listWorkers(): BaseAppWorker[];
21
+ getListeningWorkerIds(): number[];
22
+ count(): {
23
+ agent: number;
24
+ worker: number;
25
+ };
26
+ startCheck(): void;
25
27
  }
28
+ //#endregion
29
+ export { WorkerManager };