/** * ═══════════════════════════════════════════════════════════ * 🔬 活模块: SY-TEST · 系统自检 * ═══════════════════════════════════════════════════════════ * * 编号: ZY-TASK-007 · S5 Agent系统级 * 签发: 铸渊 · ICE-GL-ZY001 * 版权: 国作登字-2026-A-00037559 * * v2.0: 从死模块升级为活模块 * - 继承 LivingModule 基类 * - 自诊断覆盖: DB/COS/brain_nodes/agent_configs 四项检查 * - 自愈: DB断连自动重试、COS超时告警 * - 学习: 记录每次检查结果的成功/失败模式 * * 每30分钟运行一次 · 检测全系统健康 */ 'use strict'; const LivingModule = require('./living-module'); const db = require('../mcp-server/db'); const cos = require('../mcp-server/cos'); class LivingSyTest extends LivingModule { constructor(options = {}) { super({ moduleId: 'ZY-MOD-SY-TEST', name: '系统自检活模块', moduleType: 'guard', owner: 'zhuyuan', db: options.db || db, config: { version: '2.0.0', description: '全系统健康检测·DB/COS/表/模块', heartbeatInterval: 60000 // 自检模块心跳1分钟 } }); } /** * 自定义诊断检查 — 系统全面自检 */ async _diagnoseChecks() { const issues = []; // 1. 数据库连接检查 try { const dbStatus = await db.checkConnection(); if (!dbStatus.connected) { issues.push({ code: 'DB_DISCONNECTED', severity: 'critical', message: `数据库连接失败: ${dbStatus.error || '未知原因'}`, suggestion: '检查 PostgreSQL 服务状态' }); } } catch (err) { issues.push({ code: 'DB_ERROR', severity: 'critical', message: `数据库检查异常: ${err.message}`, suggestion: '检查数据库配置和网络' }); } // 2. COS连通性检查 try { const cosStatus = await cos.checkConnection(); if (!cosStatus.connected) { issues.push({ code: 'COS_DISCONNECTED', severity: 'warning', message: `COS存储桶不可达: ${cosStatus.reason || '未知原因'}`, suggestion: '检查 COS 密钥和网络' }); } } catch (err) { issues.push({ code: 'COS_ERROR', severity: 'warning', message: `COS检查异常: ${err.message}`, suggestion: '检查 COS 配置' }); } // 3. brain_nodes表可用性 try { await db.query("SELECT COUNT(*) as cnt FROM brain_nodes WHERE status = 'active'"); } catch (err) { issues.push({ code: 'TABLE_BRAIN_NODES_FAIL', severity: 'warning', message: `brain_nodes表不可用: ${err.message}`, suggestion: '检查 Schema 是否已初始化' }); } // 4. agent_configs表可用性 try { await db.query("SELECT COUNT(*) as cnt FROM agent_configs WHERE enabled = true"); } catch (err) { issues.push({ code: 'TABLE_AGENT_CONFIGS_FAIL', severity: 'warning', message: `agent_configs表不可用: ${err.message}`, suggestion: '检查 Schema 是否已初始化' }); } // 5. living_modules表可用性(S5新增) try { await db.query("SELECT COUNT(*) as cnt FROM living_modules WHERE status = 'alive'"); } catch (err) { issues.push({ code: 'TABLE_LIVING_MODULES_FAIL', severity: 'info', message: `living_modules表不可用: ${err.message}`, suggestion: '执行 003-living-module-tables.sql' }); } return issues; } /** * 自愈动作 */ async _healAction(issue) { switch (issue.code) { case 'DB_DISCONNECTED': case 'DB_ERROR': // 尝试重连 try { await db.query('SELECT 1'); return { action: 'db_reconnect', success: true }; } catch (err) { return { action: 'db_reconnect', success: false, error: err.message }; } case 'COS_DISCONNECTED': case 'COS_ERROR': // COS问题只能上报,无法自愈 return { action: 'cos_alert_sent', success: true, details: { reported: true } }; default: return await super._healAction(issue); } } } /** * 兼容旧调度器的 run() 接口 * 调度引擎通过 run(config) 调用 */ async function run(config) { const checks = []; let allPassed = true; // 1. 数据库连接检查 try { const dbStatus = await db.checkConnection(); checks.push({ name: '数据库连接', status: dbStatus.connected ? 'pass' : 'fail', detail: dbStatus.connected ? dbStatus.version : dbStatus.error }); if (!dbStatus.connected) allPassed = false; } catch (err) { checks.push({ name: '数据库连接', status: 'fail', detail: err.message }); allPassed = false; } // 2. COS连通性检查 try { const cosStatus = await cos.checkConnection(); checks.push({ name: 'COS存储桶', status: cosStatus.connected ? 'pass' : 'fail', detail: cosStatus.connected ? 'hot桶可达' : cosStatus.reason }); if (!cosStatus.connected) allPassed = false; } catch (err) { checks.push({ name: 'COS存储桶', status: 'fail', detail: err.message }); allPassed = false; } // 3. brain_nodes表可用性 try { const result = await db.query("SELECT COUNT(*) as cnt FROM brain_nodes WHERE status = 'active'"); checks.push({ name: 'brain_nodes表', status: 'pass', detail: `${result.rows[0].cnt} 个活跃节点` }); } catch (err) { checks.push({ name: 'brain_nodes表', status: 'fail', detail: err.message }); allPassed = false; } // 4. agent_configs表可用性 try { const result = await db.query("SELECT COUNT(*) as cnt FROM agent_configs WHERE enabled = true"); checks.push({ name: 'agent_configs表', status: 'pass', detail: `${result.rows[0].cnt} 个启用的Agent` }); } catch (err) { checks.push({ name: 'agent_configs表', status: 'fail', detail: err.message }); allPassed = false; } // 5. living_modules表可用性(S5新增) try { const result = await db.query("SELECT COUNT(*) as cnt FROM living_modules WHERE status = 'alive'"); checks.push({ name: 'living_modules表', status: 'pass', detail: `${result.rows[0].cnt} 个活跃模块` }); } catch (err) { checks.push({ name: 'living_modules表', status: 'warn', detail: `未初始化: ${err.message}` }); // 不算严重失败·Schema可能还没部署 } // 学习:如果调度引擎注入了bus,通过HLDP上报结果 if (config && config.bus) { try { await config.bus.send('ZY-MOD-SY-TEST', 'ZY-MOD-SCHEDULER', 'event', { event: 'system_check_complete', allPassed, checkCount: checks.length, failCount: checks.filter(c => c.status === 'fail').length }); } catch (err) { // 非关键·忽略 } } return { message: allPassed ? '系统自检通过' : '系统自检发现异常', details: { all_passed: allPassed, checks, checked_at: new Date().toISOString() } }; } module.exports = { run, LivingSyTest };