feat: 修复stopRoutine重复执行,并添加模板文件

This commit is contained in:
QCQCQC@Debian 2025-12-10 10:55:41 +08:00
parent 3781ed4629
commit 3e0dba7172
3 changed files with 124 additions and 35 deletions

View File

@ -402,33 +402,64 @@ async function startup(path, connector, omitWatchers, omitTimers, routine) {
if (!omitTimers) { if (!omitTimers) {
appLoader.startTimers(); appLoader.startTimers();
} }
let isShutingdown = false;
const shutdown = async () => { const shutdown = async () => {
await httpServer.close(); if (isShutingdown) {
await koa.removeAllListeners(); return;
await appLoader.execStopRoutines(); }
await appLoader.unmount(); isShutingdown = true;
(0, polyfill_1.removePolyfill)("startup"); console.log('服务器正在关闭中...');
try {
await httpServer.close();
await koa.removeAllListeners();
await appLoader.execStopRoutines();
await appLoader.unmount();
(0, polyfill_1.removePolyfill)("startup");
}
catch (err) {
console.error('关闭服务器时出错:', err);
}
};
// 处理优雅关闭的统一入口
let shutdownStarted = false;
const handleShutdown = async (signal) => {
// 防止重复处理
if (shutdownStarted) {
console.warn('关闭流程已启动,忽略此信号');
return;
}
shutdownStarted = true;
console.log(`\n收到 ${signal} 信号,准备关闭服务器...`);
// 移除所有信号处理器,防止重复触发
process.removeAllListeners('SIGINT');
process.removeAllListeners('SIGTERM');
process.removeAllListeners('SIGQUIT');
process.removeAllListeners('SIGHUP');
try {
await shutdown();
process.exit(0);
}
catch (err) {
console.error('关闭过程出错:', err);
process.exit(1);
}
}; };
// 监听终止信号进行优雅关闭 // 监听终止信号进行优雅关闭
// SIGINT - Ctrl+C 发送的中断信号 // SIGINT - Ctrl+C 发送的中断信号
process.on('SIGINT', async () => { process.on('SIGINT', () => {
await shutdown(); handleShutdown('SIGINT');
process.exit(0);
}); });
// SIGTERM - 系统/容器管理器发送的终止信号Docker、K8s、PM2等 // SIGTERM - 系统/容器管理器发送的终止信号Docker、K8s、PM2等
process.on('SIGTERM', async () => { process.on('SIGTERM', () => {
await shutdown(); handleShutdown('SIGTERM');
process.exit(0);
}); });
// SIGQUIT - Ctrl+\ 发送的退出信号 // SIGQUIT - Ctrl+\ 发送的退出信号
process.on('SIGQUIT', async () => { process.on('SIGQUIT', () => {
await shutdown(); handleShutdown('SIGQUIT');
process.exit(0);
}); });
// SIGHUP - 终端关闭时发送(可选) // SIGHUP - 终端关闭时发送(可选)
process.on('SIGHUP', async () => { process.on('SIGHUP', () => {
await shutdown(); handleShutdown('SIGHUP');
process.exit(0);
}); });
return shutdown; return shutdown;
} }

View File

@ -492,38 +492,70 @@ export async function startup<ED extends EntityDict & BaseEntityDict, FrontCxt e
appLoader.startTimers(); appLoader.startTimers();
} }
let isShutingdown = false;
const shutdown = async () => { const shutdown = async () => {
await httpServer.close(); if (isShutingdown) {
await koa.removeAllListeners(); return;
await appLoader.execStopRoutines(); }
await appLoader.unmount(); isShutingdown = true;
console.log('服务器正在关闭中...');
removePolyfill("startup"); try {
await httpServer.close();
await koa.removeAllListeners();
await appLoader.execStopRoutines();
await appLoader.unmount();
removePolyfill("startup");
} catch (err) {
console.error('关闭服务器时出错:', err);
}
} }
// 处理优雅关闭的统一入口
let shutdownStarted = false;
const handleShutdown = async (signal: string) => {
// 防止重复处理
if (shutdownStarted) {
console.warn('关闭流程已启动,忽略此信号');
return;
}
shutdownStarted = true;
console.log(`\n收到 ${signal} 信号,准备关闭服务器...`);
// 移除所有信号处理器,防止重复触发
process.removeAllListeners('SIGINT');
process.removeAllListeners('SIGTERM');
process.removeAllListeners('SIGQUIT');
process.removeAllListeners('SIGHUP');
try {
await shutdown();
process.exit(0);
} catch (err) {
console.error('关闭过程出错:', err);
process.exit(1);
}
};
// 监听终止信号进行优雅关闭 // 监听终止信号进行优雅关闭
// SIGINT - Ctrl+C 发送的中断信号 // SIGINT - Ctrl+C 发送的中断信号
process.on('SIGINT', async () => { process.on('SIGINT', () => {
await shutdown(); handleShutdown('SIGINT');
process.exit(0);
}); });
// SIGTERM - 系统/容器管理器发送的终止信号Docker、K8s、PM2等 // SIGTERM - 系统/容器管理器发送的终止信号Docker、K8s、PM2等
process.on('SIGTERM', async () => { process.on('SIGTERM', () => {
await shutdown(); handleShutdown('SIGTERM');
process.exit(0);
}); });
// SIGQUIT - Ctrl+\ 发送的退出信号 // SIGQUIT - Ctrl+\ 发送的退出信号
process.on('SIGQUIT', async () => { process.on('SIGQUIT', () => {
await shutdown(); handleShutdown('SIGQUIT');
process.exit(0);
}); });
// SIGHUP - 终端关闭时发送(可选) // SIGHUP - 终端关闭时发送(可选)
process.on('SIGHUP', async () => { process.on('SIGHUP', () => {
await shutdown(); handleShutdown('SIGHUP');
process.exit(0);
}); });
return shutdown return shutdown

View File

@ -0,0 +1,26 @@
import { Routine } from 'oak-domain/lib/types/Timer';
import { EntityDict } from '@oak-app-domain';
import { BackendRuntimeContext } from '../context/BackendRuntimeContext';
// process.on('uncaughtException', (err) => {
// console.error(`Caught exception: ${err}`);
// // Optionally, you can exit the process or perform cleanup
// });
// process.on('unhandledRejection', (err) => {
// console.error(`Caught rejection: ${err}`);
// // Optionally, you can exit the process or perform cleanup
// });
const stopRoutines: Array<Routine<EntityDict, keyof EntityDict, BackendRuntimeContext>> = [
{
name: '示例性routine_stop',
routine: async (context, env) => {
console.log('示例性routine执行请在src/routine/stop.ts中关闭');
return context.opResult;
},
},
];
export default stopRoutines;