const db = require('../dbProxy'); /** * 统一错误处理模块 * 负责错误分类、记录、恢复决策 */ class ErrorHandler { /** * 可重试的错误类型 */ static RETRYABLE_ERRORS = [ 'ETIMEDOUT', 'ECONNRESET', 'ENOTFOUND', 'NetworkError', 'MQTT客户端未初始化', '设备离线', '超时' ]; /** * 处理错误 * @param {Error} error - 错误对象 * @param {Object} context - 上下文信息 * @returns {Object} 错误处理结果 */ static async handleError(error, context = {}) { const errorInfo = { message: error.message || '未知错误', stack: error.stack || '', code: error.code || '', context: { task_id: context.task_id, sn_code: context.sn_code, taskType: context.taskType, ...context }, timestamp: new Date().toISOString(), isRetryable: this.isRetryableError(error) }; // 记录到日志 console.error(`[错误处理] ${errorInfo.message}`, { context: errorInfo.context, isRetryable: errorInfo.isRetryable, stack: errorInfo.stack }); // 错误信息已通过 console.error 记录到控制台日志 return errorInfo; } /** * 判断错误是否可重试 * @param {Error} error - 错误对象 * @returns {boolean} */ static isRetryableError(error) { if (!error) return false; const errorMessage = (error.message || '').toLowerCase(); const errorCode = error.code || ''; // 检查错误代码 if (this.RETRYABLE_ERRORS.some(code => errorCode === code)) { return true; } // 检查错误消息 return this.RETRYABLE_ERRORS.some(code => errorMessage.includes(code.toLowerCase()) ); } /** * 计算重试延迟(指数退避) * @param {number} retryCount - 当前重试次数 * @param {number} baseDelay - 基础延迟(毫秒) * @param {number} maxDelay - 最大延迟(毫秒) * @returns {number} 延迟时间(毫秒) */ static calculateRetryDelay(retryCount, baseDelay = 1000, maxDelay = 30000) { const delay = Math.min(baseDelay * Math.pow(2, retryCount - 1), maxDelay); return delay; } /** * 创建可重试错误 * @param {string} message - 错误消息 * @param {Object} context - 上下文 * @returns {Error} */ static createRetryableError(message, context = {}) { const error = new Error(message); error.code = 'RETRYABLE'; error.context = context; error.isRetryable = true; return error; } /** * 创建致命错误 * @param {string} message - 错误消息 * @param {Object} context - 上下文 * @returns {Error} */ static createFatalError(message, context = {}) { const error = new Error(message); error.code = 'FATAL'; error.context = context; error.isRetryable = false; return error; } } module.exports = ErrorHandler;