@jsenv/server 15.1.8 → 15.2.1
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 +6 -6
- package/src/start_server.js +20 -19
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/server",
|
|
3
|
-
"version": "15.1
|
|
3
|
+
"version": "15.2.1",
|
|
4
4
|
"description": "Write your Node.js server using pure functions",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -34,11 +34,11 @@
|
|
|
34
34
|
"test": "node --conditions=development ./scripts/test.mjs"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@jsenv/abort": "4.
|
|
38
|
-
"@jsenv/log": "3.
|
|
39
|
-
"@jsenv/url-meta": "8.
|
|
40
|
-
"@jsenv/utils": "2.1.
|
|
41
|
-
"ws": "8.
|
|
37
|
+
"@jsenv/abort": "4.3.0",
|
|
38
|
+
"@jsenv/log": "3.5.2",
|
|
39
|
+
"@jsenv/url-meta": "8.4.0",
|
|
40
|
+
"@jsenv/utils": "2.1.1",
|
|
41
|
+
"ws": "8.16.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@jsenv/fetch": "../fetch/",
|
package/src/start_server.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { isIP } from "node:net";
|
|
2
2
|
import cluster from "node:cluster";
|
|
3
3
|
import { createDetailedMessage, createLogger } from "@jsenv/log";
|
|
4
|
-
import {
|
|
5
|
-
Abort,
|
|
6
|
-
raceProcessTeardownEvents,
|
|
7
|
-
createCallbackListNotifiedOnce,
|
|
8
|
-
} from "@jsenv/abort";
|
|
4
|
+
import { Abort, raceProcessTeardownEvents } from "@jsenv/abort";
|
|
9
5
|
import { memoize } from "@jsenv/utils/src/memoize/memoize.js";
|
|
10
6
|
|
|
11
7
|
import { createServiceController } from "./service_controller.js";
|
|
@@ -156,7 +152,7 @@ export const startServer = async ({
|
|
|
156
152
|
let status = "starting";
|
|
157
153
|
let nodeServer;
|
|
158
154
|
const startServerOperation = Abort.startOperation();
|
|
159
|
-
const
|
|
155
|
+
const stopCallbackSet = new Set();
|
|
160
156
|
const serverOrigins = {
|
|
161
157
|
local: "", // favors hostname when possible
|
|
162
158
|
};
|
|
@@ -280,10 +276,10 @@ export const startServer = async ({
|
|
|
280
276
|
// (otherwise an AbortError is thrown to the code calling "startServer")
|
|
281
277
|
// we can proceed to create a stop function to stop it gacefully
|
|
282
278
|
// and add a request handler
|
|
283
|
-
|
|
279
|
+
stopCallbackSet.add(({ reason }) => {
|
|
284
280
|
logger.info(`${serverName} stopping server (reason: ${reason})`);
|
|
285
281
|
});
|
|
286
|
-
|
|
282
|
+
stopCallbackSet.add(async () => {
|
|
287
283
|
await stopListening(nodeServer);
|
|
288
284
|
});
|
|
289
285
|
let stoppedResolve;
|
|
@@ -292,7 +288,12 @@ export const startServer = async ({
|
|
|
292
288
|
});
|
|
293
289
|
const stop = memoize(async (reason = STOP_REASON_NOT_SPECIFIED) => {
|
|
294
290
|
status = "stopping";
|
|
295
|
-
|
|
291
|
+
const promises = [];
|
|
292
|
+
for (const stopCallback of stopCallbackSet) {
|
|
293
|
+
promises.push(stopCallback({ reason }));
|
|
294
|
+
}
|
|
295
|
+
stopCallbackSet.clear();
|
|
296
|
+
await Promise.all(promises);
|
|
296
297
|
serviceController.callHooks("serverStopped", { reason });
|
|
297
298
|
status = "stopped";
|
|
298
299
|
stoppedResolve(reason);
|
|
@@ -304,7 +305,7 @@ export const startServer = async ({
|
|
|
304
305
|
stop(PROCESS_TEARDOWN_EVENTS_MAP[winner.name]);
|
|
305
306
|
},
|
|
306
307
|
);
|
|
307
|
-
|
|
308
|
+
stopCallbackSet.add(cancelProcessTeardownRace);
|
|
308
309
|
|
|
309
310
|
const onError = (error) => {
|
|
310
311
|
if (status === "stopping" && error.code === "ECONNRESET") {
|
|
@@ -319,19 +320,19 @@ export const startServer = async ({
|
|
|
319
320
|
nodeServer,
|
|
320
321
|
onError,
|
|
321
322
|
);
|
|
322
|
-
|
|
323
|
+
stopCallbackSet.add(removeConnectionErrorListener);
|
|
323
324
|
|
|
324
325
|
const connectionsTracker = trackServerPendingConnections(nodeServer, {
|
|
325
326
|
http2,
|
|
326
327
|
});
|
|
327
328
|
// opened connection must be shutdown before the close event is emitted
|
|
328
|
-
|
|
329
|
+
stopCallbackSet.add(connectionsTracker.stop);
|
|
329
330
|
|
|
330
331
|
const pendingRequestsTracker = trackServerPendingRequests(nodeServer, {
|
|
331
332
|
http2,
|
|
332
333
|
});
|
|
333
334
|
// ensure pending requests got a response from the server
|
|
334
|
-
|
|
335
|
+
stopCallbackSet.add((reason) => {
|
|
335
336
|
pendingRequestsTracker.stop({
|
|
336
337
|
status: reason === STOP_REASON_INTERNAL_ERROR ? 500 : 503,
|
|
337
338
|
reason,
|
|
@@ -371,13 +372,13 @@ export const startServer = async ({
|
|
|
371
372
|
};
|
|
372
373
|
});
|
|
373
374
|
receiveRequestOperation.addAbortSource((abort) => {
|
|
374
|
-
return
|
|
375
|
+
return stopCallbackSet.add(abort);
|
|
375
376
|
});
|
|
376
377
|
|
|
377
378
|
const sendResponseOperation = Abort.startOperation();
|
|
378
379
|
sendResponseOperation.addAbortSignal(receiveRequestOperation.signal);
|
|
379
380
|
sendResponseOperation.addAbortSource((abort) => {
|
|
380
|
-
return
|
|
381
|
+
return stopCallbackSet.add(abort);
|
|
381
382
|
});
|
|
382
383
|
|
|
383
384
|
const request = fromNodeRequest(nodeRequest, {
|
|
@@ -930,7 +931,7 @@ export const startServer = async ({
|
|
|
930
931
|
};
|
|
931
932
|
const removeRequestListener = listenRequest(nodeServer, requestCallback);
|
|
932
933
|
// ensure we don't try to handle new requests while server is stopping
|
|
933
|
-
|
|
934
|
+
stopCallbackSet.add(removeRequestListener);
|
|
934
935
|
}
|
|
935
936
|
|
|
936
937
|
websocket: {
|
|
@@ -983,8 +984,8 @@ export const startServer = async ({
|
|
|
983
984
|
"upgrade",
|
|
984
985
|
upgradeCallback,
|
|
985
986
|
);
|
|
986
|
-
|
|
987
|
-
|
|
987
|
+
stopCallbackSet.add(removeUpgradeCallback);
|
|
988
|
+
stopCallbackSet.add(() => {
|
|
988
989
|
websocketClients.forEach((websocketClient) => {
|
|
989
990
|
websocketClient.close();
|
|
990
991
|
});
|
|
@@ -1017,7 +1018,7 @@ export const startServer = async ({
|
|
|
1017
1018
|
addEffect: (callback) => {
|
|
1018
1019
|
const cleanup = callback();
|
|
1019
1020
|
if (typeof cleanup === "function") {
|
|
1020
|
-
|
|
1021
|
+
stopCallbackSet.add(cleanup);
|
|
1021
1022
|
}
|
|
1022
1023
|
},
|
|
1023
1024
|
});
|