I want to ensure there is no brute (sub-)process termination and that any open requests are fulfilled when the Express server is closing.
import express, { Express, Request, Response } from 'express';
// Initialize the Express server application
var app = express();
var server = this.app.listen(process.env.PORT || 5000, () => { ... } );
// POST endpoint to process the shopping cart
app.post('/purchase', async (req, res) => {
// Get the items from the request body
try {
const { buyer, items } = req.body;
// Process the items (e.g., calculate total price, initiate payment, etc.)
const totalPrice = calculateTotalPrice(items);
// Charge the buyer for the purchase
const payment = chargeBuyerForPurchase(totalPrice);
// đĨˇ I don't want the server to close before it executes this line for every request
// Create shipping for the purchased items
const shipping = carrierAPI.createShipping(items, buyer.address);
res.status(200).json([totalPrice, payment, shipping]);
// đââī¸ This is now safe to close the server
} catch (error) {
next(error);
}
});
See documentation at this link
// ./src/app.ts
import process from 'node:process';
// Begin reading from stdin so the process does not exit.
process.stdin.resume();
process.on('SIGINT', () => {
console.log('Received SIGINT. Press Control-D to exit.');
});
// FYI docker "stop" <container>, a process manager, and most hosts will send SIGTERM signal when it is shutting down.
// server.close stops the server from accepting new connections and closes all connections connected to this server that are not sending a request or waiting for a response
function gracefulClose(signal) {
console.log(`Received ${signal}`);
server.close( () => { log('HTTP(S) server closed') } );
}
process.on('SIGINT', gracefulClose);
process.on('SIGTERM', gracefulClose);
Is it a feature to implement? Is this feature / code redundant?
When the SIGTERM
signal is emitted, the Node.JS server will be immediately closed. The Node.Js application / process will still be alive. Moreover, a response will not be sent to any client even if its connection was open before the SIGTERM
signal was received.
When the SIGINT
signal is emitted, the Node.JS (Express) server and application or process will be immediately closed.
When a custom signal is emitted, SIGUSR1
or SIGUSR2
, the Node.JS server will immediately close any open connections. The Node.Js application / process will still be alive. The Node.Js (Express) server will still be alive too and fulfill only new requests and responses.
PS: Signals are software interrupts sent to a program to indicate that an important event has occurred. Another common method for delivering signals is to use the kill
command, the syntax of which is as follows â
$ kill -signal <pid>
import express from 'express';
import SGS from 'super-graceful-shutdown';
const app = express();
const router = express.Router();
const express = require('express');
const SGS = require('super-graceful-shutdown');
const app = express();
const router = express.Router();
const port = 80; // Set your desired port number
// ...
router.get('/api', async function(req, res, next){
try {
// Fulfill this request in 3 seconds
setTimeout(() => { res.status(200).send(`<html> <body> <h1>${date()}</h1> </body> </html>`) }, 3000);
} catch (error) {
next(error);
}
});
const server = app.listen(port, () => console.log(`Example Express app listening on port ${port}!`) );
// âšī¸ Before you initialize other routes, you need to initialize super-graceful-shutdown
new SGS(app, server);
// đ¨âđģ Then, you can initialize other routes
app.use('/', router);
To super-gracefully-shutdown your Node.Js Express application, send the TCP shutdown
message on port 3000:
echo "shutdown" | nc localhost 3000