guanghulab/backend/api-server/services/execution-watchdog.js
Guanghu Domestic Migration d1e47f4565
Some checks are pending
自动更新代码和重启 / update-and-restart (push) Waiting to run
CI检查 + 自动部署 / check (push) Waiting to run
CI检查 + 自动部署 / deploy (push) Blocked by required conditions
重启聊天服务 / restart (push) Waiting to run
chore: import sanitized domestic snapshot for REPO-002
Source snapshot: ca48d3ddf926d79aa138306164169baf764bb829
2026-07-17 15:54:41 +08:00

101 lines
2.5 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 执行看门狗 · 超时保护 + 死锁防护
*
* 定期检查执行锁是否超时。
* 如果一个操作执行超过 MAX_EXECUTION_TIME标记为超时并释放锁。
* 这是防止死锁的兜底机制。
*
* 版权:国作登字-2026-A-00037559
*/
'use strict';
var executionLock = require('../middleware/execution-lock');
// 最大执行时间15 分钟
var MAX_EXECUTION_TIME = 15 * 60 * 1000;
// 警告时间10 分钟
var WARN_TIME = 10 * 60 * 1000;
// 检查间隔30 秒
var CHECK_INTERVAL = 30 * 1000;
var watchdogTimer = null;
/**
* 启动看门狗
* 定期扫描活跃锁表,检测超时操作
*/
function startWatchdog() {
if (watchdogTimer) return;
watchdogTimer = setInterval(function() {
var activeLocks = executionLock.getActiveLocks();
var now = Date.now();
for (var entry of activeLocks) {
var devId = entry[0];
var lock = entry[1];
if (lock.state !== 'running') continue;
var elapsed = now - lock.startTime;
// 超时:强制释放
if (elapsed > MAX_EXECUTION_TIME) {
console.error(
'[WATCHDOG] 执行超时: ' + lock.executionId +
' (' + lock.operation + ') - ' + Math.round(elapsed / 1000) + 's'
);
lock.state = 'timeout';
lock.error = {
message: '执行超时(超过 ' + Math.round(MAX_EXECUTION_TIME / 60000) + ' 分钟)'
};
executionLock.logStep(devId, {
message: '⏰ 执行超时,看门狗已强制释放锁',
success: false
});
// 延迟释放(给前端时间获取超时状态)
(function(id) {
setTimeout(function() { executionLock.releaseLock(id); }, 30000);
})(devId);
}
// 警告
else if (elapsed > WARN_TIME && !lock.warned) {
console.warn(
'[WATCHDOG] 执行时间较长: ' + lock.executionId +
' (' + lock.operation + ') - ' + Math.round(elapsed / 1000) + 's'
);
lock.warned = true;
}
}
}, CHECK_INTERVAL);
// 不阻止 Node.js 进程退出
if (watchdogTimer.unref) {
watchdogTimer.unref();
}
console.log('[WATCHDOG] 执行看门狗已启动 · 检查间隔 ' + (CHECK_INTERVAL / 1000) + 's · 超时阈值 ' + (MAX_EXECUTION_TIME / 60000) + 'min');
}
/**
* 停止看门狗
*/
function stopWatchdog() {
if (watchdogTimer) {
clearInterval(watchdogTimer);
watchdogTimer = null;
}
}
module.exports = {
startWatchdog: startWatchdog,
stopWatchdog: stopWatchdog,
MAX_EXECUTION_TIME: MAX_EXECUTION_TIME
};