// services/api/test/reset-ov.ts —— ov 库(photo_ov)e2e 隔离工具(P2 Task 2)。 // 与 reset.ts 镜像但独立成文件:两库连接串不同(DATABASE_URL_OV vs _CN), // RESET_TABLES 互不重叠,cn/ov spec 各自 beforeAll 调用,互不清对方的数据。 // 与 reset.ts 的两点差异: // 1. 无 MinIO 清理——ov 侧 P2 只读对象(签名 URL 指向同一 MinIO,上传仍归 // cn 侧 e2e 的前缀清理负责); // 2. truncate-if-exists——经 information_schema 取「库中实际存在的待重置表」 // 再逐表 TRUNCATE(MySQL 无 TRUNCATE IF EXISTS):首次迁移前的空库上 // 调用是 no-op 而非报错,ov 库生命周期独立于 cn 库(compose profile ov)。 // ov 全库扁平字符串外键、无 FK 约束,FOREIGN_KEY_CHECKS 包裹仅沿用 reset.ts // 的防御性约定(后续如引入约束同样安全);表序仍按逻辑依赖排列(子表在前)。 import { PrismaClient } from '@photo/db-ov'; export const RESET_TABLES_OV: readonly string[] = [ // 统计回传队列与互动流水(Task 7-9 的幂等锚点)。 'outbox_stat_events', 'visit_requests', 'visit_sessions', 'like_batches', 'album_stats', // 同步账本(Task 4 inbox 消费)。 'sync_inbox', 'sync_state', // 副本域(photos 先于 albums;展示位副本相册无关,随副本域一并清)。 'photos_ov', 'albums_ov', 'embed_slots_ov', ]; /** TRUNCATE photo_ov 中 RESET_TABLES_OV 里**实际存在**的表(空库安全)。 */ export async function resetOvDb(): Promise { const prisma = new PrismaClient(); try { const placeholders = RESET_TABLES_OV.map(() => '?').join(', '); const existing = await prisma.$queryRawUnsafe< { tableName: string }[] >( `SELECT TABLE_NAME AS tableName FROM information_schema.TABLES ` + `WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME IN (${placeholders})`, ...RESET_TABLES_OV, ); await prisma.$executeRawUnsafe('SET FOREIGN_KEY_CHECKS = 0'); try { for (const { tableName } of existing) { await prisma.$executeRawUnsafe(`TRUNCATE TABLE \`${tableName}\``); } } finally { await prisma.$executeRawUnsafe('SET FOREIGN_KEY_CHECKS = 1'); } } finally { await prisma.$disconnect(); } }