feat(GOV-009): 建立后端契约与健康检查

This commit is contained in:
2026-08-13 17:26:51 +08:00
parent 3fc703de0b
commit 420aa22342
32 changed files with 1625 additions and 8 deletions
@@ -0,0 +1,135 @@
import { describe, expect, it } from 'vitest';
import { MysqlHealthClient, MYSQL_HEALTH_QUERY } from './mysql-health.client';
import { RedisHealthClient } from './redis-health.client';
import { buildTypeOrmOptions } from './typeorm-options';
describe('基础设施只读健康客户端', () => {
it('Redis 仅执行 PING 并返回健康状态', async () => {
const commands: string[] = [];
const client = new RedisHealthClient({
status: 'wait',
connect: async () => {
commands.push('CONNECT');
},
ping: async () => {
commands.push('PING');
return 'PONG';
},
quit: async () => 'OK',
});
await expect(client.check()).resolves.toEqual({ status: 'healthy', detail: 'PONG' });
expect(commands).toEqual(['CONNECT', 'PING']);
});
it('MySQL 使用固定元数据查询并校验 5.7 与数据库口径', async () => {
const queries: string[] = [];
const client = new MysqlHealthClient(
{
query: async (sql: string) => {
queries.push(sql);
return [
[
{
version: '5.7.42-log',
databaseName: 'a_share_analysis_dev',
charset: 'utf8mb4',
collation: 'utf8mb4_general_ci',
timezone: '+08:00',
},
],
[],
];
},
end: async () => undefined,
},
'a_share_analysis_dev',
);
await expect(client.check()).resolves.toEqual({
status: 'healthy',
detail: 'MySQL 5.7 / a_share_analysis_dev / +08:00',
});
expect(queries).toEqual([MYSQL_HEALTH_QUERY]);
});
it('MySQL 拒绝版本、库名或连接口径漂移', async () => {
const createClient = (override: Record<string, string>) =>
new MysqlHealthClient(
{
query: async () => [
[
{
version: '5.7.42',
databaseName: 'a_share_analysis_dev',
charset: 'utf8mb4',
collation: 'utf8mb4_general_ci',
timezone: '+08:00',
...override,
},
],
[],
],
end: async () => undefined,
},
'a_share_analysis_dev',
);
await expect(createClient({ version: '8.0.40' }).check()).rejects.toThrow(/MySQL 5.7/);
await expect(createClient({ databaseName: 'a_share_analysis' }).check()).rejects.toThrow(
/a_share_analysis_dev/,
);
await expect(createClient({ collation: 'utf8mb4_0900_ai_ci' }).check()).rejects.toThrow(
/utf8mb4_general_ci/,
);
});
it('MySQL 按当前配置校验生产库名', async () => {
const client = new MysqlHealthClient(
{
query: async () => [
[
{
version: '5.7.42',
databaseName: 'a_share_analysis',
charset: 'utf8mb4',
collation: 'utf8mb4_general_ci',
timezone: '+08:00',
},
],
[],
],
end: async () => undefined,
},
'a_share_analysis',
);
await expect(client.check()).resolves.toMatchObject({ status: 'healthy' });
});
});
describe('TypeORM MySQL 5.7 选项', () => {
it('禁止自动同步并固定字符集、排序规则和东八区', () => {
const options = buildTypeOrmOptions({
enabled: true,
host: '127.0.0.1',
port: 3306,
database: 'a_share_analysis_dev',
username: 'dev-user',
password: 'TEST_SENSITIVE_VALUE',
charset: 'utf8mb4',
collation: 'utf8mb4_general_ci',
timezone: '+08:00',
});
expect(options).toMatchObject({
type: 'mysql',
charset: 'utf8mb4',
timezone: '+08:00',
synchronize: false,
migrationsRun: false,
});
expect(options.extra).toMatchObject({ collation: 'utf8mb4_general_ci' });
});
});