/** * 测试:通过 TtsQueue 路径发 TTS 请求,验证日志是否入库 * 模拟真实的 book generation → TtsQueue → TTS provider 流程 */ import { prisma } from '../src/models'; import { generateAudio } from '../src/modules/tts/tts.service'; async function main() { const beforeCount = await prisma.aiCallLog.count(); console.log(`基线 AiCallLog: ${beforeCount}`); // 直接调用 generateAudio(这是 processTtsTask 内部调用的函数) console.log('\n发送 3 次 generateAudio(文本="测试音频1234567890")...'); for (let i = 0; i < 3; i++) { try { await generateAudio( '1', // userId `测试音频${i + 1},这是用于验证TTS日志记录完整性的测试文本。`.repeat(3), // text ~150字 'default', // voiceId { speed: 1, pitch: 0, volume: 50 }, undefined, // onComplete { bookId: '999', chapterId: 999, chapterTitle: `测试章节${i + 1}`, } ); console.log(` #${i + 1}: ✅ generateAudio 返回成功`); } catch (err: any) { console.log(` #${i + 1}: ❌ ${err.message?.substring(0, 80)}`); } } // 等待异步日志落库 await new Promise(r => setTimeout(r, 3000)); const afterCount = await prisma.aiCallLog.count(); const newRecords = afterCount - beforeCount; console.log(`\n=== 结果 ===`); console.log(`新增 AiCallLog: ${newRecords} 条`); // 按类型拆分 const byType = await prisma.aiCallLog.groupBy({ by: ['callType', 'provider', 'success'], where: { id: { gt: beforeCount } }, _count: { id: true }, }); let total = 0; for (const t of byType) { const s = t.success ? '✅' : '❌'; console.log(` ${s} ${t.callType.padEnd(25)} ${(t.provider || '-').padEnd(12)} ${t._count.id} 次`); total += t._count.id; } console.log(` ---`); console.log(` 实际总记录: ${total} (新增: ${afterCount - beforeCount})`); if (total === 0) { console.log('\n❌ 问题:generateAudio 路径完全没有日志记录!'); console.log(' 可能原因:'); console.log(' 1. withAiLog 在 provider.synthesize 中没有被调用'); console.log(' 2. 或者 processAudioGeneration 中 provider 全部不可用时直接抛异常'); console.log(' 3. 或者 logAiCall 的 fire-and-forget 写入失败'); } else { console.log(`\n✅ generateAudio 路径有 ${total} 条日志记录`); } await prisma.$disconnect(); } main().catch(e => { console.error(e); process.exit(1); });