Files
photo-live/services/worker/test/reset.ts
T
2026-09-20 17:53:44 +08:00

108 lines
3.1 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.
// services/worker/test/reset.ts
// worker e2e 共用隔离工具(镜像 services/api/test/reset.ts):每个 e2e spec 的
// beforeAll 调用 resetDb()。MySQL 逐表 TRUNCATE(SET FOREIGN_KEY_CHECKS=0 包裹,
// users 被子表引用);MinIO 侧清理 photo-live/dev 前缀对象(worker 的 variants
// 写入与 api 的 staging/originals 同前缀)。S3Client 为 devDependencies
// (与 @photo/storage 内部同款)——StoragePort 不含列举/删除(YAGNI),隔离工具
// 直连 S3 协议。
import {
DeleteObjectsCommand,
ListObjectsV2Command,
S3Client,
} from '@aws-sdk/client-s3';
import { PrismaClient } from '@photo/db-cn';
export const RESET_TABLES: readonly string[] = [
// 与 api/test/reset.ts 同表同序(子表在前)。
'outbox_events',
'photo_jobs',
'photo_variants',
'upload_sessions',
'photos',
// 水印域(P4a Task 3,同 api/test/reset.ts)。
'watermark_jobs',
'watermark_configs',
'category_translations',
'categories',
'album_assets',
'album_translations',
'album_members',
'albums',
'audit_logs',
'sessions',
'users',
];
/** e2e 对象隔离边界:与 api src/uploads/support.ts 的 OBJECT_KEY_ROOT 一致。 */
const RESET_OBJECT_PREFIX = 'photo-live/dev/';
/** 删除 MinIO 中 RESET_OBJECT_PREFIX 前缀的全部对象(分页列举 + 批量删除)。 */
async function resetMinioObjects(): Promise<void> {
const required = [
'S3_ENDPOINT',
'S3_REGION',
'S3_ACCESS_KEY',
'S3_SECRET_KEY',
'S3_BUCKET',
] as const;
const missing = required.filter((key) => !process.env[key]);
if (missing.length > 0) {
throw new Error(`resetMinioObjects: 缺少环境变量 ${missing.join(', ')}`);
}
const client = new S3Client({
endpoint: process.env.S3_ENDPOINT,
region: process.env.S3_REGION,
credentials: {
accessKeyId: process.env.S3_ACCESS_KEY as string,
secretAccessKey: process.env.S3_SECRET_KEY as string,
},
forcePathStyle: true,
});
const bucket = process.env.S3_BUCKET as string;
try {
for (;;) {
const listed = await client.send(
new ListObjectsV2Command({
Bucket: bucket,
Prefix: RESET_OBJECT_PREFIX,
MaxKeys: 1000,
}),
);
const objects = (listed.Contents ?? []).filter(
(obj) => typeof obj.Key === 'string',
);
if (objects.length === 0) {
break;
}
await client.send(
new DeleteObjectsCommand({
Bucket: bucket,
Delete: {
Objects: objects.map((obj) => ({ Key: obj.Key as string })),
Quiet: true,
},
}),
);
if (!listed.IsTruncated) {
break;
}
}
} finally {
await client.destroy();
}
}
export async function resetDb(): Promise<void> {
await resetMinioObjects();
const prisma = new PrismaClient();
try {
await prisma.$executeRawUnsafe('SET FOREIGN_KEY_CHECKS = 0');
for (const table of RESET_TABLES) {
await prisma.$executeRawUnsafe(`TRUNCATE TABLE ${table}`);
}
} finally {
await prisma.$executeRawUnsafe('SET FOREIGN_KEY_CHECKS = 1');
await prisma.$disconnect();
}
}