maildev
Version:
SMTP Server and Web Interface for reading and testing emails during development
71 lines • 2.48 kB
JavaScript
/**
* MailDev Graceful Shutdown Handler
*
* Handles SIGTERM, SIGINT, and uncaught exceptions for clean server shutdown
*/
/**
* Setup graceful shutdown handlers
*
* Handles:
* - SIGTERM (e.g., from docker stop, process managers)
* - SIGINT (e.g., Ctrl+C)
* - Uncaught exceptions
* - Unhandled promise rejections
*/
export function setupShutdownHandlers(options) {
const { orchestrator, logger, timeout = 10000 } = options;
let shuttingDown = false;
const shutdown = async (signal) => {
if (shuttingDown) {
logger.debug('Already shutting down, please wait...');
return;
}
shuttingDown = true;
logger.info('');
logger.info(`Received ${signal}, shutting down gracefully...`);
// Set a timeout to force exit if graceful shutdown takes too long
const forceExitTimeout = setTimeout(() => {
logger.error('Graceful shutdown timed out, forcing exit');
process.exit(1);
}, timeout);
try {
await orchestrator.stop();
clearTimeout(forceExitTimeout);
logger.success('Shutdown complete');
process.exit(0);
}
catch (error) {
clearTimeout(forceExitTimeout);
const message = error instanceof Error ? error.message : String(error);
logger.error(`Error during shutdown: ${message}`);
process.exit(1);
}
};
// Handle termination signals
process.on('SIGTERM', () => shutdown('SIGTERM'));
process.on('SIGINT', () => shutdown('SIGINT'));
// Handle uncaught exceptions
process.on('uncaughtException', (error) => {
logger.error(`Uncaught exception: ${error.message}`);
if (error.stack) {
logger.debug(error.stack);
}
shutdown('uncaughtException');
});
// Handle unhandled promise rejections
process.on('unhandledRejection', (reason) => {
const message = reason instanceof Error ? reason.message : String(reason);
logger.error(`Unhandled rejection: ${message}`);
shutdown('unhandledRejection');
});
}
/**
* Remove all shutdown handlers (useful for testing)
*/
export function removeShutdownHandlers() {
process.removeAllListeners('SIGTERM');
process.removeAllListeners('SIGINT');
process.removeAllListeners('uncaughtException');
process.removeAllListeners('unhandledRejection');
}
//# sourceMappingURL=shutdown.js.map