Files
awesome-copilot/eng/utils/graceful-shutdown.mjs
Ashley Childress 1322aa2dde feat(eng): add contributor reporting and management scripts
- Add eng/README.md documenting maintainer utilities
- Add eng/contributor-report.mjs for generating contributor reports
- Add eng/add-missing-contributors.mjs for automating contributor additions
- Add eng/utils/graceful-shutdown.mjs for script lifecycle management
- Update eng/update-readme.mjs with minor fixes
- Update package.json with new contributor scripts

Generated-by: GitHub Copilot <copilot@github.com>
Signed-off-by: Ashley Childress <6563688+anchildress1@users.noreply.github.com>
2025-12-19 20:43:27 -05:00

61 lines
2.1 KiB
JavaScript

/**
* Lightweight graceful shutdown helper for one-off scripts.
*
* Call setupGracefulShutdown('script-name') early in your script to attach
* signal and exception handlers that exit the process cleanly.
*
* @param {string} name - Human readable name for log messages
* @param {{exitCode?:number}} [opts]
* @returns {() => void} teardown function to remove handlers (useful in tests)
*/
export const setupGracefulShutdown = (name, { exitCode = 1 } = {}) => {
let _shuttingDown = false;
const cleanup = (signal) => {
if (_shuttingDown) return;
_shuttingDown = true;
console.log(`\n🛑 ${name}: received ${signal}, shutting down gracefully...`);
// Best-effort cleanup: keep this short and synchronous
try {
// Place for lightweight cleanup tasks if needed in future
} catch (e) {
console.error(`${name}: error during shutdown cleanup:`, e);
}
// Exit with a non-zero code to indicate abnormal termination
try {
process.exit(exitCode);
} catch (e) {
// process.exit may not be desirable in some test harnesses; swallow errors
console.warn(`${name}: process.exit failed:`, e?.message);
}
};
const onSigInt = () => cleanup('SIGINT');
const onSigTerm = () => cleanup('SIGTERM');
const onSigHup = () => cleanup('SIGHUP');
const onUncaught = (err) => {
console.error(`${name}: Uncaught exception:`, err);
cleanup('uncaughtException');
};
const onUnhandledRejection = (reason) => {
console.error(`${name}: Unhandled promise rejection:`, reason);
cleanup('unhandledRejection');
};
process.on('SIGINT', onSigInt);
process.on('SIGTERM', onSigTerm);
process.on('SIGHUP', onSigHup);
process.on('uncaughtException', onUncaught);
process.on('unhandledRejection', onUnhandledRejection);
// Return a teardown function useful for tests or if a caller wants to remove handlers
return () => {
process.removeListener('SIGINT', onSigInt);
process.removeListener('SIGTERM', onSigTerm);
process.removeListener('SIGHUP', onSigHup);
process.removeListener('uncaughtException', onUncaught);
process.removeListener('unhandledRejection', onUnhandledRejection);
};
};