cursor-init/src/modules/health/health.service.ts
expressgy a23d336ebd refactor: 重构项目架构并标准化开发规范
- 重构项目结构:controllers/services -> modules模块化组织

- 新增Drizzle ORM集成和数据库schema定义

- 添加完整的开发规范文档(.cursor/rules/)

- 重新组织插件结构为子目录方式

- 新增用户模块和示例代码

- 更新类型定义并移除试验性代码

- 添加API文档和JWT使用示例

关联任务计划文档
2025-06-30 01:25:17 +08:00

300 lines
9.4 KiB
TypeScript
Raw 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.

/**
* @file 健康检查服务
* @author hotok
* @date 2025-06-28
* @lastEditor hotok
* @lastEditTime 2025-06-28
* @description 系统健康状态检查业务逻辑包括数据库、Redis等依赖检查
*/
import type { Context } from 'elysia';
import { Redis } from '@/utils/redis';
import { pool } from '@/utils/mysql';
import { Logger } from '@/plugins/logger/logger.service';
// 临时内联类型定义
interface ComponentStatus {
status: 'healthy' | 'unhealthy' | 'degraded';
responseTime?: number;
error?: string;
details?: Record<string, any>;
}
interface HealthStatus {
code: number;
message: string;
data: {
status: 'healthy' | 'unhealthy' | 'degraded';
timestamp: string;
uptime: number;
responseTime: number;
version: string;
environment: string;
error?: string;
components: {
mysql?: ComponentStatus;
redis?: ComponentStatus;
[key: string]: ComponentStatus | undefined;
};
};
}
interface DetailedHealthStatus extends HealthStatus {
data: HealthStatus['data'] & {
system?: {
platform: string;
arch: string;
nodeVersion: string;
runtime: string;
pid: number;
cwd: string;
};
performance?: {
cpuUsage: {
user: number;
system: number;
};
memoryUsage: {
rss: number;
heapTotal: number;
heapUsed: number;
external: number;
arrayBuffers: number;
};
uptime: number;
};
};
}
/**
* 健康检查服务类
* 提供系统及依赖服务的健康状态检查
*/
class HealthService {
/**
* Redis实例
*/
private redis: Redis;
constructor() {
this.redis = new Redis();
}
/**
* 获取基本健康状态
* @param ctx Elysia上下文
* @returns 健康状态信息
*/
async getHealthStatus(ctx: Context): Promise<HealthStatus> {
const startTime = Date.now();
const timestamp = new Date().toISOString();
try {
// 并行检查所有依赖
const [mysqlStatus, redisStatus] = await Promise.allSettled([
this.checkMysqlHealth(),
this.checkRedisHealth(),
]);
/** 系统整体状态 */
const overallStatus = this.determineOverallStatus([
mysqlStatus.status === 'fulfilled' ? mysqlStatus.value : { status: 'unhealthy', error: 'Connection failed' },
redisStatus.status === 'fulfilled' ? redisStatus.value : { status: 'unhealthy', error: 'Connection failed' },
]);
const responseTime = Date.now() - startTime;
return {
code: overallStatus === 'healthy' ? 0 : 1,
message: overallStatus === 'healthy' ? '所有服务运行正常' : '部分服务异常',
data: {
status: overallStatus,
timestamp,
uptime: process.uptime(),
responseTime,
version: process.env.npm_package_version || '1.0.0',
environment: process.env.NODE_ENV || 'development',
components: {
mysql: mysqlStatus.status === 'fulfilled' ? mysqlStatus.value : { status: 'unhealthy', error: 'Connection failed' },
redis: redisStatus.status === 'fulfilled' ? redisStatus.value : { status: 'unhealthy', error: 'Connection failed' },
},
},
};
} catch (error) {
Logger.error(error as Error);
return {
code: 1,
message: '健康检查异常',
data: {
status: 'unhealthy',
timestamp,
uptime: process.uptime(),
responseTime: Date.now() - startTime,
version: process.env.npm_package_version || '1.0.0',
environment: process.env.NODE_ENV || 'development',
error: 'Health check failed',
components: {},
},
};
}
}
/**
* 获取详细健康状态
* @param ctx Elysia上下文
* @returns 详细健康状态信息
*/
async getDetailedHealthStatus(ctx: Context): Promise<DetailedHealthStatus> {
const startTime = Date.now();
const timestamp = new Date().toISOString();
try {
// 获取基本健康状态
const basicHealth = await this.getHealthStatus(ctx);
// 获取系统资源信息
const systemInfo = this.getSystemInfo();
return {
...basicHealth,
data: {
...basicHealth.data,
system: systemInfo,
performance: {
cpuUsage: process.cpuUsage(),
memoryUsage: process.memoryUsage(),
uptime: process.uptime(),
},
},
};
} catch (error) {
Logger.error(error as Error);
return {
code: 1,
message: '详细健康检查异常',
data: {
status: 'unhealthy',
timestamp,
uptime: process.uptime(),
responseTime: Date.now() - startTime,
version: process.env.npm_package_version || '1.0.0',
environment: process.env.NODE_ENV || 'development',
error: 'Detailed health check failed',
components: {},
},
};
}
}
/**
* 检查MySQL健康状态
* @returns MySQL组件状态
*/
private async checkMysqlHealth(): Promise<ComponentStatus> {
try {
const startTime = Date.now();
await pool.execute('SELECT 1');
const responseTime = Date.now() - startTime;
return {
status: 'healthy',
responseTime,
details: {
connection: 'active',
host: process.env.DB_HOST || 'localhost',
port: process.env.DB_PORT || '3306',
},
};
} catch (error) {
Logger.error(error as Error);
return {
status: 'unhealthy',
error: (error as Error).message,
details: {
connection: 'failed',
host: process.env.DB_HOST || 'localhost',
port: process.env.DB_PORT || '3306',
},
};
}
}
/**
* 检查Redis健康状态
* @returns Redis组件状态
*/
private async checkRedisHealth(): Promise<ComponentStatus> {
try {
const startTime = Date.now();
const isHealthy = await this.redis.checkRedisHealth();
const responseTime = Date.now() - startTime;
if (isHealthy) {
const redisStatus = this.redis.getRedisStatus();
return {
status: 'healthy',
responseTime,
details: {
connection: 'active',
...redisStatus.config,
},
};
} else {
return {
status: 'unhealthy',
error: 'Redis ping failed',
details: {
connection: 'failed',
},
};
}
} catch (error) {
Logger.error(error as Error);
return {
status: 'unhealthy',
error: (error as Error).message,
details: {
connection: 'failed',
},
};
}
}
/**
* 确定整体状态
* @param components 各组件状态
* @returns 整体状态
*/
private determineOverallStatus(components: ComponentStatus[]): 'healthy' | 'unhealthy' | 'degraded' {
const healthyCount = components.filter(c => c.status === 'healthy').length;
const totalCount = components.length;
if (healthyCount === totalCount) {
return 'healthy';
} else if (healthyCount === 0) {
return 'unhealthy';
} else {
return 'degraded';
}
}
/**
* 获取系统信息
* @returns 系统信息
*/
private getSystemInfo() {
return {
platform: process.platform,
arch: process.arch,
nodeVersion: process.version,
runtime: 'Bun',
pid: process.pid,
cwd: process.cwd(),
};
}
}
/**
* 导出健康检查服务实例
*/
export const healthService = new HealthService();