@eggjs/cluster 3.1.0-beta.9 → 4.0.0-beta.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent_worker.d.ts +1 -0
- package/dist/agent_worker.js +55 -0
- package/dist/app_worker.d.ts +1 -0
- package/dist/app_worker.js +131 -0
- package/dist/utils/mode/impl/process/agent.js +1 -1
- package/dist/utils/mode/impl/process/app.js +1 -1
- package/dist/utils/mode/impl/worker_threads/agent.js +1 -1
- package/dist/utils/mode/impl/worker_threads/app.js +1 -1
- package/package.json +10 -9
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { AgentProcessWorker } from "./utils/mode/impl/process/agent.js";
|
|
2
|
+
import { AgentThreadWorker } from "./utils/mode/impl/worker_threads/agent.js";
|
|
3
|
+
import { debuglog } from "node:util";
|
|
4
|
+
import { EggConsoleLogger } from "egg-logger";
|
|
5
|
+
import { importModule } from "@eggjs/utils";
|
|
6
|
+
|
|
7
|
+
//#region src/agent_worker.ts
|
|
8
|
+
const debug = debuglog("egg/cluster/agent_worker");
|
|
9
|
+
/**
|
|
10
|
+
* agent worker is child_process forked by master.
|
|
11
|
+
*
|
|
12
|
+
* agent worker only exit in two cases:
|
|
13
|
+
* - receive signal SIGTERM, exit code 0 (exit gracefully)
|
|
14
|
+
* - receive disconnect event, exit code 110 (maybe master exit in accident)
|
|
15
|
+
*/
|
|
16
|
+
async function main() {
|
|
17
|
+
const options = JSON.parse(process.argv[2]);
|
|
18
|
+
if (options.require) for (const mod of options.require) await importModule(mod, { paths: [options.baseDir] });
|
|
19
|
+
let AgentWorker;
|
|
20
|
+
if (options.startMode === "worker_threads") AgentWorker = AgentThreadWorker;
|
|
21
|
+
else AgentWorker = AgentProcessWorker;
|
|
22
|
+
const consoleLogger = new EggConsoleLogger({ level: process.env.EGG_AGENT_WORKER_LOGGER_LEVEL });
|
|
23
|
+
const { Agent } = await importModule(options.framework, { paths: [options.baseDir] });
|
|
24
|
+
debug("new Agent with options %j", options);
|
|
25
|
+
let agent;
|
|
26
|
+
try {
|
|
27
|
+
agent = new Agent(options);
|
|
28
|
+
} catch (err) {
|
|
29
|
+
consoleLogger.error(err);
|
|
30
|
+
throw err;
|
|
31
|
+
}
|
|
32
|
+
function startErrorHandler(err) {
|
|
33
|
+
consoleLogger.error(err);
|
|
34
|
+
consoleLogger.error("[agent_worker] start error, exiting with code:1");
|
|
35
|
+
AgentWorker.kill();
|
|
36
|
+
}
|
|
37
|
+
agent.ready((err) => {
|
|
38
|
+
if (err) return;
|
|
39
|
+
agent.removeListener("error", startErrorHandler);
|
|
40
|
+
AgentWorker.send({
|
|
41
|
+
action: "agent-start",
|
|
42
|
+
to: "master"
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
agent.once("error", startErrorHandler);
|
|
46
|
+
AgentWorker.gracefulExit({
|
|
47
|
+
logger: consoleLogger,
|
|
48
|
+
label: "agent_worker",
|
|
49
|
+
beforeExit: () => agent.close()
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
main();
|
|
53
|
+
|
|
54
|
+
//#endregion
|
|
55
|
+
export { };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { AppProcessWorker } from "./utils/mode/impl/process/app.js";
|
|
2
|
+
import { AppThreadWorker } from "./utils/mode/impl/worker_threads/app.js";
|
|
3
|
+
import { debuglog } from "node:util";
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import { EggConsoleLogger } from "egg-logger";
|
|
6
|
+
import { importModule } from "@eggjs/utils";
|
|
7
|
+
import { createServer } from "node:http";
|
|
8
|
+
import { createServer as createServer$1 } from "node:https";
|
|
9
|
+
|
|
10
|
+
//#region src/app_worker.ts
|
|
11
|
+
const debug = debuglog("egg/cluster/app_worker");
|
|
12
|
+
async function main() {
|
|
13
|
+
const options = JSON.parse(process.argv[2]);
|
|
14
|
+
if (options.require) for (const mod of options.require) await importModule(mod, { paths: [options.baseDir] });
|
|
15
|
+
let AppWorker;
|
|
16
|
+
if (options.startMode === "worker_threads") AppWorker = AppThreadWorker;
|
|
17
|
+
else AppWorker = AppProcessWorker;
|
|
18
|
+
const consoleLogger = new EggConsoleLogger({ level: process.env.EGG_APP_WORKER_LOGGER_LEVEL });
|
|
19
|
+
const { Application } = await importModule(options.framework, { paths: [options.baseDir] });
|
|
20
|
+
debug("[app_worker:%s] new Application with options %j", process.pid, options);
|
|
21
|
+
let app;
|
|
22
|
+
try {
|
|
23
|
+
app = new Application(options);
|
|
24
|
+
} catch (err) {
|
|
25
|
+
consoleLogger.error(err);
|
|
26
|
+
throw err;
|
|
27
|
+
}
|
|
28
|
+
app.ready(startServer);
|
|
29
|
+
function exitProcess() {
|
|
30
|
+
AppWorker.kill();
|
|
31
|
+
}
|
|
32
|
+
app.once("startTimeout", startTimeoutHandler);
|
|
33
|
+
function startTimeoutHandler() {
|
|
34
|
+
consoleLogger.error("[app_worker] start timeout, exiting with code:1");
|
|
35
|
+
exitProcess();
|
|
36
|
+
}
|
|
37
|
+
function startServer(err) {
|
|
38
|
+
if (err) {
|
|
39
|
+
consoleLogger.error(err);
|
|
40
|
+
consoleLogger.error("[app_worker] start error, exiting with code:1");
|
|
41
|
+
exitProcess();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const clusterConfig = app.config.cluster ?? {};
|
|
45
|
+
const listenConfig = clusterConfig.listen ?? {};
|
|
46
|
+
const httpsOptions = {
|
|
47
|
+
...clusterConfig.https,
|
|
48
|
+
...options.https
|
|
49
|
+
};
|
|
50
|
+
const port = app.options.port = options.port || listenConfig.port;
|
|
51
|
+
const debugPort = options.debugPort;
|
|
52
|
+
const protocol = httpsOptions.key && httpsOptions.cert ? "https" : "http";
|
|
53
|
+
debug("[app_worker:%s] listenConfig: %j, real port: %o, protocol: %o, debugPort: %o", process.pid, listenConfig, port, protocol, debugPort);
|
|
54
|
+
AppWorker.send({
|
|
55
|
+
to: "master",
|
|
56
|
+
action: "realport",
|
|
57
|
+
data: {
|
|
58
|
+
port,
|
|
59
|
+
protocol
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
app.removeListener("startTimeout", startTimeoutHandler);
|
|
63
|
+
let server;
|
|
64
|
+
let debugPortServer;
|
|
65
|
+
if (protocol === "https") {
|
|
66
|
+
httpsOptions.key = fs.readFileSync(httpsOptions.key);
|
|
67
|
+
httpsOptions.cert = fs.readFileSync(httpsOptions.cert);
|
|
68
|
+
httpsOptions.ca = httpsOptions.ca && fs.readFileSync(httpsOptions.ca);
|
|
69
|
+
server = createServer$1(httpsOptions, app.callback());
|
|
70
|
+
if (debugPort) debugPortServer = createServer(app.callback());
|
|
71
|
+
} else {
|
|
72
|
+
server = createServer(app.callback());
|
|
73
|
+
if (debugPort) debugPortServer = server;
|
|
74
|
+
}
|
|
75
|
+
server.once("error", (err$1) => {
|
|
76
|
+
consoleLogger.error("[app_worker] server got error: %s, code: %s", err$1.message, err$1.code);
|
|
77
|
+
exitProcess();
|
|
78
|
+
});
|
|
79
|
+
app.emit("server", server);
|
|
80
|
+
if (options.sticky && options.stickyWorkerPort) {
|
|
81
|
+
server.listen(options.stickyWorkerPort, "127.0.0.1");
|
|
82
|
+
AppWorker.on("message", (message, connection) => {
|
|
83
|
+
if (message !== "sticky-session:connection") return;
|
|
84
|
+
server.emit("connection", connection);
|
|
85
|
+
connection.resume();
|
|
86
|
+
});
|
|
87
|
+
} else {
|
|
88
|
+
if (listenConfig.path) server.listen(listenConfig.path);
|
|
89
|
+
else {
|
|
90
|
+
if (typeof port !== "number") {
|
|
91
|
+
consoleLogger.error("[app_worker:%s] port should be number, but got %s(%s)", process.pid, port, typeof port);
|
|
92
|
+
exitProcess();
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const args = [port];
|
|
96
|
+
if (listenConfig.hostname) args.push(listenConfig.hostname);
|
|
97
|
+
debug("listen options %j", args);
|
|
98
|
+
server.listen(...args);
|
|
99
|
+
}
|
|
100
|
+
if (debugPortServer) {
|
|
101
|
+
debug("listen on debug port: %s", debugPort);
|
|
102
|
+
debugPortServer.listen(debugPort);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
server.once("listening", () => {
|
|
106
|
+
let address = server.address() || { port };
|
|
107
|
+
if (typeof address === "string") address = {
|
|
108
|
+
address,
|
|
109
|
+
addressType: -1
|
|
110
|
+
};
|
|
111
|
+
debug("[app_worker:%s] listening at %j", process.pid, address);
|
|
112
|
+
AppWorker.send({
|
|
113
|
+
to: "master",
|
|
114
|
+
action: "app-start",
|
|
115
|
+
data: {
|
|
116
|
+
address,
|
|
117
|
+
workerId: AppWorker.workerId
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
AppWorker.gracefulExit({
|
|
123
|
+
logger: consoleLogger,
|
|
124
|
+
label: "app_worker",
|
|
125
|
+
beforeExit: () => app.close()
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
main();
|
|
129
|
+
|
|
130
|
+
//#endregion
|
|
131
|
+
export { };
|
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eggjs/cluster",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0-beta.13",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
7
|
"type": "module",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": "./dist/index.js",
|
|
10
|
+
"./agent_worker": "./dist/agent_worker.js",
|
|
11
|
+
"./app_worker": "./dist/app_worker.js",
|
|
10
12
|
"./package.json": "./package.json"
|
|
11
13
|
},
|
|
12
14
|
"main": "./dist/index.js",
|
|
@@ -43,23 +45,22 @@
|
|
|
43
45
|
"sendmessage": "^3.0.1",
|
|
44
46
|
"terminal-link": "^5.0.0",
|
|
45
47
|
"utility": "^2.5.0",
|
|
46
|
-
"@eggjs/utils": "
|
|
48
|
+
"@eggjs/utils": "5.0.0-beta.13"
|
|
47
49
|
},
|
|
48
50
|
"devDependencies": {
|
|
49
|
-
"@types/node": "24.5.2",
|
|
50
51
|
"address": "2",
|
|
51
52
|
"coffee": "5",
|
|
52
53
|
"egg-errors": "^2.3.2",
|
|
53
|
-
"tsdown": "0.15.
|
|
54
|
+
"tsdown": "^0.15.4",
|
|
54
55
|
"typescript": "5.9.2",
|
|
55
56
|
"urllib": "^4.6.11",
|
|
56
|
-
"
|
|
57
|
-
"@eggjs/
|
|
58
|
-
"
|
|
59
|
-
"@eggjs/
|
|
57
|
+
"vitest": "4.0.0-beta.13",
|
|
58
|
+
"@eggjs/mock": "7.0.0-beta.13",
|
|
59
|
+
"@eggjs/tsconfig": "3.1.0-beta.13",
|
|
60
|
+
"@eggjs/supertest": "9.0.0-beta.13"
|
|
60
61
|
},
|
|
61
62
|
"engines": {
|
|
62
|
-
"node": ">=
|
|
63
|
+
"node": ">=22.18.0"
|
|
63
64
|
},
|
|
64
65
|
"scripts": {
|
|
65
66
|
"build": "tsdown",
|