@hirosystems/api-toolkit
Version:
API development toolkit
82 lines • 3.01 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.shutdown = shutdown;
exports.registerShutdownConfig = registerShutdownConfig;
const time_1 = require("../helpers/time");
const logger_1 = require("../logger");
const SHUTDOWN_SIGNALS = ['SIGINT', 'SIGTERM'];
const shutdownConfigs = [];
let isShuttingDown = false;
/**
* Start a graceful API shutdown.
*/
async function shutdown() {
if (isShuttingDown) {
return;
}
isShuttingDown = true;
const timeoutMs = parseInt(process.env['STACKS_SHUTDOWN_FORCE_KILL_TIMEOUT'] ?? '60') * 1000;
let errorEncountered = false;
for (const config of shutdownConfigs) {
try {
logger_1.logger.info(`Closing ${config.name}...`);
const gracefulShutdown = await (0, time_1.resolveOrTimeout)(Promise.resolve(config.handler()), timeoutMs, !config.forceKillable, () => logger_1.logger.error(`${config.name} is taking longer than expected to shutdown, possibly hanging indefinitely`));
if (!gracefulShutdown) {
if (config.forceKillable && config.forceKillHandler) {
await Promise.resolve(config.forceKillHandler());
}
logger_1.logger.error(`${config.name} was force killed after taking longer than ${timeoutMs}ms to shutdown`);
}
else {
logger_1.logger.info(`${config.name} closed`);
}
}
catch (error) {
errorEncountered = true;
logger_1.logger.error(error, `Error running ${config.name} shutdown handler`);
}
}
if (errorEncountered) {
process.exit(1);
}
else {
logger_1.logger.info('App shutdown successful.');
process.exit();
}
}
let shutdownSignalsRegistered = false;
function registerShutdownSignals() {
if (shutdownSignalsRegistered) {
return;
}
shutdownSignalsRegistered = true;
SHUTDOWN_SIGNALS.forEach(sig => {
process.once(sig, () => {
logger_1.logger.info(`Shutting down... received signal: ${sig}`);
void shutdown();
});
});
process.once('unhandledRejection', error => {
logger_1.logger.error(error, 'unhandledRejection');
logger_1.logger.error('Shutting down... received unhandledRejection.');
void shutdown();
});
process.once('uncaughtException', error => {
logger_1.logger.error(error, 'uncaughtException');
logger_1.logger.error('Shutting down... received uncaughtException.');
void shutdown();
});
process.once('beforeExit', () => {
logger_1.logger.error('Shutting down... received beforeExit.');
void shutdown();
});
}
/**
* Register shutdown handlers for different API components.
* @param configs - Array of shutdown configurations
*/
function registerShutdownConfig(...configs) {
registerShutdownSignals();
shutdownConfigs.push(...configs);
}
//# sourceMappingURL=index.js.map