/** * Health Checker — 健康检查器 * * 对数据库连通性、磁盘空间、内存使用执行真实检查。 * * @see docs/生产级通用 AI Agent 智能体桌面应用:完整设计与构建指南.html — 第十一章 */ import { existsSync } from 'fs'; import { app } from 'electron'; import type Database from 'better-sqlite3'; export interface HealthReport { healthy: boolean; checks: HealthCheck[]; timestamp: Date; } export interface HealthCheck { name: string; healthy: boolean; latencyMs?: number; error?: string; } export class HealthChecker { /** * @param getDB 数据库获取器(用于真实验证数据库连通性) * @param dbPath 数据库文件路径(后备:文件存在性检查) */ constructor( private getDB?: () => Database.Database, private dbPath?: string, ) {} async check(): Promise { const checks: HealthCheck[] = []; checks.push(await this.checkDatabase()); checks.push(await this.checkDiskSpace()); checks.push(await this.checkMemoryUsage()); const allHealthy = checks.every((c) => c.healthy); return { healthy: allHealthy, checks, timestamp: new Date() }; } private async checkDatabase(): Promise { const start = Date.now(); try { // 优先使用注入的 DB 实例执行真实 ping if (this.getDB) { const db = this.getDB(); // 执行真实查询验证数据库连通性 db.prepare('SELECT 1').get(); return { name: 'database', healthy: true, latencyMs: Date.now() - start }; } // 后备:检查数据库文件是否存在 if (this.dbPath && existsSync(this.dbPath)) { return { name: 'database', healthy: true, latencyMs: Date.now() - start }; } return { name: 'database', healthy: false, error: 'Database not available' }; } catch (error) { return { name: 'database', healthy: false, error: error instanceof Error ? error.message : String(error), }; } } private async checkDiskSpace(): Promise { try { const userDataPath = app.getPath('userData'); if (!existsSync(userDataPath)) { return { name: 'disk_space', healthy: false, error: 'User data path not accessible' }; } // 检查实际可用磁盘空间(Windows/Linux 返回字节数) const { freemem } = await import('os'); const freeBytes = freemem(); const freeMB = freeBytes / (1024 * 1024); // 少于 200MB 视为不健康 if (freeMB < 200) { return { name: 'disk_space', healthy: false, error: `Free memory critically low: ${freeMB.toFixed(0)}MB available`, }; } return { name: 'disk_space', healthy: true }; } catch (error) { return { name: 'disk_space', healthy: false, error: error instanceof Error ? error.message : String(error), }; } } private async checkMemoryUsage(): Promise { const used = process.memoryUsage(); const heapUsedMB = used.heapUsed / 1024 / 1024; const thresholdMB = 512; return { name: 'memory_usage', healthy: heapUsedMB < thresholdMB, ...(heapUsedMB >= thresholdMB ? { error: `Heap usage ${heapUsedMB.toFixed(0)}MB exceeds threshold ${thresholdMB}MB` } : {}), }; } }