lupine.api 1.1.51 → 1.1.52
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/admin/admin-release.tsx +37 -2
- package/package.json +1 -1
- package/src/admin-api/admin-auth.ts +15 -14
- package/src/admin-api/admin-release.ts +58 -0
- package/src/app/app-message.ts +15 -7
- package/src/app/app-restart.ts +54 -0
- package/src/app/app-start.ts +27 -7
- package/src/app/process-dev-requests.ts +21 -8
- package/src/app/web-server.ts +4 -2
package/admin/admin-release.tsx
CHANGED
|
@@ -284,7 +284,7 @@ export const AdminReleasePage = () => {
|
|
|
284
284
|
isLocal,
|
|
285
285
|
});
|
|
286
286
|
const dataResponse = await response.json;
|
|
287
|
-
console.log('
|
|
287
|
+
console.log('refresh-cache', dataResponse);
|
|
288
288
|
if (!dataResponse || dataResponse.status !== 'ok') {
|
|
289
289
|
NotificationMessage.sendMessage(dataResponse.message || 'Failed to refresh cache', NotificationColor.Error);
|
|
290
290
|
return;
|
|
@@ -293,6 +293,35 @@ export const AdminReleasePage = () => {
|
|
|
293
293
|
NotificationMessage.sendMessage('Cache refreshed successfully', NotificationColor.Success);
|
|
294
294
|
};
|
|
295
295
|
|
|
296
|
+
const onRestartAppLocal = async () => {
|
|
297
|
+
return onRestartApp(true);
|
|
298
|
+
};
|
|
299
|
+
const onRestartAppRemote = async () => {
|
|
300
|
+
return onRestartApp(false);
|
|
301
|
+
};
|
|
302
|
+
const onRestartApp = async (isLocal?: boolean) => {
|
|
303
|
+
const data = getDomData();
|
|
304
|
+
if (!isLocal) {
|
|
305
|
+
if (!data.targetUrl || !data.accessToken) {
|
|
306
|
+
NotificationMessage.sendMessage('Please fill in all fields', NotificationColor.Error);
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const response = await getRenderPageProps().renderPageFunctions.fetchData('/api/admin/release/restart-app', {
|
|
312
|
+
...data,
|
|
313
|
+
isLocal,
|
|
314
|
+
});
|
|
315
|
+
const dataResponse = await response.json;
|
|
316
|
+
console.log('restart-app', dataResponse);
|
|
317
|
+
if (!dataResponse || dataResponse.status !== 'ok') {
|
|
318
|
+
NotificationMessage.sendMessage(dataResponse.message || 'Failed to Restart App', NotificationColor.Error);
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
domLog.value = <pre>{JSON.stringify(dataResponse, null, 2)}</pre>;
|
|
322
|
+
NotificationMessage.sendMessage('Restart App successfully', NotificationColor.Success);
|
|
323
|
+
};
|
|
324
|
+
|
|
296
325
|
const ref: RefProps = {
|
|
297
326
|
onLoad: async () => {
|
|
298
327
|
const data = JSON.parse(localStorage.getItem('admin-release') || '{}');
|
|
@@ -321,9 +350,15 @@ export const AdminReleasePage = () => {
|
|
|
321
350
|
<button onClick={onRefreshCacheRemote} class='button-base mr-m'>
|
|
322
351
|
Refresh Cache (Remote)
|
|
323
352
|
</button>
|
|
324
|
-
<button onClick={
|
|
353
|
+
<button onClick={onRestartAppRemote} class='button-base mr-m color-red'>
|
|
354
|
+
Restart App (Remote)
|
|
355
|
+
</button>
|
|
356
|
+
<button onClick={onRefreshCacheLocal} class='button-base mr-m'>
|
|
325
357
|
Refresh Cache (Local)
|
|
326
358
|
</button>
|
|
359
|
+
<button onClick={onRestartAppLocal} class='button-base color-red'>
|
|
360
|
+
Restart App (Local)
|
|
361
|
+
</button>
|
|
327
362
|
</div>
|
|
328
363
|
{domUpdate.node}
|
|
329
364
|
{domLog.node}
|
package/package.json
CHANGED
|
@@ -69,14 +69,15 @@ export const devAdminAuth = async (req: ServerRequest, res: ServerResponse) => {
|
|
|
69
69
|
ApiHelper.sendJson(req, res, response);
|
|
70
70
|
return true;
|
|
71
71
|
}
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
72
|
+
// on set app cookie when login, not every time
|
|
73
|
+
// // if it's dev admin, then set app admin cookie as well
|
|
74
|
+
// let addLoginResponse = {};
|
|
75
|
+
// const appAdminHookSetCookie = adminApiHelper.getAppAdminHookSetCookie();
|
|
76
|
+
// if (appAdminHookSetCookie) {
|
|
77
|
+
// addLoginResponse = await appAdminHookSetCookie(req, res, devAdminSession.u);
|
|
78
|
+
// }
|
|
78
79
|
const response = {
|
|
79
|
-
...addLoginResponse,
|
|
80
|
+
// ...addLoginResponse,
|
|
80
81
|
status: 'ok',
|
|
81
82
|
message: langHelper.getLang('shared:login_success'),
|
|
82
83
|
devLogin: CryptoUtils.encrypt(JSON.stringify(devAdminSession), cryptoKey),
|
|
@@ -109,13 +110,13 @@ export const devAdminAuth = async (req: ServerRequest, res: ServerResponse) => {
|
|
|
109
110
|
message: langHelper.getLang('shared:login_success'),
|
|
110
111
|
devLogin: tokenCookie,
|
|
111
112
|
};
|
|
112
|
-
req.locals.setCookie('_token', tokenCookie, {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
});
|
|
113
|
+
// req.locals.setCookie('_token', tokenCookie, {
|
|
114
|
+
// expireDays: 360,
|
|
115
|
+
// path: '/',
|
|
116
|
+
// httpOnly: false,
|
|
117
|
+
// secure: true,
|
|
118
|
+
// sameSite: 'none',
|
|
119
|
+
// });
|
|
119
120
|
ApiHelper.sendJson(req, res, response);
|
|
120
121
|
return true;
|
|
121
122
|
}
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
adminApiHelper,
|
|
12
12
|
processRefreshCache,
|
|
13
13
|
apiStorage,
|
|
14
|
+
processRestartApp,
|
|
14
15
|
} from 'lupine.api';
|
|
15
16
|
import path from 'path';
|
|
16
17
|
import { needDevAdminSession } from './admin-auth';
|
|
@@ -36,11 +37,13 @@ export class AdminRelease implements IApiBase {
|
|
|
36
37
|
this.router.use('/view-log', needDevAdminSession, this.viewLog.bind(this));
|
|
37
38
|
// called online or by clients
|
|
38
39
|
this.router.use('/refresh-cache', needDevAdminSession, this.refreshCache.bind(this));
|
|
40
|
+
this.router.use('/restart-app', needDevAdminSession, this.restartApp.bind(this));
|
|
39
41
|
|
|
40
42
|
// ...ByClient will verify credentials from post, so it doesn't need AdminSession
|
|
41
43
|
this.router.use('/byClientCheck', this.byClientCheck.bind(this));
|
|
42
44
|
this.router.use('/byClientUpdate', this.byClientUpdate.bind(this));
|
|
43
45
|
this.router.use('/byClientRefreshCache', this.byClientRefreshCache.bind(this));
|
|
46
|
+
this.router.use('/byClientRestartApp', this.byClientRestartApp.bind(this));
|
|
44
47
|
this.router.use('/byClientViewLog', this.byClientViewLog.bind(this));
|
|
45
48
|
}
|
|
46
49
|
|
|
@@ -126,6 +129,47 @@ export class AdminRelease implements IApiBase {
|
|
|
126
129
|
return true;
|
|
127
130
|
}
|
|
128
131
|
|
|
132
|
+
async restartApp(req: ServerRequest, res: ServerResponse) {
|
|
133
|
+
// check whether it's from online admin
|
|
134
|
+
const json = await adminApiHelper.getDevAdminFromCookie(req, res, false);
|
|
135
|
+
const jsonData = req.locals.json();
|
|
136
|
+
if (json && jsonData && !Array.isArray(jsonData) && jsonData.isLocal) {
|
|
137
|
+
await processRestartApp(req);
|
|
138
|
+
const response = {
|
|
139
|
+
status: 'ok',
|
|
140
|
+
message: 'Restart app successfully.',
|
|
141
|
+
};
|
|
142
|
+
ApiHelper.sendJson(req, res, response);
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const data = await this.chkData(jsonData, req, res, true);
|
|
147
|
+
if (!data) return true;
|
|
148
|
+
|
|
149
|
+
let targetUrl = data.targetUrl as string;
|
|
150
|
+
if (targetUrl.endsWith('/')) {
|
|
151
|
+
targetUrl = targetUrl.slice(0, -1);
|
|
152
|
+
}
|
|
153
|
+
const remoteData = await fetch(targetUrl + '/api/admin/release/byClientRestartApp', {
|
|
154
|
+
method: 'POST',
|
|
155
|
+
body: JSON.stringify(data),
|
|
156
|
+
});
|
|
157
|
+
const resultText = await remoteData.text();
|
|
158
|
+
let remoteResult: any;
|
|
159
|
+
try {
|
|
160
|
+
remoteResult = JSON.parse(resultText);
|
|
161
|
+
} catch (e: any) {
|
|
162
|
+
remoteResult = { status: 'error', message: resultText };
|
|
163
|
+
}
|
|
164
|
+
const response = {
|
|
165
|
+
status: 'ok',
|
|
166
|
+
message: 'check.',
|
|
167
|
+
...remoteResult,
|
|
168
|
+
};
|
|
169
|
+
ApiHelper.sendJson(req, res, response);
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
|
|
129
173
|
public async chkData(data: any, req: ServerRequest, res: ServerResponse, chkCredential: boolean) {
|
|
130
174
|
// add access token
|
|
131
175
|
if (!data || Array.isArray(data) || typeof data !== 'object' || !data.accessToken || !data.targetUrl) {
|
|
@@ -569,4 +613,18 @@ export class AdminRelease implements IApiBase {
|
|
|
569
613
|
ApiHelper.sendJson(req, res, response);
|
|
570
614
|
return true;
|
|
571
615
|
}
|
|
616
|
+
|
|
617
|
+
async byClientRestartApp(req: ServerRequest, res: ServerResponse) {
|
|
618
|
+
const jsonData = req.locals.json();
|
|
619
|
+
const data = await this.chkData(jsonData, req, res, true);
|
|
620
|
+
if (!data) return true;
|
|
621
|
+
|
|
622
|
+
await processRestartApp(req);
|
|
623
|
+
const response = {
|
|
624
|
+
status: 'ok',
|
|
625
|
+
message: 'Restart app successfully.',
|
|
626
|
+
};
|
|
627
|
+
ApiHelper.sendJson(req, res, response);
|
|
628
|
+
return true;
|
|
629
|
+
}
|
|
572
630
|
}
|
package/src/app/app-message.ts
CHANGED
|
@@ -2,6 +2,7 @@ import cluster from 'cluster';
|
|
|
2
2
|
import { Logger, LogWriter, LogWriterMessageId } from '../lib';
|
|
3
3
|
import { processDebugMessage } from './process-dev-requests';
|
|
4
4
|
import { cleanupAndExit } from './cleanup-exit';
|
|
5
|
+
import { restartApp } from './app-restart';
|
|
5
6
|
|
|
6
7
|
export type AppMessageProps = {
|
|
7
8
|
id: string;
|
|
@@ -78,15 +79,22 @@ export const processMessageFromWorker = (msgObject: AppMessageProps) => {
|
|
|
78
79
|
logger.debug(
|
|
79
80
|
`Message from worker ${cluster.worker?.id}, message: ${msgObject.message}, appName: ${msgObject.appName}`
|
|
80
81
|
);
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
82
|
+
if (msgObject.message === 'restartApp') {
|
|
83
|
+
restartApp();
|
|
84
|
+
return;
|
|
85
|
+
} else if (msgObject.message === 'refresh') {
|
|
86
|
+
broadcast(msgObject);
|
|
87
|
+
} else if (msgObject.message === 'shutdown') {
|
|
88
|
+
broadcast(msgObject);
|
|
89
|
+
// if it's shutdown, the primary process will exit
|
|
90
|
+
setTimeout(async () => {
|
|
91
|
+
console.log(`[server primary] Received shutdown command.`, cluster.workers);
|
|
92
|
+
await cleanupAndExit();
|
|
87
93
|
}, 100);
|
|
94
|
+
} else {
|
|
95
|
+
logger.warn(`Unknown message: ${msgObject.id}`);
|
|
88
96
|
}
|
|
89
97
|
} else {
|
|
90
|
-
logger.warn(`Unknown message: ${msgObject.id}`);
|
|
98
|
+
logger.warn(`Unknown message id: ${msgObject.id}`);
|
|
91
99
|
}
|
|
92
100
|
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import cluster from 'cluster';
|
|
2
|
+
import { spawn } from 'child_process';
|
|
3
|
+
import { appStorage } from './app-shared-storage';
|
|
4
|
+
import { AppMessageProps, processMessageFromWorker } from './app-message';
|
|
5
|
+
|
|
6
|
+
export const _restartApp = {
|
|
7
|
+
isRestarting: false,
|
|
8
|
+
};
|
|
9
|
+
export const restartApp = async () => {
|
|
10
|
+
if (!cluster.isPrimary) {
|
|
11
|
+
console.warn(`restartApp: shouldn't come here`);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
await appStorage.save('', true);
|
|
16
|
+
console.log(`Old app ${process.pid} sends SIGTERM to all workors.`);
|
|
17
|
+
// const closeAll = () => {
|
|
18
|
+
// _restartApp.isRestarting = true;
|
|
19
|
+
|
|
20
|
+
// return Object.values(cluster.workers!).map(
|
|
21
|
+
// (w) =>
|
|
22
|
+
// new Promise((resolve) => {
|
|
23
|
+
// console.log(`Sending SIGTERM to workor ${w!.id}.`);
|
|
24
|
+
// w!.once('exit', resolve);
|
|
25
|
+
// w!.kill('SIGTERM');
|
|
26
|
+
// })
|
|
27
|
+
// );
|
|
28
|
+
// };
|
|
29
|
+
// await Promise.all(closeAll());
|
|
30
|
+
|
|
31
|
+
console.log(`Old app ${process.pid} starts new app ${process.execPath}`, process.argv);
|
|
32
|
+
// spawn(process.execPath, process.argv.slice(1), {
|
|
33
|
+
// stdio: 'inherit',
|
|
34
|
+
// env: { ...process.env, RESTARTING: '1' },
|
|
35
|
+
// });
|
|
36
|
+
|
|
37
|
+
console.log(`Old app ${process.pid} exists.`);
|
|
38
|
+
// setTimeout(process.exit, 3000);
|
|
39
|
+
if (!process.send) {
|
|
40
|
+
console.log(`The primary process is not focked from loader, so cannot restart.`);
|
|
41
|
+
} else {
|
|
42
|
+
process.send({ id: 'debug', message: 'restartApp' });
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// this is primary, and receive messages from loader
|
|
47
|
+
export const receiveMessageFromLoader = () => {
|
|
48
|
+
process.on('message', async (msg: AppMessageProps) => {
|
|
49
|
+
if (msg?.id === 'debug' && msg?.message === 'shutdown') {
|
|
50
|
+
console.log(`App ${process.pid}: received shutdown message from loader.`);
|
|
51
|
+
processMessageFromWorker(msg);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
};
|
package/src/app/app-start.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { AppStartProps, InitStartProps, AppCacheGlobal, AppCacheKeys } from '../
|
|
|
9
9
|
import { appStorage } from './app-shared-storage';
|
|
10
10
|
import { HostToPath } from './host-to-path';
|
|
11
11
|
import { cleanupAndExit } from './cleanup-exit';
|
|
12
|
+
import { _restartApp, receiveMessageFromLoader } from './app-restart';
|
|
12
13
|
|
|
13
14
|
// Don't use logger before set process message
|
|
14
15
|
class AppStart {
|
|
@@ -16,10 +17,16 @@ class AppStart {
|
|
|
16
17
|
webServer: WebServer | undefined;
|
|
17
18
|
|
|
18
19
|
getWorkerId() {
|
|
19
|
-
return cluster.worker ? cluster.worker.id :
|
|
20
|
+
return cluster.worker ? cluster.worker.id : -1;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
async start(props: AppStartProps, webServer?: WebServer) {
|
|
24
|
+
// if it's started from spawn, wait for old master to clear ports
|
|
25
|
+
if (cluster.isPrimary && process.env.RESTARTING === '1') {
|
|
26
|
+
console.log(`New app ${process.pid} RESTARTING.`);
|
|
27
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
28
|
+
}
|
|
29
|
+
|
|
23
30
|
this.debug = props.debug;
|
|
24
31
|
this.bindProcess();
|
|
25
32
|
|
|
@@ -58,14 +65,20 @@ class AppStart {
|
|
|
58
65
|
const numCPUs = props.debug ? 1 : require('os').cpus().length;
|
|
59
66
|
console.log(`Master Process is trying to fork ${numCPUs} processes`);
|
|
60
67
|
|
|
68
|
+
receiveMessageFromLoader();
|
|
69
|
+
|
|
61
70
|
for (let i = 0; i < numCPUs; i++) {
|
|
62
71
|
let worker = cluster.fork();
|
|
63
72
|
worker.on('message', processMessageFromWorker);
|
|
64
73
|
}
|
|
65
74
|
|
|
66
75
|
cluster.on('death', (worker: any) => {
|
|
67
|
-
|
|
68
|
-
|
|
76
|
+
if (!_restartApp.isRestarting) {
|
|
77
|
+
console.log(`Worker ${worker.pid} died; starting a new one...`);
|
|
78
|
+
cluster.fork();
|
|
79
|
+
} else {
|
|
80
|
+
console.log(`Worker ${worker.pid} exited during restart`);
|
|
81
|
+
}
|
|
69
82
|
});
|
|
70
83
|
}
|
|
71
84
|
}
|
|
@@ -82,7 +95,7 @@ class AppStart {
|
|
|
82
95
|
|
|
83
96
|
// do something when app is closing
|
|
84
97
|
process.on('beforeExit', async () => {
|
|
85
|
-
cleanupAndExit();
|
|
98
|
+
await cleanupAndExit();
|
|
86
99
|
});
|
|
87
100
|
process.on('exit', (ret) => {
|
|
88
101
|
console.log(`${process.pid} - Process on exit, code: ${ret}`);
|
|
@@ -103,14 +116,21 @@ class AppStart {
|
|
|
103
116
|
const sslKeyPath = config.sslKeyPath || '';
|
|
104
117
|
const sslCrtPath = config.sslCrtPath || '';
|
|
105
118
|
|
|
106
|
-
console.log(
|
|
119
|
+
console.log(`${process.pid} - Starting Web Server, httpPort: ${httpPort}, httpsPort: ${httpsPort}`);
|
|
107
120
|
// for dev to refresh the FE or stop the server
|
|
108
121
|
if (this.debug) {
|
|
109
122
|
WebProcessor.enableDebug('/debug', processDevRequests);
|
|
110
123
|
}
|
|
111
124
|
|
|
112
|
-
httpPort && this.webServer!.startHttp(httpPort, bindIp);
|
|
113
|
-
httpsPort && this.webServer!.startHttps(httpsPort, bindIp, sslKeyPath, sslCrtPath);
|
|
125
|
+
const httpServer = httpPort && this.webServer!.startHttp(httpPort, bindIp);
|
|
126
|
+
const heepsServer = httpsPort && this.webServer!.startHttps(httpsPort, bindIp, sslKeyPath, sslCrtPath);
|
|
127
|
+
|
|
128
|
+
process.on("SIGTERM", () => {
|
|
129
|
+
console.log(`${process.pid} - Worker closing servers...`);
|
|
130
|
+
httpServer && httpServer.close();
|
|
131
|
+
heepsServer && heepsServer.close();
|
|
132
|
+
});
|
|
133
|
+
|
|
114
134
|
}
|
|
115
135
|
}
|
|
116
136
|
|
|
@@ -5,6 +5,7 @@ import { appLoader } from './app-loader';
|
|
|
5
5
|
import { DebugService } from '../api/debug-service';
|
|
6
6
|
import { AppCacheGlobal, AppCacheKeys, getAppCache, ServerRequest } from '../models';
|
|
7
7
|
import { cleanupAndExit } from './cleanup-exit';
|
|
8
|
+
import { restartApp } from './app-restart';
|
|
8
9
|
const logger = new Logger('process-dev-requests');
|
|
9
10
|
|
|
10
11
|
function deleteRequireCache(moduleName: string) {
|
|
@@ -42,10 +43,10 @@ export const processDebugMessage = async (msgObject: any) => {
|
|
|
42
43
|
// this only works in debug mode (no clusters)
|
|
43
44
|
DebugService.broadcastRefresh();
|
|
44
45
|
}
|
|
45
|
-
if (msgObject.id === 'debug' && msgObject.message === '
|
|
46
|
-
// Only when it's debug mode, it can go here, otherwise
|
|
47
|
-
console.log(`[server] Received
|
|
48
|
-
cleanupAndExit();
|
|
46
|
+
if (msgObject.id === 'debug' && msgObject.message === 'shutdown') {
|
|
47
|
+
// Only when it's debug mode, it can go here, otherwise shutdown should be processed in processMessageFromWorker
|
|
48
|
+
console.log(`[server] Received shutdown command.`);
|
|
49
|
+
await cleanupAndExit();
|
|
49
50
|
}
|
|
50
51
|
};
|
|
51
52
|
|
|
@@ -63,6 +64,18 @@ export async function processRefreshCache(req: ServerRequest) {
|
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
66
|
|
|
67
|
+
export async function processRestartApp(req: ServerRequest) {
|
|
68
|
+
// if this is a child process, we need to notice parent process to broadcast to all clients to refresh
|
|
69
|
+
if (process.send) {
|
|
70
|
+
// send message to Primary to handle it
|
|
71
|
+
process.send({ id: 'debug', message: 'restartApp' });
|
|
72
|
+
}
|
|
73
|
+
// in case if it's only one process (primary process)
|
|
74
|
+
else {
|
|
75
|
+
await restartApp();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
66
79
|
// this is only for local development
|
|
67
80
|
export async function processDevRequests(req: ServerRequest, res: ServerResponse, rootUrl?: string) {
|
|
68
81
|
res.end();
|
|
@@ -71,15 +84,15 @@ export async function processDevRequests(req: ServerRequest, res: ServerResponse
|
|
|
71
84
|
console.log(`[server] Ignore request from: `, req.url, address.address);
|
|
72
85
|
return true;
|
|
73
86
|
}
|
|
74
|
-
if (req.url === '/debug/
|
|
75
|
-
console.log(`[server] Received
|
|
87
|
+
if (req.url === '/debug/shutdown') {
|
|
88
|
+
console.log(`[server] Received shutdown command.`);
|
|
76
89
|
if (process.send) {
|
|
77
90
|
// send to parent process to kill all
|
|
78
|
-
process.send({ id: 'debug', message: '
|
|
91
|
+
process.send({ id: 'debug', message: 'shutdown' });
|
|
79
92
|
}
|
|
80
93
|
// if it's debug mode (only one process)
|
|
81
94
|
else if (getAppCache().get(AppCacheGlobal, AppCacheKeys.APP_DEBUG) === true) {
|
|
82
|
-
await processDebugMessage({ id: 'debug', message: '
|
|
95
|
+
await processDebugMessage({ id: 'debug', message: 'shutdown' });
|
|
83
96
|
}
|
|
84
97
|
} else if (req.url === '/debug/refresh') {
|
|
85
98
|
await processRefreshCache(req);
|
package/src/app/web-server.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { IncomingMessage, ServerResponse } from 'http';
|
|
|
8
8
|
import { Duplex } from 'stream';
|
|
9
9
|
import { WebProcessor } from './web-processor';
|
|
10
10
|
import { DebugService } from '../api/debug-service';
|
|
11
|
+
import cluster from 'cluster';
|
|
11
12
|
const logger = new Logger('web-server');
|
|
12
13
|
|
|
13
14
|
export class WebServer {
|
|
@@ -47,7 +48,7 @@ export class WebServer {
|
|
|
47
48
|
httpServer.on('upgrade', this.handleUpgrade.bind(this));
|
|
48
49
|
|
|
49
50
|
httpServer.listen(httpPort, bindIp, () => {
|
|
50
|
-
logger.info(`Http Server is started: http://localhost:${httpPort}`);
|
|
51
|
+
logger.info(`Http Server ${cluster.worker ? cluster.worker.id : -1} is started: http://localhost:${httpPort}`);
|
|
51
52
|
});
|
|
52
53
|
httpServer.on('error', (error: any) => {
|
|
53
54
|
logger.error('Error occurred on http server', error);
|
|
@@ -88,11 +89,12 @@ export class WebServer {
|
|
|
88
89
|
httpsServer.setTimeout(timeout);
|
|
89
90
|
}
|
|
90
91
|
httpsServer.listen(httpsPort, bindIp, () => {
|
|
91
|
-
logger.info(`Https Server is started: https://localhost:${httpsPort}`);
|
|
92
|
+
logger.info(`Https Server ${cluster.worker ? cluster.worker.id : -1} is started: https://localhost:${httpsPort}`);
|
|
92
93
|
});
|
|
93
94
|
httpsServer.on('error', (error: any) => {
|
|
94
95
|
logger.error('Error occurred on https server', error);
|
|
95
96
|
});
|
|
97
|
+
|
|
96
98
|
return httpsServer;
|
|
97
99
|
}
|
|
98
100
|
}
|