@radically-straightforward/node
TypeScript icon, indicating that this package has built-in type declarations

3.1.5 • Public • Published

Radically Straightforward · Node

🔨 Utilities for Node.js

Installation

$ npm install @radically-straightforward/node

Usage

import * as node from "@radically-straightforward/node";

Graceful Termination

Importing @radically-straightforward/node enables graceful termination, which gives your application the opportunity to clean up resources before exiting.

Graceful termination works by listening to the following signals:

  • SIGINT: Emitted by pressing ⌃C on the terminal.
  • SIGQUIT: Emitted by pressing ⌃\ on the terminal.
  • SIGBREAK: Emitted by pressing Ctrl+Break on the terminal on Windows.
  • SIGHUP: Emitted when the terminal is closed while the application is still running.
  • SIGTERM: Emitted by process managers that wish to terminate the application, for example, systemd, kill, and so forth.
  • SIGUSR2: Emitted by nodemon to indicate that the application should restart.

Note: Some signals, for example, SIGKILL, which may be sent by kill -9, cannot be handled and cause the process to terminate immediately without the opportunity to clean up resources.

When one of these signals is received, the process.once("gracefulTermination") event is emitted, and your application should handle it to close HTTP servers, clear timers, and so forth. The goal is to leave the Node.js event loop empty so that the process may terminate naturally.

Note: The "gracefulTermination" signal is emitted only once.

As one last step before termination, you may handle Node.js’s process.once("beforeExit") event, which is emitted after the Node.js event loop is empty, but before the application terminates. This is useful, for example, to close a database connection, to log that the application terminated gracefully, and so forth.

Note: You may wish to close a database connection on "beforeExit" instead of "gracefulTermination" because during "gracefulTermination" an HTTP server may still need the database connection while it’s responding to the last undergoing requests before closing.

Note: According to Node.js’s documentation you may use "beforeExit" to add more work to the event loop and prevent the process from terminating, but we advise against using it that way.

Note: Use the "beforeExit" event instead of the "exit" event for the following reasons:

  1. The "exit" event handler runs in a constrained environment that only allows for synchronous operations, but your cleanup may need to be asynchronous.
  2. The "exit" event is emitted even when the process is terminating in abnormal conditions, for example, because of an uncaught exception, and under these abnormal conditions graceful termination isn’t appropriate.

After the "gracefulTermination" event is emitted, if the application doesn’t terminate in 10 seconds, then it’s terminated forcefully with process.exit(1).

Example

import http from "node:http";
import "@radically-straightforward/node";

const server = http
  .createServer((request, response) => {
    response.end("gracefulTermination");
  })
  .listen(8000);
process.once("gracefulTermination", () => {
  // If you comment the line below the application remains running for 10 seconds and then it is forcefully terminated.
  server.close();
});

console.log("gracefulTermination: Press ⌃C to gracefully terminate...");
process.once("gracefulTermination", () => {
  console.log("gracefulTermination: Starting graceful termination...");
});
process.once("beforeExit", () => {
  console.log("gracefulTermination: Succeeded.");
});

backgroundJob()

export function backgroundJob(
  {
    onStop,
    ...utilitiesBackgroundJobOptions
  }: Parameters<typeof utilities.backgroundJob>[0],
  job: Parameters<typeof utilities.backgroundJob>[1],
): ReturnType<typeof utilities.backgroundJob>;

This is an extension of @radically-straightforward/utilities’s backgroundJob() which adds support for graceful termination.

Example

import timers from "node:timers/promises";
import * as node from "@radically-straightforward/node";

node.backgroundJob({ interval: 3 * 1000 }, async () => {
  console.log("backgroundJob(): Running background job...");
  await timers.setTimeout(3 * 1000);
  console.log("backgroundJob(): ...finished running background job.");
});

childProcessKeepAlive()

export function childProcessKeepAlive(
  newChildProcess: () =>
    | ReturnType<(typeof childProcess)["spawn"]>
    | Promise<ReturnType<(typeof childProcess)["spawn"]>>,
): void;

Keep a child process alive. If the child process crashes, respawn it. When the process gracefully terminates, gracefully terminate the child process as well.

Example

node.childProcessKeepAlive(() =>
  childProcess.spawn("node", ["--eval", `http.createServer().listen(18000)`], {
    stdio: "inherit",
  }),
);

exit()

export function exit(): void;

On Windows this is the same as process.exit(), but in other platforms that support signals this sends a SIGTERM to the process itself, which starts graceful termination.

Readme

Keywords

Package Sidebar

Install

npm i @radically-straightforward/node

Weekly Downloads

754

Version

3.1.5

License

MIT

Unpacked Size

27.5 kB

Total Files

14

Last publish

Collaborators

  • leafac