Skip to content

Commit

Permalink
Merge branch 'master' of github.com:gajus/http-terminator
Browse files Browse the repository at this point in the history
  • Loading branch information
gajus committed Sep 17, 2021
2 parents ba207b6 + 1f50850 commit ab4d305
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 8 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
},
"dependencies": {
"delay": "^5.0.0",
"p-wait-for": "^3.2.0",
"roarr": "^7.0.4",
"type-fest": "^2.3.3"
},
Expand Down
21 changes: 13 additions & 8 deletions src/factories/createInternalHttpTerminator.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable import/order */

import http from 'http';
import delay from 'delay';
import waitFor from 'p-wait-for';
import type {
Duplex,
} from 'node:stream';
Expand Down Expand Up @@ -130,16 +130,21 @@ export default (
destroySocket(socket);
}

if (sockets.size) {
await delay(configuration.gracefulTerminationTimeout);

// Wait for all in-flight connections to drain, forcefully terminating any
// open connections after the given timeout
try {
await waitFor(() => {
return sockets.size === 0 && secureSockets.size === 0;
}, {
interval: 10,
timeout: configuration.gracefulTerminationTimeout,
});
} catch {
// Ignore timeout errors
} finally {
for (const socket of sockets) {
destroySocket(socket);
}
}

if (secureSockets.size) {
await delay(configuration.gracefulTerminationTimeout);

for (const socket of secureSockets) {
destroySocket(socket);
Expand Down
34 changes: 34 additions & 0 deletions test/http-terminator/factories/createInternalHttpTerminator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,3 +241,37 @@ test('empties internal socket collection for https server', async (t) => {

await terminator.terminate();
});

test('closes immediately after in-flight connections are closed (#16)', async (t) => {
t.timeout(1_000);

const spy = sinon.spy((incomingMessage, outgoingMessage) => {
setTimeout(() => {
outgoingMessage.end('foo');
}, 100);
});

const httpServer = await createHttpServer(spy);

t.true(httpServer.server.listening);

const terminator = createInternalHttpTerminator({
gracefulTerminationTimeout: 500,
server: httpServer.server,
});

got(httpServer.url);

await delay(50);

t.is(await httpServer.getConnections(), 1);

terminator.terminate();

// Wait for outgoingMessage.end to be called, plus a few extra ms for the
// terminator to finish polling in-flight connections. (Do not, however, wait
// long enough to trigger graceful termination.)
await delay(75);

t.is(await httpServer.getConnections(), 0);
});

0 comments on commit ab4d305

Please sign in to comment.