stoppable.js 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. exports.Stopper = void 0;
  7. const https_1 = __importDefault(require("https"));
  8. class Stopper {
  9. constructor(server) {
  10. this.server = server;
  11. this.requestCountPerSocket = new Map();
  12. this.stopped = false;
  13. server.on(server instanceof https_1.default.Server ? 'secureConnection' : 'connection', (socket) => {
  14. this.requestCountPerSocket.set(socket, 0);
  15. socket.once('close', () => this.requestCountPerSocket.delete(socket));
  16. });
  17. server.on('request', (req, res) => {
  18. this.requestCountPerSocket.set(req.socket, (this.requestCountPerSocket.get(req.socket) ?? 0) + 1);
  19. res.once('finish', () => {
  20. const pending = (this.requestCountPerSocket.get(req.socket) ?? 0) - 1;
  21. this.requestCountPerSocket.set(req.socket, pending);
  22. if (this.stopped && pending === 0) {
  23. req.socket.end();
  24. }
  25. });
  26. });
  27. }
  28. async stop(hardDestroyAbortSignal) {
  29. let gracefully = true;
  30. await new Promise((resolve) => setImmediate(resolve));
  31. this.stopped = true;
  32. const onAbort = () => {
  33. gracefully = false;
  34. this.requestCountPerSocket.forEach((_, socket) => socket.end());
  35. setImmediate(() => {
  36. this.requestCountPerSocket.forEach((_, socket) => socket.destroy());
  37. });
  38. };
  39. hardDestroyAbortSignal?.addEventListener('abort', onAbort);
  40. const closePromise = new Promise((resolve) => this.server.close(() => {
  41. hardDestroyAbortSignal?.removeEventListener('abort', onAbort);
  42. resolve();
  43. }));
  44. this.requestCountPerSocket.forEach((requests, socket) => {
  45. if (requests === 0)
  46. socket.end();
  47. });
  48. await closePromise;
  49. return gracefully;
  50. }
  51. }
  52. exports.Stopper = Stopper;
  53. //# sourceMappingURL=stoppable.js.map