-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
94 lines (80 loc) · 3.5 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// don't let idle HTTP Keep-Alive connections prevent server.close()
// <https://github.com/nodejs/node-v0.x-archive/issues/9066>:
"use strict";
module.exports = function getGracefulClose(server) {
var isServerListening = false, sockets = new Map(), ids = [];
server.on("listening", () => {
isServerListening = true; // Node 5+: remove, can use "server.listening"
});
server.on("connection", (socket) => {
ids.push(socket);
console.log(`socket#${ids.indexOf(socket)} opened`);
sockets.set(socket, false);
socket.on("close", () => {
console.log(`socket#${ids.indexOf(socket)} closed`);
sockets.delete(socket);
});
});
server.on("request", (req, res) => {
var socket = req.connection;
console.log(`socket#${ids.indexOf(socket)}: request started`);
sockets.set(socket, true);
res.on("finish", () => {
console.log(`socket#${ids.indexOf(socket)}: request finished`);
sockets.set(socket, false);
if (!isServerListening) { // Node 5+: use "server.listening"
console.log(`socket#${ids.indexOf(socket)}: ...destroying because server is closing`);
socket.end();
socket.destroy(); // helps Varnish: http://bit.ly/1TQxTRQ
// let socket "close" event handler remove it from sockets
}
});
});
return function gracefulClose(options, cb) {
var failsafeClose, didForceClose = false;
console.log(`gracefulClose: gracefulClose() invoked`);
// normalize arguments:
if (arguments.length === 1 && typeof arguments[0] === "function") {
options = void 0;
cb = arguments[0];
}
if (typeof options === "number") {
options = { timeout: options };
} else if (!options) {
options = {};
}
if (options.timeout == null) {
options.timeout = 5000;
}
cb = cb || () => {};
// close server to new connections:
server.close(() => {
console.log(`gracefulClose: server.close() callback, all cleaned up! (didForceClose=${didForceClose})`);
clearTimeout(failsafeClose);
cb(didForceClose);
});
isServerListening = false; // Node 5+: remove, can use "server.listening"
// close idle connections:
sockets.forEach((isActive, socket) => {
if (!isActive) {
console.log(`gracefulClose: destroying idle socket#${ids.indexOf(socket)}`);
socket.end();
socket.destroy(); // helps Varnish: http://bit.ly/1TQxTRQ
// let socket "close" event handler remove it from sockets
}
});
// exit in 5 seconds in case server.close never returns:
failsafeClose = setTimeout(() => {
console.log(`gracefulClose: connections still open after timeout, destroying active sockets`)
didForceClose = true;
sockets.forEach((isActive, socket) => {
console.log(`gracefulClose: destroying active (isActive=${isActive}) socket#${ids.indexOf(socket)}`);
// should only be active sockets at this point
socket.end();
socket.destroy(); // helps Varnish: http://bit.ly/1TQxTRQ
// let socket "close" event handler remove it from sockets
});
// let server.close callback call cb()
}, options.timeout);
};
};