@lynx-js/rspeedy
Version:
A webpack/rspack-based frontend toolchain for Lynx
113 lines (112 loc) • 5.37 kB
JavaScript
import node_process from "node:process";
export const __rspack_esm_id = "src_cli_exit_ts";
export const __rspack_esm_ids = [
"src_cli_exit_ts"
];
export const __webpack_modules__ = {
"./src/cli/exit.ts" (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
__webpack_require__.d(__webpack_exports__, {
exit: ()=>exit_exit
});
var core_ = __webpack_require__("@rsbuild/core");
const asyncCallbacks = new Set();
const callbacks = new Set();
let isCalled = false;
let isRegistered = false;
async function exit(shouldManuallyExit, isSynchronous, signal) {
if (isCalled) return;
isCalled = true;
if (asyncCallbacks.size > 0 && isSynchronous) console.error("SYNCHRONOUS TERMINATION NOTICE: When explicitly exiting the process via process.exit or via a parent process, asynchronous tasks in your exitHooks will not run. Either remove these tasks, use gracefulExit() instead of process.exit(), or ensure your parent process sends a SIGINT to the process running this code.");
const exitCode = 128 + signal;
const done = (force = false)=>{
if (true === force || true === shouldManuallyExit) node_process.exit(exitCode);
};
for (const callback of callbacks)callback(exitCode);
if (isSynchronous) return void done();
const promises = [];
let forceAfter = 0;
for (const [callback, wait] of asyncCallbacks){
forceAfter = Math.max(forceAfter, wait);
promises.push(Promise.resolve(callback(exitCode)));
}
const asyncTimer = setTimeout(()=>{
done(true);
}, forceAfter);
await Promise.all(promises);
clearTimeout(asyncTimer);
done();
}
function addHook(options) {
const { onExit, wait, isSynchronous } = options;
const asyncCallbackConfig = [
onExit,
wait
];
if (isSynchronous) callbacks.add(onExit);
else asyncCallbacks.add(asyncCallbackConfig);
if (!isRegistered) {
isRegistered = true;
node_process.once('beforeExit', exit.bind(void 0, true, false, -128));
node_process.once('SIGINT', exit.bind(void 0, true, false, 2));
node_process.once('SIGTERM', exit.bind(void 0, true, false, 15));
node_process.once('exit', exit.bind(void 0, false, true, 0));
node_process.on('message', (message)=>{
if ('shutdown' === message) exit(true, true, -128);
});
}
return ()=>{
if (isSynchronous) callbacks.delete(onExit);
else asyncCallbacks.delete(asyncCallbackConfig);
};
}
function asyncExitHook(onExit, options = {}) {
if ('function' != typeof onExit) throw new TypeError('onExit must be a function');
if (!('number' == typeof options.wait && options.wait > 0)) throw new TypeError('wait must be set to a positive numeric value');
return addHook({
onExit,
wait: options.wait,
isSynchronous: false
});
}
function gracefulExit(signal = 0) {
exit(true, false, -128 + signal);
}
var picocolors = __webpack_require__("../../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js");
var picocolors_default = /*#__PURE__*/ __webpack_require__.n(picocolors);
var debug = __webpack_require__("./src/debug.ts");
const start = Date.now();
const exitPromises = [];
const unsubscribe = asyncExitHook(exit_onExit, {
wait: 1000
});
process.on('unhandledRejection', async (reason)=>{
core_.logger.error('Unhandled Rejection with reason:', reason instanceof Error ? reason : new Error(JSON.stringify(reason)));
unsubscribe();
await exit_onExit(1);
process.exit(1);
});
let interrupted = false;
process.on('SIGINT', ()=>{
if (interrupted) {
core_.logger.info("Force exiting Rspeedy.");
return process.exit(130);
}
interrupted = true;
core_.logger.info(`Gracefully shutting down. Please wait... (Press ${picocolors_default().cyan('Ctrl+C')} again to force exit)`);
exit_exit(130);
});
let previousSignal = null;
const exit_exit = (signal = 0)=>{
if (null !== previousSignal) (0, debug.Yz)(`graceful exit called multiple times, current: ${signal}, previous: ${previousSignal}`);
previousSignal = signal;
(0, debug.Yz)(`graceful exit process with signal: ${signal}`);
gracefulExit(signal);
};
async function exit_onExit(signal) {
const duration = Date.now() - start;
(0, debug.Yz)(`exit hook fired with signal: ${signal}, duration: ${duration}`);
(0, debug.Yz)(`awaiting exit promises(length: ${exitPromises.length})...`);
await Promise.allSettled(exitPromises);
}
}
};