@contember/engine-server 2.1.0-alpha.30 → 2.1.0-alpha.35
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/package.json +17 -12
- package/src/cluster.ts +15 -17
- package/src/start.ts +3 -4
- package/dist/development/src/cluster.cjs +0 -87
- package/dist/development/src/cluster.cjs.map +0 -1
- package/dist/development/src/cluster.js +0 -87
- package/dist/development/src/cluster.js.map +0 -1
- package/dist/development/src/loadPlugins.cjs +0 -9
- package/dist/development/src/loadPlugins.cjs.map +0 -1
- package/dist/development/src/loadPlugins.js +0 -10
- package/dist/development/src/loadPlugins.js.map +0 -1
- package/dist/development/src/utils.cjs +0 -7
- package/dist/development/src/utils.cjs.map +0 -1
- package/dist/development/src/utils.js +0 -7
- package/dist/development/src/utils.js.map +0 -1
- package/dist/development/start.cjs +0 -152
- package/dist/development/start.cjs.map +0 -1
- package/dist/development/start.js +0 -134
- package/dist/development/start.js.map +0 -1
- package/dist/production/src/cluster.cjs +0 -87
- package/dist/production/src/cluster.cjs.map +0 -1
- package/dist/production/src/cluster.js +0 -87
- package/dist/production/src/cluster.js.map +0 -1
- package/dist/production/src/loadPlugins.cjs +0 -9
- package/dist/production/src/loadPlugins.cjs.map +0 -1
- package/dist/production/src/loadPlugins.js +0 -10
- package/dist/production/src/loadPlugins.js.map +0 -1
- package/dist/production/src/utils.cjs +0 -7
- package/dist/production/src/utils.cjs.map +0 -1
- package/dist/production/src/utils.js +0 -7
- package/dist/production/src/utils.js.map +0 -1
- package/dist/production/start.cjs +0 -152
- package/dist/production/start.cjs.map +0 -1
- package/dist/production/start.js +0 -134
- package/dist/production/start.js.map +0 -1
- package/dist/types/cluster.d.ts +0 -16
- package/dist/types/cluster.d.ts.map +0 -1
- package/dist/types/loadPlugins.d.ts +0 -3
- package/dist/types/loadPlugins.d.ts.map +0 -1
- package/dist/types/start.d.ts +0 -3
- package/dist/types/start.d.ts.map +0 -1
- package/dist/types/tsconfig.tsbuildinfo +0 -1
- package/dist/types/utils.d.ts +0 -2
- package/dist/types/utils.d.ts.map +0 -1
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { createDefaultLogger, isDebugMode, getServerVersion, printStartInfo, resolveServerConfig, serverConfigSchema, createSentryLoggerHandler, createContainer, listenOnProcessTermination } from "@contember/engine-http";
|
|
3
|
-
import loadPlugins from "./src/loadPlugins.js";
|
|
4
|
-
import cluster from "node:cluster";
|
|
5
|
-
import * as os from "node:os";
|
|
6
|
-
import { timeout } from "./src/utils.js";
|
|
7
|
-
import { getClusterProcessType, notifyWorkerStarted, WorkerManager } from "./src/cluster.js";
|
|
8
|
-
const logger = createDefaultLogger();
|
|
9
|
-
process.on("warning", (message) => {
|
|
10
|
-
logger.warn(message);
|
|
11
|
-
});
|
|
12
|
-
(async () => {
|
|
13
|
-
const isDebug = isDebugMode();
|
|
14
|
-
const version = await getServerVersion();
|
|
15
|
-
printStartInfo({ version, isDebug }, logger);
|
|
16
|
-
const plugins = await loadPlugins();
|
|
17
|
-
const { serverConfig, projectConfigResolver, tenantConfigResolver } = await resolveServerConfig({ plugins, serverConfigSchema });
|
|
18
|
-
if (process.argv[2] === "validate") {
|
|
19
|
-
process.exit(0);
|
|
20
|
-
}
|
|
21
|
-
const sentryhandler = createSentryLoggerHandler(serverConfig.logging?.sentry?.dsn);
|
|
22
|
-
if (sentryhandler !== null) {
|
|
23
|
-
logger.addHandler(sentryhandler);
|
|
24
|
-
}
|
|
25
|
-
const workerConfig = serverConfig.workerCount || 1;
|
|
26
|
-
const workerCount = workerConfig === "auto" ? os.cpus().length : Number(workerConfig);
|
|
27
|
-
const isClusterMode = serverConfig.workerCount !== void 0;
|
|
28
|
-
const processType = getClusterProcessType(isClusterMode);
|
|
29
|
-
const container = createContainer({
|
|
30
|
-
debugMode: isDebug,
|
|
31
|
-
serverConfig,
|
|
32
|
-
projectConfigResolver,
|
|
33
|
-
tenantConfigResolver,
|
|
34
|
-
plugins,
|
|
35
|
-
processType,
|
|
36
|
-
version,
|
|
37
|
-
logger
|
|
38
|
-
});
|
|
39
|
-
let initializedProjects = [];
|
|
40
|
-
const terminationJobs = [];
|
|
41
|
-
listenOnProcessTermination(terminationJobs, logger);
|
|
42
|
-
if (cluster.isMaster) {
|
|
43
|
-
const monitoringPort = serverConfig.monitoringPort;
|
|
44
|
-
const monitoringServer = container.monitoringKoa.listen(monitoringPort, () => {
|
|
45
|
-
logger.info(`Monitoring running on http://localhost:${monitoringPort}`);
|
|
46
|
-
});
|
|
47
|
-
terminationJobs.push(async () => {
|
|
48
|
-
await new Promise((resolve) => monitoringServer.close(resolve));
|
|
49
|
-
logger.info("Monitoring server terminated");
|
|
50
|
-
});
|
|
51
|
-
if (!serverConfig.projectGroup) {
|
|
52
|
-
initializedProjects = await container.initializer.initialize();
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
const port = serverConfig.port;
|
|
56
|
-
const printStarted = () => {
|
|
57
|
-
if (serverConfig.projectGroup) {
|
|
58
|
-
logger.info("Contember Cloud running");
|
|
59
|
-
} else {
|
|
60
|
-
logger.info(`Contember API running on http://localhost:${port}`);
|
|
61
|
-
}
|
|
62
|
-
if (initializedProjects.length) {
|
|
63
|
-
logger.info(`Initialized projects: ${initializedProjects.join(", ")}`);
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
const startApplication = async () => {
|
|
67
|
-
const httpServerPromise = container.application.listen();
|
|
68
|
-
terminationJobs.push(async () => {
|
|
69
|
-
await (await httpServerPromise).close();
|
|
70
|
-
logger.info("API server terminated");
|
|
71
|
-
});
|
|
72
|
-
await httpServerPromise;
|
|
73
|
-
};
|
|
74
|
-
const startWorker = async (workerName) => {
|
|
75
|
-
const worker = container.applicationWorkers.getWorker(workerName);
|
|
76
|
-
const runningWorker = worker.run({
|
|
77
|
-
logger,
|
|
78
|
-
onError: (e) => {
|
|
79
|
-
logger.crit(e);
|
|
80
|
-
process.exit(1);
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
terminationJobs.push(async () => {
|
|
84
|
-
(await runningWorker).end();
|
|
85
|
-
});
|
|
86
|
-
await runningWorker;
|
|
87
|
-
logger.info(`Contember Worker ${workerName} started.`);
|
|
88
|
-
};
|
|
89
|
-
const applicationWorker = serverConfig.applicationWorker;
|
|
90
|
-
if (applicationWorker && applicationWorker !== "all") {
|
|
91
|
-
await startWorker(applicationWorker);
|
|
92
|
-
if (isClusterMode) {
|
|
93
|
-
notifyWorkerStarted();
|
|
94
|
-
}
|
|
95
|
-
} else if (isClusterMode) {
|
|
96
|
-
if (cluster.isMaster) {
|
|
97
|
-
logger.info(`Master ${process.pid} is running`);
|
|
98
|
-
const workerManager = new WorkerManager();
|
|
99
|
-
terminationJobs.push(async ({ signal }) => {
|
|
100
|
-
await workerManager.terminate(signal);
|
|
101
|
-
logger.info("Workers terminated");
|
|
102
|
-
});
|
|
103
|
-
await workerManager.start({ workerCount });
|
|
104
|
-
if (applicationWorker === "all") {
|
|
105
|
-
for (const workerName of container.applicationWorkers.getWorkerNames()) {
|
|
106
|
-
await workerManager.start({
|
|
107
|
-
workerCount,
|
|
108
|
-
env: {
|
|
109
|
-
CONTEMBER_APPLICATION_WORKER: workerName
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
printStarted();
|
|
115
|
-
} else {
|
|
116
|
-
logger.info(`Starting worker ${process.pid}`);
|
|
117
|
-
process.on("disconnect", () => timeout(0));
|
|
118
|
-
await startApplication();
|
|
119
|
-
notifyWorkerStarted();
|
|
120
|
-
}
|
|
121
|
-
} else {
|
|
122
|
-
await startApplication();
|
|
123
|
-
if (applicationWorker === "all") {
|
|
124
|
-
for (const workerName of container.applicationWorkers.getWorkerNames()) {
|
|
125
|
-
await startWorker(workerName);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
printStarted();
|
|
129
|
-
}
|
|
130
|
-
})().catch((e) => {
|
|
131
|
-
logger.crit(e);
|
|
132
|
-
process.exit(1);
|
|
133
|
-
});
|
|
134
|
-
//# sourceMappingURL=start.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"start.js","sources":["../../../packages/engine-server/src/start.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport {\n\tcreateContainer,\n\tcreateDefaultLogger,\n\tcreateSentryLoggerHandler,\n\tgetServerVersion,\n\tisDebugMode,\n\tlistenOnProcessTermination,\n\tprintStartInfo,\n\tresolveServerConfig,\n\tserverConfigSchema,\n\tTerminationJob,\n} from '@contember/engine-http'\nimport loadPlugins from './loadPlugins'\nimport cluster from 'node:cluster'\nimport * as os from 'node:os'\nimport { timeout } from './utils'\nimport { getClusterProcessType, notifyWorkerStarted, WorkerManager } from './cluster'\n\nconst logger = createDefaultLogger()\nprocess.on('warning', message => {\n\tlogger.warn(message)\n})\n;(async () => {\n\tconst isDebug = isDebugMode()\n\n\tconst version = await getServerVersion()\n\tprintStartInfo({ version, isDebug }, logger)\n\tconst plugins = await loadPlugins()\n\tconst { serverConfig, projectConfigResolver, tenantConfigResolver } = await resolveServerConfig({ plugins, serverConfigSchema })\n\n\tif (process.argv[2] === 'validate') {\n\t\tprocess.exit(0)\n\t}\n\n\tconst sentryhandler = createSentryLoggerHandler(serverConfig.logging?.sentry?.dsn)\n\tif (sentryhandler !== null) {\n\t\tlogger.addHandler(sentryhandler)\n\t}\n\n\tconst workerConfig = serverConfig.workerCount || 1\n\n\tconst workerCount = workerConfig === 'auto' ? os.cpus().length : Number(workerConfig)\n\tconst isClusterMode = serverConfig.workerCount !== undefined\n\n\tconst processType = getClusterProcessType(isClusterMode)\n\n\tconst container = createContainer({\n\t\tdebugMode: isDebug,\n\t\tserverConfig,\n\t\tprojectConfigResolver,\n\t\ttenantConfigResolver,\n\t\tplugins,\n\t\tprocessType,\n\t\tversion,\n\t\tlogger,\n\t})\n\n\tlet initializedProjects: string[] = []\n\tconst terminationJobs: TerminationJob[] = []\n\tlistenOnProcessTermination(terminationJobs, logger)\n\n\tif (cluster.isMaster) {\n\t\tconst monitoringPort = serverConfig.monitoringPort\n\t\tconst monitoringServer = container.monitoringKoa.listen(monitoringPort, () => {\n\t\t\tlogger.info(`Monitoring running on http://localhost:${monitoringPort}`)\n\t\t})\n\t\tterminationJobs.push(async () => {\n\t\t\tawait new Promise<any>(resolve => monitoringServer.close(resolve))\n\t\t\tlogger.info('Monitoring server terminated')\n\t\t})\n\t\tif (!serverConfig.projectGroup) {\n\t\t\tinitializedProjects = await container.initializer.initialize()\n\t\t}\n\t}\n\n\tconst port = serverConfig.port\n\tconst printStarted = () => {\n\t\tif (serverConfig.projectGroup) {\n\t\t\tlogger.info('Contember Cloud running')\n\t\t} else {\n\t\t\tlogger.info(`Contember API running on http://localhost:${port}`)\n\t\t}\n\t\tif (initializedProjects.length) {\n\t\t\tlogger.info(`Initialized projects: ${initializedProjects.join(', ')}`)\n\t\t}\n\t}\n\n\tconst startApplication = async () => {\n\t\tconst httpServerPromise = container.application.listen()\n\t\tterminationJobs.push(async () => {\n\t\t\tawait (await httpServerPromise).close()\n\t\t\tlogger.info('API server terminated')\n\t\t})\n\t\tawait httpServerPromise\n\t}\n\n\tconst startWorker = async (workerName: string) => {\n\t\tconst worker = container.applicationWorkers.getWorker(workerName)\n\t\tconst runningWorker = worker.run({\n\t\t\tlogger,\n\t\t\tonError: e => {\n\t\t\t\tlogger.crit(e)\n\t\t\t\tprocess.exit(1)\n\t\t\t},\n\t\t})\n\t\tterminationJobs.push(async () => {\n\t\t\t(await runningWorker).end()\n\t\t})\n\t\tawait runningWorker\n\t\tlogger.info(`Contember Worker ${workerName} started.`)\n\n\t}\n\n\tconst applicationWorker = serverConfig.applicationWorker\n\tif (applicationWorker && applicationWorker !== 'all') {\n\t\tawait startWorker(applicationWorker)\n\t\tif (isClusterMode) {\n\t\t\tnotifyWorkerStarted()\n\t\t}\n\t} else if (isClusterMode) {\n\t\tif (cluster.isMaster) {\n\t\t\tlogger.info(`Master ${process.pid} is running`)\n\t\t\tconst workerManager = new WorkerManager()\n\t\t\tterminationJobs.push(async ({ signal }) => {\n\t\t\t\tawait workerManager.terminate(signal)\n\t\t\t\tlogger.info('Workers terminated')\n\t\t\t})\n\n\t\t\tawait workerManager.start({ workerCount })\n\n\t\t\tif (applicationWorker === 'all') {\n\t\t\t\tfor (const workerName of container.applicationWorkers.getWorkerNames()) {\n\t\t\t\t\tawait workerManager.start({\n\t\t\t\t\t\tworkerCount, env: {\n\t\t\t\t\t\t\tCONTEMBER_APPLICATION_WORKER: workerName,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t\tprintStarted()\n\t\t} else {\n\t\t\tlogger.info(`Starting worker ${process.pid}`)\n\n\t\t\t// this line somehow ensures, that worker waits for termination of all jobs\n\t\t\tprocess.on('disconnect', () => timeout(0))\n\n\t\t\tawait startApplication()\n\t\t\tnotifyWorkerStarted()\n\t\t}\n\t} else {\n\t\tawait startApplication()\n\t\tif (applicationWorker === 'all') {\n\t\t\tfor (const workerName of container.applicationWorkers.getWorkerNames()) {\n\t\t\t\tawait startWorker(workerName)\n\t\t\t}\n\t\t}\n\t\tprintStarted()\n\t}\n\n})().catch(e => {\n\tlogger.crit(e)\n\tprocess.exit(1)\n})\n"],"names":[],"mappings":"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"}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const cluster = require("node:cluster");
|
|
4
|
-
const utils = require("./utils.cjs");
|
|
5
|
-
var __defProp = Object.defineProperty;
|
|
6
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
7
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
8
|
-
const getClusterProcessType = (isClusterMode) => !isClusterMode ? "singleNode" : cluster.isMaster ? "clusterMaster" : "clusterWorker";
|
|
9
|
-
const MSG_WORKER_STARTED = "msg_worker_started";
|
|
10
|
-
const waitForWorker = (worker, timeoutMs) => {
|
|
11
|
-
let ok = false;
|
|
12
|
-
return Promise.race([
|
|
13
|
-
new Promise(async (resolve) => {
|
|
14
|
-
const listener = (message) => {
|
|
15
|
-
if ("type" in message && message.type === MSG_WORKER_STARTED) {
|
|
16
|
-
ok = true;
|
|
17
|
-
resolve(null);
|
|
18
|
-
worker.removeListener("message", listener);
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
await worker.on("message", listener);
|
|
22
|
-
}),
|
|
23
|
-
utils.timeout(timeoutMs).then(() => {
|
|
24
|
-
if (!ok) {
|
|
25
|
-
throw new Error("Worker start timed out");
|
|
26
|
-
}
|
|
27
|
-
return true;
|
|
28
|
-
})
|
|
29
|
-
]);
|
|
30
|
-
};
|
|
31
|
-
const notifyWorkerStarted = () => process.send?.({
|
|
32
|
-
type: MSG_WORKER_STARTED
|
|
33
|
-
});
|
|
34
|
-
class WorkerManager {
|
|
35
|
-
constructor() {
|
|
36
|
-
__publicField(this, "isTerminating", false);
|
|
37
|
-
__publicField(this, "workers", /* @__PURE__ */ new Set());
|
|
38
|
-
}
|
|
39
|
-
async start({ workerCount, env }) {
|
|
40
|
-
if (this.isTerminating) {
|
|
41
|
-
throw new Error(`Worker manager is terminating`);
|
|
42
|
-
}
|
|
43
|
-
for (let i = 0; i < workerCount; i++) {
|
|
44
|
-
await this.startWorker(env);
|
|
45
|
-
if (this.isTerminating) {
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
async startWorker(env) {
|
|
51
|
-
const worker = cluster.fork(env);
|
|
52
|
-
worker.on("exit", async (code, signal) => {
|
|
53
|
-
this.workers.delete(worker);
|
|
54
|
-
if (!this.isTerminating) {
|
|
55
|
-
console.log(`Worker ${worker.process.pid} died with signal ${signal}, restarting`);
|
|
56
|
-
await utils.timeout(2e3);
|
|
57
|
-
await this.startWorker(env);
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
this.workers.add(worker);
|
|
61
|
-
await waitForWorker(worker, 15e3);
|
|
62
|
-
}
|
|
63
|
-
async terminate(signal) {
|
|
64
|
-
if (this.isTerminating) {
|
|
65
|
-
throw new Error(`Worker manager is terminating`);
|
|
66
|
-
}
|
|
67
|
-
this.isTerminating = true;
|
|
68
|
-
await Promise.allSettled(Array.from(this.workers).map(async (it) => {
|
|
69
|
-
if (!it) {
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
console.log(`Terminating worker ${it.process.pid}`);
|
|
73
|
-
const disconnectPromise = new Promise((resolve) => it.once("disconnect", resolve));
|
|
74
|
-
it.disconnect();
|
|
75
|
-
await disconnectPromise;
|
|
76
|
-
const killPromise = new Promise((resolve) => it.once("exit", resolve));
|
|
77
|
-
it.kill(signal);
|
|
78
|
-
await killPromise;
|
|
79
|
-
console.log(`Worker ${it.process.pid} terminated`);
|
|
80
|
-
}));
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
exports.WorkerManager = WorkerManager;
|
|
84
|
-
exports.getClusterProcessType = getClusterProcessType;
|
|
85
|
-
exports.notifyWorkerStarted = notifyWorkerStarted;
|
|
86
|
-
exports.waitForWorker = waitForWorker;
|
|
87
|
-
//# sourceMappingURL=cluster.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cluster.cjs","sources":["../../../../packages/engine-server/src/cluster.ts"],"sourcesContent":["import cluster, { Worker } from 'node:cluster'\nimport { timeout } from './utils'\n\nexport const getClusterProcessType = (isClusterMode: boolean): ProcessType =>\n\t!isClusterMode ? 'singleNode' : cluster.isMaster ? 'clusterMaster' : 'clusterWorker'\n\nexport type ProcessType =\n\t| 'singleNode'\n\t| 'clusterMaster'\n\t| 'clusterWorker'\n\nconst MSG_WORKER_STARTED = 'msg_worker_started'\n\nexport const waitForWorker = (worker: Worker, timeoutMs: number) => {\n\tlet ok = false\n\treturn Promise.race([\n\t\tnew Promise(async resolve => {\n\t\t\tconst listener = (message: any) => {\n\t\t\t\tif ('type' in message && message.type === MSG_WORKER_STARTED) {\n\t\t\t\t\tok = true\n\t\t\t\t\tresolve(null)\n\t\t\t\t\tworker.removeListener('message', listener)\n\t\t\t\t}\n\t\t\t}\n\t\t\tawait worker.on('message', listener)\n\t\t}),\n\t\ttimeout(timeoutMs).then(() => {\n\t\t\tif (!ok) {\n\t\t\t\tthrow new Error('Worker start timed out')\n\t\t\t}\n\t\t\treturn true\n\t\t}),\n\t])\n}\n\nexport const notifyWorkerStarted = () =>\n\tprocess.send?.({\n\t\ttype: MSG_WORKER_STARTED,\n\t})\n\nexport class WorkerManager {\n\n\tprivate isTerminating = false\n\n\tprivate workers: Set<Worker> = new Set()\n\n\tpublic async start({ workerCount, env }: { workerCount: number; env?: any }): Promise<void> {\n\t\tif (this.isTerminating) {\n\t\t\tthrow new Error(`Worker manager is terminating`)\n\t\t}\n\t\tfor (let i = 0; i < workerCount; i++) {\n\t\t\tawait this.startWorker(env)\n\t\t\tif (this.isTerminating) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async startWorker(env?: any) {\n\t\tconst worker = cluster.fork(env)\n\t\tworker.on('exit', async (code, signal) => {\n\t\t\tthis.workers.delete(worker)\n\t\t\tif (!this.isTerminating) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log(`Worker ${worker.process.pid} died with signal ${signal}, restarting`)\n\t\t\t\tawait timeout(2000)\n\t\t\t\tawait this.startWorker(env)\n\t\t\t}\n\t\t})\n\t\tthis.workers.add(worker)\n\t\tawait waitForWorker(worker, 15000)\n\t}\n\n\tpublic async terminate(signal: NodeJS.Signals): Promise<void> {\n\t\tif (this.isTerminating) {\n\t\t\tthrow new Error(`Worker manager is terminating`)\n\t\t}\n\t\tthis.isTerminating = true\n\t\tawait Promise.allSettled(Array.from(this.workers).map(async it => {\n\t\t\tif (!it) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.log(`Terminating worker ${it.process.pid}`)\n\t\t\tconst disconnectPromise = new Promise(resolve => it.once('disconnect', resolve))\n\t\t\tit.disconnect()\n\t\t\tawait disconnectPromise\n\t\t\tconst killPromise = new Promise(resolve => it.once('exit', resolve))\n\t\t\tit.kill(signal)\n\t\t\tawait killPromise\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.log(`Worker ${it.process.pid} terminated`)\n\t\t}))\n\t}\n}\n"],"names":["timeout"],"mappings":";;;;;;;AAGa,MAAA,wBAAwB,CAAC,kBACrC,CAAC,gBAAgB,eAAe,QAAQ,WAAW,kBAAkB;AAOtE,MAAM,qBAAqB;AAEd,MAAA,gBAAgB,CAAC,QAAgB,cAAsB;AACnE,MAAI,KAAK;AACT,SAAO,QAAQ,KAAK;AAAA,IACnB,IAAI,QAAQ,OAAM,YAAW;AACtB,YAAA,WAAW,CAAC,YAAiB;AAClC,YAAI,UAAU,WAAW,QAAQ,SAAS,oBAAoB;AACxD,eAAA;AACL,kBAAQ,IAAI;AACL,iBAAA,eAAe,WAAW,QAAQ;AAAA,QAAA;AAAA,MAE3C;AACM,YAAA,OAAO,GAAG,WAAW,QAAQ;AAAA,IAAA,CACnC;AAAA,IACDA,cAAQ,SAAS,EAAE,KAAK,MAAM;AAC7B,UAAI,CAAC,IAAI;AACF,cAAA,IAAI,MAAM,wBAAwB;AAAA,MAAA;AAElC,aAAA;AAAA,IACP,CAAA;AAAA,EAAA,CACD;AACF;AAEa,MAAA,sBAAsB,MAClC,QAAQ,OAAO;AAAA,EACd,MAAM;AACP,CAAC;AAEK,MAAM,cAAc;AAAA,EAApB,cAAA;AAEN,kBAAA,MAAQ,iBAAgB,KAAA;AAEhB,kBAAA,MAAA,+BAA2B,IAAI,CAAA;AAAA,EAAA;AAAA,EAEvC,MAAa,MAAM,EAAE,aAAa,OAA0D;AAC3F,QAAI,KAAK,eAAe;AACjB,YAAA,IAAI,MAAM,+BAA+B;AAAA,IAAA;AAEhD,aAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AAC/B,YAAA,KAAK,YAAY,GAAG;AAC1B,UAAI,KAAK,eAAe;AACvB;AAAA,MAAA;AAAA,IACD;AAAA,EACD;AAAA,EAGD,MAAc,YAAY,KAAW;AAC9B,UAAA,SAAS,QAAQ,KAAK,GAAG;AAC/B,WAAO,GAAG,QAAQ,OAAO,MAAM,WAAW;AACpC,WAAA,QAAQ,OAAO,MAAM;AACtB,UAAA,CAAC,KAAK,eAAe;AAExB,gBAAQ,IAAI,UAAU,OAAO,QAAQ,GAAG,qBAAqB,MAAM,cAAc;AACjF,cAAMA,MAAAA,QAAQ,GAAI;AACZ,cAAA,KAAK,YAAY,GAAG;AAAA,MAAA;AAAA,IAC3B,CACA;AACI,SAAA,QAAQ,IAAI,MAAM;AACjB,UAAA,cAAc,QAAQ,IAAK;AAAA,EAAA;AAAA,EAGlC,MAAa,UAAU,QAAuC;AAC7D,QAAI,KAAK,eAAe;AACjB,YAAA,IAAI,MAAM,+BAA+B;AAAA,IAAA;AAEhD,SAAK,gBAAgB;AACf,UAAA,QAAQ,WAAW,MAAM,KAAK,KAAK,OAAO,EAAE,IAAI,OAAM,OAAM;AACjE,UAAI,CAAC,IAAI;AACR;AAAA,MAAA;AAGD,cAAQ,IAAI,sBAAsB,GAAG,QAAQ,GAAG,EAAE;AAC5C,YAAA,oBAAoB,IAAI,QAAQ,CAAA,YAAW,GAAG,KAAK,cAAc,OAAO,CAAC;AAC/E,SAAG,WAAW;AACR,YAAA;AACA,YAAA,cAAc,IAAI,QAAQ,CAAA,YAAW,GAAG,KAAK,QAAQ,OAAO,CAAC;AACnE,SAAG,KAAK,MAAM;AACR,YAAA;AAEN,cAAQ,IAAI,UAAU,GAAG,QAAQ,GAAG,aAAa;AAAA,IAAA,CACjD,CAAC;AAAA,EAAA;AAEJ;;;;;"}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import cluster from "node:cluster";
|
|
2
|
-
import { timeout } from "./utils.js";
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
5
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
6
|
-
const getClusterProcessType = (isClusterMode) => !isClusterMode ? "singleNode" : cluster.isMaster ? "clusterMaster" : "clusterWorker";
|
|
7
|
-
const MSG_WORKER_STARTED = "msg_worker_started";
|
|
8
|
-
const waitForWorker = (worker, timeoutMs) => {
|
|
9
|
-
let ok = false;
|
|
10
|
-
return Promise.race([
|
|
11
|
-
new Promise(async (resolve) => {
|
|
12
|
-
const listener = (message) => {
|
|
13
|
-
if ("type" in message && message.type === MSG_WORKER_STARTED) {
|
|
14
|
-
ok = true;
|
|
15
|
-
resolve(null);
|
|
16
|
-
worker.removeListener("message", listener);
|
|
17
|
-
}
|
|
18
|
-
};
|
|
19
|
-
await worker.on("message", listener);
|
|
20
|
-
}),
|
|
21
|
-
timeout(timeoutMs).then(() => {
|
|
22
|
-
if (!ok) {
|
|
23
|
-
throw new Error("Worker start timed out");
|
|
24
|
-
}
|
|
25
|
-
return true;
|
|
26
|
-
})
|
|
27
|
-
]);
|
|
28
|
-
};
|
|
29
|
-
const notifyWorkerStarted = () => process.send?.({
|
|
30
|
-
type: MSG_WORKER_STARTED
|
|
31
|
-
});
|
|
32
|
-
class WorkerManager {
|
|
33
|
-
constructor() {
|
|
34
|
-
__publicField(this, "isTerminating", false);
|
|
35
|
-
__publicField(this, "workers", /* @__PURE__ */ new Set());
|
|
36
|
-
}
|
|
37
|
-
async start({ workerCount, env }) {
|
|
38
|
-
if (this.isTerminating) {
|
|
39
|
-
throw new Error(`Worker manager is terminating`);
|
|
40
|
-
}
|
|
41
|
-
for (let i = 0; i < workerCount; i++) {
|
|
42
|
-
await this.startWorker(env);
|
|
43
|
-
if (this.isTerminating) {
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
async startWorker(env) {
|
|
49
|
-
const worker = cluster.fork(env);
|
|
50
|
-
worker.on("exit", async (code, signal) => {
|
|
51
|
-
this.workers.delete(worker);
|
|
52
|
-
if (!this.isTerminating) {
|
|
53
|
-
console.log(`Worker ${worker.process.pid} died with signal ${signal}, restarting`);
|
|
54
|
-
await timeout(2e3);
|
|
55
|
-
await this.startWorker(env);
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
this.workers.add(worker);
|
|
59
|
-
await waitForWorker(worker, 15e3);
|
|
60
|
-
}
|
|
61
|
-
async terminate(signal) {
|
|
62
|
-
if (this.isTerminating) {
|
|
63
|
-
throw new Error(`Worker manager is terminating`);
|
|
64
|
-
}
|
|
65
|
-
this.isTerminating = true;
|
|
66
|
-
await Promise.allSettled(Array.from(this.workers).map(async (it) => {
|
|
67
|
-
if (!it) {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
console.log(`Terminating worker ${it.process.pid}`);
|
|
71
|
-
const disconnectPromise = new Promise((resolve) => it.once("disconnect", resolve));
|
|
72
|
-
it.disconnect();
|
|
73
|
-
await disconnectPromise;
|
|
74
|
-
const killPromise = new Promise((resolve) => it.once("exit", resolve));
|
|
75
|
-
it.kill(signal);
|
|
76
|
-
await killPromise;
|
|
77
|
-
console.log(`Worker ${it.process.pid} terminated`);
|
|
78
|
-
}));
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
export {
|
|
82
|
-
WorkerManager,
|
|
83
|
-
getClusterProcessType,
|
|
84
|
-
notifyWorkerStarted,
|
|
85
|
-
waitForWorker
|
|
86
|
-
};
|
|
87
|
-
//# sourceMappingURL=cluster.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cluster.js","sources":["../../../../packages/engine-server/src/cluster.ts"],"sourcesContent":["import cluster, { Worker } from 'node:cluster'\nimport { timeout } from './utils'\n\nexport const getClusterProcessType = (isClusterMode: boolean): ProcessType =>\n\t!isClusterMode ? 'singleNode' : cluster.isMaster ? 'clusterMaster' : 'clusterWorker'\n\nexport type ProcessType =\n\t| 'singleNode'\n\t| 'clusterMaster'\n\t| 'clusterWorker'\n\nconst MSG_WORKER_STARTED = 'msg_worker_started'\n\nexport const waitForWorker = (worker: Worker, timeoutMs: number) => {\n\tlet ok = false\n\treturn Promise.race([\n\t\tnew Promise(async resolve => {\n\t\t\tconst listener = (message: any) => {\n\t\t\t\tif ('type' in message && message.type === MSG_WORKER_STARTED) {\n\t\t\t\t\tok = true\n\t\t\t\t\tresolve(null)\n\t\t\t\t\tworker.removeListener('message', listener)\n\t\t\t\t}\n\t\t\t}\n\t\t\tawait worker.on('message', listener)\n\t\t}),\n\t\ttimeout(timeoutMs).then(() => {\n\t\t\tif (!ok) {\n\t\t\t\tthrow new Error('Worker start timed out')\n\t\t\t}\n\t\t\treturn true\n\t\t}),\n\t])\n}\n\nexport const notifyWorkerStarted = () =>\n\tprocess.send?.({\n\t\ttype: MSG_WORKER_STARTED,\n\t})\n\nexport class WorkerManager {\n\n\tprivate isTerminating = false\n\n\tprivate workers: Set<Worker> = new Set()\n\n\tpublic async start({ workerCount, env }: { workerCount: number; env?: any }): Promise<void> {\n\t\tif (this.isTerminating) {\n\t\t\tthrow new Error(`Worker manager is terminating`)\n\t\t}\n\t\tfor (let i = 0; i < workerCount; i++) {\n\t\t\tawait this.startWorker(env)\n\t\t\tif (this.isTerminating) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async startWorker(env?: any) {\n\t\tconst worker = cluster.fork(env)\n\t\tworker.on('exit', async (code, signal) => {\n\t\t\tthis.workers.delete(worker)\n\t\t\tif (!this.isTerminating) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log(`Worker ${worker.process.pid} died with signal ${signal}, restarting`)\n\t\t\t\tawait timeout(2000)\n\t\t\t\tawait this.startWorker(env)\n\t\t\t}\n\t\t})\n\t\tthis.workers.add(worker)\n\t\tawait waitForWorker(worker, 15000)\n\t}\n\n\tpublic async terminate(signal: NodeJS.Signals): Promise<void> {\n\t\tif (this.isTerminating) {\n\t\t\tthrow new Error(`Worker manager is terminating`)\n\t\t}\n\t\tthis.isTerminating = true\n\t\tawait Promise.allSettled(Array.from(this.workers).map(async it => {\n\t\t\tif (!it) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.log(`Terminating worker ${it.process.pid}`)\n\t\t\tconst disconnectPromise = new Promise(resolve => it.once('disconnect', resolve))\n\t\t\tit.disconnect()\n\t\t\tawait disconnectPromise\n\t\t\tconst killPromise = new Promise(resolve => it.once('exit', resolve))\n\t\t\tit.kill(signal)\n\t\t\tawait killPromise\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.log(`Worker ${it.process.pid} terminated`)\n\t\t}))\n\t}\n}\n"],"names":[],"mappings":";;;;;AAGa,MAAA,wBAAwB,CAAC,kBACrC,CAAC,gBAAgB,eAAe,QAAQ,WAAW,kBAAkB;AAOtE,MAAM,qBAAqB;AAEd,MAAA,gBAAgB,CAAC,QAAgB,cAAsB;AACnE,MAAI,KAAK;AACT,SAAO,QAAQ,KAAK;AAAA,IACnB,IAAI,QAAQ,OAAM,YAAW;AACtB,YAAA,WAAW,CAAC,YAAiB;AAClC,YAAI,UAAU,WAAW,QAAQ,SAAS,oBAAoB;AACxD,eAAA;AACL,kBAAQ,IAAI;AACL,iBAAA,eAAe,WAAW,QAAQ;AAAA,QAAA;AAAA,MAE3C;AACM,YAAA,OAAO,GAAG,WAAW,QAAQ;AAAA,IAAA,CACnC;AAAA,IACD,QAAQ,SAAS,EAAE,KAAK,MAAM;AAC7B,UAAI,CAAC,IAAI;AACF,cAAA,IAAI,MAAM,wBAAwB;AAAA,MAAA;AAElC,aAAA;AAAA,IACP,CAAA;AAAA,EAAA,CACD;AACF;AAEa,MAAA,sBAAsB,MAClC,QAAQ,OAAO;AAAA,EACd,MAAM;AACP,CAAC;AAEK,MAAM,cAAc;AAAA,EAApB,cAAA;AAEN,kBAAA,MAAQ,iBAAgB,KAAA;AAEhB,kBAAA,MAAA,+BAA2B,IAAI,CAAA;AAAA,EAAA;AAAA,EAEvC,MAAa,MAAM,EAAE,aAAa,OAA0D;AAC3F,QAAI,KAAK,eAAe;AACjB,YAAA,IAAI,MAAM,+BAA+B;AAAA,IAAA;AAEhD,aAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AAC/B,YAAA,KAAK,YAAY,GAAG;AAC1B,UAAI,KAAK,eAAe;AACvB;AAAA,MAAA;AAAA,IACD;AAAA,EACD;AAAA,EAGD,MAAc,YAAY,KAAW;AAC9B,UAAA,SAAS,QAAQ,KAAK,GAAG;AAC/B,WAAO,GAAG,QAAQ,OAAO,MAAM,WAAW;AACpC,WAAA,QAAQ,OAAO,MAAM;AACtB,UAAA,CAAC,KAAK,eAAe;AAExB,gBAAQ,IAAI,UAAU,OAAO,QAAQ,GAAG,qBAAqB,MAAM,cAAc;AACjF,cAAM,QAAQ,GAAI;AACZ,cAAA,KAAK,YAAY,GAAG;AAAA,MAAA;AAAA,IAC3B,CACA;AACI,SAAA,QAAQ,IAAI,MAAM;AACjB,UAAA,cAAc,QAAQ,IAAK;AAAA,EAAA;AAAA,EAGlC,MAAa,UAAU,QAAuC;AAC7D,QAAI,KAAK,eAAe;AACjB,YAAA,IAAI,MAAM,+BAA+B;AAAA,IAAA;AAEhD,SAAK,gBAAgB;AACf,UAAA,QAAQ,WAAW,MAAM,KAAK,KAAK,OAAO,EAAE,IAAI,OAAM,OAAM;AACjE,UAAI,CAAC,IAAI;AACR;AAAA,MAAA;AAGD,cAAQ,IAAI,sBAAsB,GAAG,QAAQ,GAAG,EAAE;AAC5C,YAAA,oBAAoB,IAAI,QAAQ,CAAA,YAAW,GAAG,KAAK,cAAc,OAAO,CAAC;AAC/E,SAAG,WAAW;AACR,YAAA;AACA,YAAA,cAAc,IAAI,QAAQ,CAAA,YAAW,GAAG,KAAK,QAAQ,OAAO,CAAC;AACnE,SAAG,KAAK,MAAM;AACR,YAAA;AAEN,cAAQ,IAAI,UAAU,GAAG,QAAQ,GAAG,aAAa;AAAA,IAAA,CACjD,CAAC;AAAA,EAAA;AAEJ;"}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
const ActionsPlugin = require("@contember/engine-actions");
|
|
3
|
-
const S3Plugin = require("@contember/engine-s3-plugin");
|
|
4
|
-
const VimeoPlugin = require("@contember/engine-vimeo-plugin");
|
|
5
|
-
function loadPlugins() {
|
|
6
|
-
return Promise.resolve([new S3Plugin(), new VimeoPlugin(), new ActionsPlugin()]);
|
|
7
|
-
}
|
|
8
|
-
module.exports = loadPlugins;
|
|
9
|
-
//# sourceMappingURL=loadPlugins.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"loadPlugins.cjs","sources":["../../../../packages/engine-server/src/loadPlugins.ts"],"sourcesContent":["import ActionsPlugin from '@contember/engine-actions'\nimport { Plugin } from '@contember/engine-plugins'\nimport S3Plugin from '@contember/engine-s3-plugin'\nimport VimeoPlugin from '@contember/engine-vimeo-plugin'\n\nexport default function loadPlugins(): Promise<Plugin[]> {\n\treturn Promise.resolve([new S3Plugin(), new VimeoPlugin(), new ActionsPlugin()])\n}\n"],"names":[],"mappings":";;;;AAKA,SAAwB,cAAiC;AACxD,SAAO,QAAQ,QAAQ,CAAC,IAAI,SAAS,GAAG,IAAI,YAAe,GAAA,IAAI,cAAc,CAAC,CAAC;AAChF;;"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import ActionsPlugin from "@contember/engine-actions";
|
|
2
|
-
import S3Plugin from "@contember/engine-s3-plugin";
|
|
3
|
-
import VimeoPlugin from "@contember/engine-vimeo-plugin";
|
|
4
|
-
function loadPlugins() {
|
|
5
|
-
return Promise.resolve([new S3Plugin(), new VimeoPlugin(), new ActionsPlugin()]);
|
|
6
|
-
}
|
|
7
|
-
export {
|
|
8
|
-
loadPlugins as default
|
|
9
|
-
};
|
|
10
|
-
//# sourceMappingURL=loadPlugins.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"loadPlugins.js","sources":["../../../../packages/engine-server/src/loadPlugins.ts"],"sourcesContent":["import ActionsPlugin from '@contember/engine-actions'\nimport { Plugin } from '@contember/engine-plugins'\nimport S3Plugin from '@contember/engine-s3-plugin'\nimport VimeoPlugin from '@contember/engine-vimeo-plugin'\n\nexport default function loadPlugins(): Promise<Plugin[]> {\n\treturn Promise.resolve([new S3Plugin(), new VimeoPlugin(), new ActionsPlugin()])\n}\n"],"names":[],"mappings":";;;AAKA,SAAwB,cAAiC;AACxD,SAAO,QAAQ,QAAQ,CAAC,IAAI,SAAS,GAAG,IAAI,YAAe,GAAA,IAAI,cAAc,CAAC,CAAC;AAChF;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.cjs","sources":["../../../../packages/engine-server/src/utils.ts"],"sourcesContent":["export const timeout = (ms: number) =>\n\tnew Promise(resolve => {\n\t\tsetTimeout(resolve, ms)\n\t})\n"],"names":[],"mappings":";;AAAO,MAAM,UAAU,CAAC,OACvB,IAAI,QAAQ,CAAW,YAAA;AACtB,aAAW,SAAS,EAAE;AACvB,CAAC;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../../../packages/engine-server/src/utils.ts"],"sourcesContent":["export const timeout = (ms: number) =>\n\tnew Promise(resolve => {\n\t\tsetTimeout(resolve, ms)\n\t})\n"],"names":[],"mappings":"AAAO,MAAM,UAAU,CAAC,OACvB,IAAI,QAAQ,CAAW,YAAA;AACtB,aAAW,SAAS,EAAE;AACvB,CAAC;"}
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
const engineHttp = require("@contember/engine-http");
|
|
4
|
-
const loadPlugins = require("./src/loadPlugins.cjs");
|
|
5
|
-
const cluster$1 = require("node:cluster");
|
|
6
|
-
const os = require("node:os");
|
|
7
|
-
const utils = require("./src/utils.cjs");
|
|
8
|
-
const cluster = require("./src/cluster.cjs");
|
|
9
|
-
function _interopNamespaceDefault(e) {
|
|
10
|
-
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
11
|
-
if (e) {
|
|
12
|
-
for (const k in e) {
|
|
13
|
-
if (k !== "default") {
|
|
14
|
-
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
15
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
16
|
-
enumerable: true,
|
|
17
|
-
get: () => e[k]
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
n.default = e;
|
|
23
|
-
return Object.freeze(n);
|
|
24
|
-
}
|
|
25
|
-
const os__namespace = /* @__PURE__ */ _interopNamespaceDefault(os);
|
|
26
|
-
const logger = engineHttp.createDefaultLogger();
|
|
27
|
-
process.on("warning", (message) => {
|
|
28
|
-
logger.warn(message);
|
|
29
|
-
});
|
|
30
|
-
(async () => {
|
|
31
|
-
const isDebug = engineHttp.isDebugMode();
|
|
32
|
-
const version = await engineHttp.getServerVersion();
|
|
33
|
-
engineHttp.printStartInfo({ version, isDebug }, logger);
|
|
34
|
-
const plugins = await loadPlugins();
|
|
35
|
-
const { serverConfig, projectConfigResolver, tenantConfigResolver } = await engineHttp.resolveServerConfig({ plugins, serverConfigSchema: engineHttp.serverConfigSchema });
|
|
36
|
-
if (process.argv[2] === "validate") {
|
|
37
|
-
process.exit(0);
|
|
38
|
-
}
|
|
39
|
-
const sentryhandler = engineHttp.createSentryLoggerHandler(serverConfig.logging?.sentry?.dsn);
|
|
40
|
-
if (sentryhandler !== null) {
|
|
41
|
-
logger.addHandler(sentryhandler);
|
|
42
|
-
}
|
|
43
|
-
const workerConfig = serverConfig.workerCount || 1;
|
|
44
|
-
const workerCount = workerConfig === "auto" ? os__namespace.cpus().length : Number(workerConfig);
|
|
45
|
-
const isClusterMode = serverConfig.workerCount !== void 0;
|
|
46
|
-
const processType = cluster.getClusterProcessType(isClusterMode);
|
|
47
|
-
const container = engineHttp.createContainer({
|
|
48
|
-
debugMode: isDebug,
|
|
49
|
-
serverConfig,
|
|
50
|
-
projectConfigResolver,
|
|
51
|
-
tenantConfigResolver,
|
|
52
|
-
plugins,
|
|
53
|
-
processType,
|
|
54
|
-
version,
|
|
55
|
-
logger
|
|
56
|
-
});
|
|
57
|
-
let initializedProjects = [];
|
|
58
|
-
const terminationJobs = [];
|
|
59
|
-
engineHttp.listenOnProcessTermination(terminationJobs, logger);
|
|
60
|
-
if (cluster$1.isMaster) {
|
|
61
|
-
const monitoringPort = serverConfig.monitoringPort;
|
|
62
|
-
const monitoringServer = container.monitoringKoa.listen(monitoringPort, () => {
|
|
63
|
-
logger.info(`Monitoring running on http://localhost:${monitoringPort}`);
|
|
64
|
-
});
|
|
65
|
-
terminationJobs.push(async () => {
|
|
66
|
-
await new Promise((resolve) => monitoringServer.close(resolve));
|
|
67
|
-
logger.info("Monitoring server terminated");
|
|
68
|
-
});
|
|
69
|
-
if (!serverConfig.projectGroup) {
|
|
70
|
-
initializedProjects = await container.initializer.initialize();
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
const port = serverConfig.port;
|
|
74
|
-
const printStarted = () => {
|
|
75
|
-
if (serverConfig.projectGroup) {
|
|
76
|
-
logger.info("Contember Cloud running");
|
|
77
|
-
} else {
|
|
78
|
-
logger.info(`Contember API running on http://localhost:${port}`);
|
|
79
|
-
}
|
|
80
|
-
if (initializedProjects.length) {
|
|
81
|
-
logger.info(`Initialized projects: ${initializedProjects.join(", ")}`);
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
const startApplication = async () => {
|
|
85
|
-
const httpServerPromise = container.application.listen();
|
|
86
|
-
terminationJobs.push(async () => {
|
|
87
|
-
await (await httpServerPromise).close();
|
|
88
|
-
logger.info("API server terminated");
|
|
89
|
-
});
|
|
90
|
-
await httpServerPromise;
|
|
91
|
-
};
|
|
92
|
-
const startWorker = async (workerName) => {
|
|
93
|
-
const worker = container.applicationWorkers.getWorker(workerName);
|
|
94
|
-
const runningWorker = worker.run({
|
|
95
|
-
logger,
|
|
96
|
-
onError: (e) => {
|
|
97
|
-
logger.crit(e);
|
|
98
|
-
process.exit(1);
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
terminationJobs.push(async () => {
|
|
102
|
-
(await runningWorker).end();
|
|
103
|
-
});
|
|
104
|
-
await runningWorker;
|
|
105
|
-
logger.info(`Contember Worker ${workerName} started.`);
|
|
106
|
-
};
|
|
107
|
-
const applicationWorker = serverConfig.applicationWorker;
|
|
108
|
-
if (applicationWorker && applicationWorker !== "all") {
|
|
109
|
-
await startWorker(applicationWorker);
|
|
110
|
-
if (isClusterMode) {
|
|
111
|
-
cluster.notifyWorkerStarted();
|
|
112
|
-
}
|
|
113
|
-
} else if (isClusterMode) {
|
|
114
|
-
if (cluster$1.isMaster) {
|
|
115
|
-
logger.info(`Master ${process.pid} is running`);
|
|
116
|
-
const workerManager = new cluster.WorkerManager();
|
|
117
|
-
terminationJobs.push(async ({ signal }) => {
|
|
118
|
-
await workerManager.terminate(signal);
|
|
119
|
-
logger.info("Workers terminated");
|
|
120
|
-
});
|
|
121
|
-
await workerManager.start({ workerCount });
|
|
122
|
-
if (applicationWorker === "all") {
|
|
123
|
-
for (const workerName of container.applicationWorkers.getWorkerNames()) {
|
|
124
|
-
await workerManager.start({
|
|
125
|
-
workerCount,
|
|
126
|
-
env: {
|
|
127
|
-
CONTEMBER_APPLICATION_WORKER: workerName
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
printStarted();
|
|
133
|
-
} else {
|
|
134
|
-
logger.info(`Starting worker ${process.pid}`);
|
|
135
|
-
process.on("disconnect", () => utils.timeout(0));
|
|
136
|
-
await startApplication();
|
|
137
|
-
cluster.notifyWorkerStarted();
|
|
138
|
-
}
|
|
139
|
-
} else {
|
|
140
|
-
await startApplication();
|
|
141
|
-
if (applicationWorker === "all") {
|
|
142
|
-
for (const workerName of container.applicationWorkers.getWorkerNames()) {
|
|
143
|
-
await startWorker(workerName);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
printStarted();
|
|
147
|
-
}
|
|
148
|
-
})().catch((e) => {
|
|
149
|
-
logger.crit(e);
|
|
150
|
-
process.exit(1);
|
|
151
|
-
});
|
|
152
|
-
//# sourceMappingURL=start.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"start.cjs","sources":["../../../packages/engine-server/src/start.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport {\n\tcreateContainer,\n\tcreateDefaultLogger,\n\tcreateSentryLoggerHandler,\n\tgetServerVersion,\n\tisDebugMode,\n\tlistenOnProcessTermination,\n\tprintStartInfo,\n\tresolveServerConfig,\n\tserverConfigSchema,\n\tTerminationJob,\n} from '@contember/engine-http'\nimport loadPlugins from './loadPlugins'\nimport cluster from 'node:cluster'\nimport * as os from 'node:os'\nimport { timeout } from './utils'\nimport { getClusterProcessType, notifyWorkerStarted, WorkerManager } from './cluster'\n\nconst logger = createDefaultLogger()\nprocess.on('warning', message => {\n\tlogger.warn(message)\n})\n;(async () => {\n\tconst isDebug = isDebugMode()\n\n\tconst version = await getServerVersion()\n\tprintStartInfo({ version, isDebug }, logger)\n\tconst plugins = await loadPlugins()\n\tconst { serverConfig, projectConfigResolver, tenantConfigResolver } = await resolveServerConfig({ plugins, serverConfigSchema })\n\n\tif (process.argv[2] === 'validate') {\n\t\tprocess.exit(0)\n\t}\n\n\tconst sentryhandler = createSentryLoggerHandler(serverConfig.logging?.sentry?.dsn)\n\tif (sentryhandler !== null) {\n\t\tlogger.addHandler(sentryhandler)\n\t}\n\n\tconst workerConfig = serverConfig.workerCount || 1\n\n\tconst workerCount = workerConfig === 'auto' ? os.cpus().length : Number(workerConfig)\n\tconst isClusterMode = serverConfig.workerCount !== undefined\n\n\tconst processType = getClusterProcessType(isClusterMode)\n\n\tconst container = createContainer({\n\t\tdebugMode: isDebug,\n\t\tserverConfig,\n\t\tprojectConfigResolver,\n\t\ttenantConfigResolver,\n\t\tplugins,\n\t\tprocessType,\n\t\tversion,\n\t\tlogger,\n\t})\n\n\tlet initializedProjects: string[] = []\n\tconst terminationJobs: TerminationJob[] = []\n\tlistenOnProcessTermination(terminationJobs, logger)\n\n\tif (cluster.isMaster) {\n\t\tconst monitoringPort = serverConfig.monitoringPort\n\t\tconst monitoringServer = container.monitoringKoa.listen(monitoringPort, () => {\n\t\t\tlogger.info(`Monitoring running on http://localhost:${monitoringPort}`)\n\t\t})\n\t\tterminationJobs.push(async () => {\n\t\t\tawait new Promise<any>(resolve => monitoringServer.close(resolve))\n\t\t\tlogger.info('Monitoring server terminated')\n\t\t})\n\t\tif (!serverConfig.projectGroup) {\n\t\t\tinitializedProjects = await container.initializer.initialize()\n\t\t}\n\t}\n\n\tconst port = serverConfig.port\n\tconst printStarted = () => {\n\t\tif (serverConfig.projectGroup) {\n\t\t\tlogger.info('Contember Cloud running')\n\t\t} else {\n\t\t\tlogger.info(`Contember API running on http://localhost:${port}`)\n\t\t}\n\t\tif (initializedProjects.length) {\n\t\t\tlogger.info(`Initialized projects: ${initializedProjects.join(', ')}`)\n\t\t}\n\t}\n\n\tconst startApplication = async () => {\n\t\tconst httpServerPromise = container.application.listen()\n\t\tterminationJobs.push(async () => {\n\t\t\tawait (await httpServerPromise).close()\n\t\t\tlogger.info('API server terminated')\n\t\t})\n\t\tawait httpServerPromise\n\t}\n\n\tconst startWorker = async (workerName: string) => {\n\t\tconst worker = container.applicationWorkers.getWorker(workerName)\n\t\tconst runningWorker = worker.run({\n\t\t\tlogger,\n\t\t\tonError: e => {\n\t\t\t\tlogger.crit(e)\n\t\t\t\tprocess.exit(1)\n\t\t\t},\n\t\t})\n\t\tterminationJobs.push(async () => {\n\t\t\t(await runningWorker).end()\n\t\t})\n\t\tawait runningWorker\n\t\tlogger.info(`Contember Worker ${workerName} started.`)\n\n\t}\n\n\tconst applicationWorker = serverConfig.applicationWorker\n\tif (applicationWorker && applicationWorker !== 'all') {\n\t\tawait startWorker(applicationWorker)\n\t\tif (isClusterMode) {\n\t\t\tnotifyWorkerStarted()\n\t\t}\n\t} else if (isClusterMode) {\n\t\tif (cluster.isMaster) {\n\t\t\tlogger.info(`Master ${process.pid} is running`)\n\t\t\tconst workerManager = new WorkerManager()\n\t\t\tterminationJobs.push(async ({ signal }) => {\n\t\t\t\tawait workerManager.terminate(signal)\n\t\t\t\tlogger.info('Workers terminated')\n\t\t\t})\n\n\t\t\tawait workerManager.start({ workerCount })\n\n\t\t\tif (applicationWorker === 'all') {\n\t\t\t\tfor (const workerName of container.applicationWorkers.getWorkerNames()) {\n\t\t\t\t\tawait workerManager.start({\n\t\t\t\t\t\tworkerCount, env: {\n\t\t\t\t\t\t\tCONTEMBER_APPLICATION_WORKER: workerName,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t\tprintStarted()\n\t\t} else {\n\t\t\tlogger.info(`Starting worker ${process.pid}`)\n\n\t\t\t// this line somehow ensures, that worker waits for termination of all jobs\n\t\t\tprocess.on('disconnect', () => timeout(0))\n\n\t\t\tawait startApplication()\n\t\t\tnotifyWorkerStarted()\n\t\t}\n\t} else {\n\t\tawait startApplication()\n\t\tif (applicationWorker === 'all') {\n\t\t\tfor (const workerName of container.applicationWorkers.getWorkerNames()) {\n\t\t\t\tawait startWorker(workerName)\n\t\t\t}\n\t\t}\n\t\tprintStarted()\n\t}\n\n})().catch(e => {\n\tlogger.crit(e)\n\tprocess.exit(1)\n})\n"],"names":["createDefaultLogger","isDebugMode","getServerVersion","printStartInfo","resolveServerConfig","serverConfigSchema","createSentryLoggerHandler","os","getClusterProcessType","createContainer","listenOnProcessTermination","cluster","notifyWorkerStarted","WorkerManager","timeout"],"mappings":"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"}
|