Sfoglia il codice sorgente

fix(server): app.ts 启动巡检,扫 BookChapter.audioUrl='/uploads/...' 脏数据

生产 nginx 不反代 /uploads/,任何 audioUrl 是本地路径的章节前端播放必 404。
本次清空 75 条历史脏数据(content 保留),由 AudioScanner 自动入队 TTS 重生成。
启动巡检保证未来脏数据立即报警(不 fail boot,避免历史数据阻塞启动)。

Co-Authored-By: Claude <noreply@anthropic.com>
MyFramework User 2 mesi fa
parent
commit
b53be328b2
1 ha cambiato i file con 27 aggiunte e 1 eliminazioni
  1. 27 1
      server/src/app.ts

+ 27 - 1
server/src/app.ts

@@ -13,7 +13,7 @@ import path from 'path';
 import fs from 'fs';
 import http from 'http';
 import { config } from './config';
-import { connectDatabase } from './models';
+import { connectDatabase, prisma } from './models';
 import { errorHandler } from './middleware/errorHandler';
 import { requestLogger } from './services/requestLogger';
 import { httpLogger } from './services/logger.service';
@@ -210,6 +210,32 @@ async function start() {
     // 5. 初始化 WebSocket 服务
     initWebSocket(server);
 
+    // 5.5 启动巡检:扫脏数据 audioUrl,防止 #audio-play-404-on-prod 复发
+    // 生产 nginx 不反代 /uploads/,任何 audioUrl 仍是 /uploads/... 的章节前端播放必 404。
+    // 这里只报警不 fail boot(避免历史脏数据导致服务起不来)。
+    try {
+      const dirty = await prisma.bookChapter.count({
+        where: { audioUrl: { startsWith: '/uploads/' } },
+      });
+      if (dirty > 0) {
+        console.error(`🚨 [BootWatchdog] 发现 ${dirty} 个 chapter 的 audioUrl 是本地路径 (/uploads/...)!`);
+        console.error(`🚨 [BootWatchdog] 生产 nginx 不反代 /uploads/,这些章节播放必 404。`);
+        console.error(`🚨 [BootWatchdog] 修复: cd server && STORAGE_TYPE=oss npx tsx scripts/fix-local-audio-urls.ts`);
+        // 列出前 5 个脏数据 chapter id 方便定位
+        const samples = await prisma.bookChapter.findMany({
+          where: { audioUrl: { startsWith: '/uploads/' } },
+          select: { id: true, level: true, audioUrl: true, bookId: true },
+          take: 5,
+          orderBy: { id: 'asc' },
+        });
+        console.error(`🚨 [BootWatchdog] 样例:`, JSON.stringify(samples));
+      } else {
+        console.log('✅ [BootWatchdog] 脏数据巡检通过:无 /uploads/... 本地路径 audioUrl');
+      }
+    } catch (e: any) {
+      console.warn('[BootWatchdog] 巡检异常(不阻塞启动):', e?.message || e);
+    }
+
     // 6. 启动服务
     // 清理 temp 目录中的残留临时文件
     FFmpegProcessor.cleanupAllTempFiles();