Przeglądaj źródła

feat(core): 实现优雅停机以正确释放资源

添加 SIGTERM/SIGINT 处理,确保调度器、服务器及数据库连接在退出前被正确关闭。
yangkaixiang 6 dni temu
rodzic
commit
8c08b0c519
3 zmienionych plików z 44 dodań i 3 usunięć
  1. 30 2
      src/index.js
  2. 13 0
      src/mqttService.js
  3. 1 1
      src/scheduler.js

+ 30 - 2
src/index.js

@@ -218,10 +218,38 @@ app.post('/settings', (req, res) => {
 
 cleanupLogs();
 mqttService.connect();
-startScheduler(mqttService);
+const schedulerTask = startScheduler(mqttService);
 
 const config = getConfig();
 const port = Number(process.env.PORT || config.server_port || 3000);
-app.listen(port, () => {
+const server = app.listen(port, () => {
   console.log(`Office Light running at http://localhost:${port}`);
 });
+
+let shuttingDown = false;
+
+async function shutdown(signal) {
+  if (shuttingDown) return;
+  shuttingDown = true;
+  console.log(`Received ${signal}, shutting down...`);
+
+  schedulerTask.stop();
+
+  await new Promise((resolve) => {
+    server.close(resolve);
+  });
+
+  await mqttService.close();
+  db.close();
+  process.exit(0);
+}
+
+process.on('SIGTERM', () => shutdown('SIGTERM').catch((error) => {
+  console.error('Shutdown failed:', error);
+  process.exit(1);
+}));
+
+process.on('SIGINT', () => shutdown('SIGINT').catch((error) => {
+  console.error('Shutdown failed:', error);
+  process.exit(1);
+}));

+ 13 - 0
src/mqttService.js

@@ -85,6 +85,19 @@ class MqttService {
     return this.status;
   }
 
+  close() {
+    if (!this.client) return Promise.resolve();
+
+    const client = this.client;
+    this.client = null;
+    this.pending.clear();
+    this.status = { connected: false, message: '连接已关闭', lastError: null, connectedAt: null };
+
+    return new Promise((resolve) => {
+      client.end(false, {}, resolve);
+    });
+  }
+
   commandTopic(channel) {
     const topicConfig = getTopicConfig();
     return `${topicConfig.commandPrefix}/Power${channel}`;

+ 1 - 1
src/scheduler.js

@@ -4,7 +4,7 @@ const { db, getConfig } = require('./db');
 const { getDueSchedules } = require('./scheduleService');
 
 function startScheduler(mqttService) {
-  cron.schedule('* * * * *', async () => {
+  return cron.schedule('* * * * *', async () => {
     await runDueSchedules(mqttService);
     cleanupLogs();
   });