This commit is contained in:
张成
2025-11-26 15:00:14 +08:00
parent 7858459118
commit e27c0dc41a
9 changed files with 1046 additions and 358 deletions

View File

@@ -6,6 +6,8 @@ const command = require('./command');
const PriorityQueue = require('./PriorityQueue');
const ErrorHandler = require('./ErrorHandler');
const deviceManager = require('./deviceManager');
const ScheduleUtils = require('./utils');
const ScheduleConfig = require('./config');
/**
* 任务队列管理器(重构版)
@@ -548,7 +550,7 @@ class TaskQueue {
}
/**
* 执行任务(统一重试机制)
* 执行任务(统一重试机制 + 超时保护
* @param {object} task - 任务对象
*/
async executeTask(task) {
@@ -587,8 +589,16 @@ class TaskQueue {
throw new Error(`未找到任务类型 ${task.taskType} 的处理器,请先注册处理器`);
}
// 执行任务处理器
const result = await handler(task);
// 获取任务超时时间从配置中获取默认10分钟
const taskTimeout = ScheduleConfig.getTaskTimeout(task.taskType) || 10 * 60 * 1000;
// 使用超时机制包装任务执行,防止任务卡住
const taskPromise = handler(task);
const result = await ScheduleUtils.withTimeout(
taskPromise,
taskTimeout,
`任务执行超时: ${task.taskName} (任务类型: ${task.taskType}, 超时时间: ${taskTimeout / 1000}秒)`
);
// 任务成功
task.status = 'completed';
@@ -613,46 +623,64 @@ class TaskQueue {
} catch (error) {
// 使用统一错误处理
const errorInfo = await ErrorHandler.handleError(error, {
taskId: task.id,
task_id: task.id,
sn_code: task.sn_code,
taskType: task.taskType,
taskName: task.taskName
});
// 直接标记为失败(重试已禁用)
task.status = 'failed';
task.endTime = new Date();
task.duration = Date.now() - startTime;
task.errorMessage = errorInfo.message || error.message || '未知错误';
task.errorStack = errorInfo.stack || error.stack || '';
// 直接标记为失败(重试已禁用)
task.status = 'failed';
task.endTime = new Date();
task.duration = Date.now() - startTime;
task.errorMessage = errorInfo.message || error.message || '未知错误';
task.errorStack = errorInfo.stack || error.stack || '';
console.error(`[任务队列] 任务执行失败: ${task.taskName} (ID: ${task.id}), 错误: ${task.errorMessage}`, {
errorStack: task.errorStack,
taskId: task.id,
sn_code: task.sn_code,
taskType: task.taskType
});
// 更新数据库任务状态为失败
try {
await db.getModel('task_status').update(
{
status: 'failed',
endTime: task.endTime,
duration: task.duration,
result: JSON.stringify({
error: task.errorMessage,
stack: task.errorStack
}),
progress: 0
},
{ where: { id: task.id } }
);
} catch (dbError) {
console.error(`[任务队列] 更新任务失败状态到数据库失败:`, dbError);
}
console.error(`[任务队列] 任务执行失败: ${task.taskName} (ID: ${task.id}), 错误: ${task.errorMessage}`, {
errorStack: task.errorStack,
task_id: task.id,
sn_code: task.sn_code,
taskType: task.taskType,
duration: task.duration
});
}
}
/**
* 取消任务
* @param {string} taskId - 任务ID
* @param {string} task_id - 任务ID
* @returns {Promise<boolean>} 是否成功取消
*/
async cancelTask(taskId) {
async cancelTask(task_id) {
// 遍历所有设备队列查找任务
for (const [sn_code, queue] of this.deviceQueues.entries()) {
const removed = queue.remove(task => task.id === taskId);
const removed = queue.remove(task => task.id === task_id);
if (removed) {
// 检查是否正在执行
const status = this.deviceStatus.get(sn_code);
if (status && status.currentTask && status.currentTask.id === taskId) {
if (status && status.currentTask && status.currentTask.id === task_id) {
// 正在执行的任务无法取消,只能标记
console.warn(`[任务队列] 任务 ${taskId} 正在执行,无法取消`);
console.warn(`[任务队列] 任务 ${task_id} 正在执行,无法取消`);
return false;
}
@@ -662,10 +690,10 @@ class TaskQueue {
status: 'cancelled',
endTime: new Date()
},
{ where: { id: taskId } }
{ where: { id: task_id } }
);
console.log(`[任务队列] 任务已取消: ${taskId}`);
console.log(`[任务队列] 任务已取消: ${task_id}`);
return true;
}
}
@@ -766,13 +794,13 @@ class TaskQueue {
/**
* 获取任务状态
* @param {string} taskId - 任务ID
* @param {string} task_id - 任务ID
* @returns {Promise<object|null>} 任务对象
*/
async getTaskStatus(taskId) {
async getTaskStatus(task_id) {
// 先从内存中查找
for (const queue of this.deviceQueues.values()) {
const task = queue.find(t => t.id === taskId);
const task = queue.find(t => t.id === task_id);
if (task) {
return task;
}
@@ -780,7 +808,7 @@ class TaskQueue {
// 从正在执行的任务中查找
for (const status of this.deviceStatus.values()) {
if (status.currentTask && status.currentTask.id === taskId) {
if (status.currentTask && status.currentTask.id === task_id) {
return status.currentTask;
}
}
@@ -788,7 +816,7 @@ class TaskQueue {
// 从数据库中查找
try {
const taskRecord = await db.getModel('task_status').findOne({
where: { id: taskId }
where: { id: task_id }
});
if (taskRecord) {
@@ -796,7 +824,7 @@ class TaskQueue {
}
} catch (error) {
console.error(`[任务队列] 查询任务状态失败:`, error, {
taskId: taskId
task_id: task_id
});
}
@@ -858,24 +886,24 @@ class TaskQueue {
});
console.log(`[任务队列] 已删除任务指令记录: ${commandsDeleted}`);
// 删除聊天记录中关联的任务记录(删除所有有 taskId 且不为空的记录)
// 删除聊天记录中关联的任务记录(删除所有有 task_id 且不为空的记录)
const chatRecordsDeleted = await chatRecordsModel.destroy({
where: {
[Sequelize.Op.and]: [
{ taskId: { [Sequelize.Op.ne]: null } },
{ taskId: { [Sequelize.Op.ne]: '' } }
{ task_id: { [Sequelize.Op.ne]: null } },
{ task_id: { [Sequelize.Op.ne]: '' } }
]
},
truncate: false
});
console.log(`[任务队列] 已删除聊天记录: ${chatRecordsDeleted}`);
// 删除投递记录中关联的任务记录(删除所有有 taskId 且不为空的记录)
// 删除投递记录中关联的任务记录(删除所有有 task_id 且不为空的记录)
const applyRecordsDeleted = await applyRecordsModel.destroy({
where: {
[Sequelize.Op.and]: [
{ taskId: { [Sequelize.Op.ne]: null } },
{ taskId: { [Sequelize.Op.ne]: '' } }
{ task_id: { [Sequelize.Op.ne]: null } },
{ task_id: { [Sequelize.Op.ne]: '' } }
]
},
truncate: false