UNPKG

omniwheel

Version:

Boilerplate reduction for backend and microservices. Scale your application easily in any direction.

43 lines (42 loc) 1.56 kB
import { constants } from 'node:os'; class Terminator { constructor() { this.exiting = false; this.callbacks = []; } async handleSignal(signal) { if (this.exiting) { return; } this.exiting = true; // Invoke in reverse order in case any callbacks registered later depend on things registered earlier for (let i = this.callbacks.length - 1; i >= 0; --i) { await this.callbacks[i](signal); } // POSIX process exit code is typically 128+signal, such as 143 for SIGTERM process.exit(128 + constants.signals[signal]); } registerCallback(callback) { this.callbacks.push(callback); } } const handler = new Terminator(); for (const signal of ['SIGTERM', 'SIGINT']) { process.once(signal, () => { void handler.handleSignal(signal); }); } /** * Register a callback for when termination of the process is requested via an external signal. When a signal is * received, all callbacks will be run serially in reverse order, and then the process will exit. * Explicit termination such as via process.exit() will not invoke any of the callbacks. * * The callback can be asynchronous, returning a Promise. Still it is required to limit the total amount of time spent * in termination callbacks, since the OS (or container orchestration) might forcefully kill the process a few seconds * after the signal. * * @param fn The callback to register. */ export function onTermination(fn) { handler.registerCallback(fn); }