gongxiangp2/instrumentation.ts
chenpei 7326e273e1 fix: harden media upload and release safety
Protect upload cleanup and atomic completion paths, add durable media worker leases and brand asset validation, and introduce verified migration/bootstrap/deployment gates.
2026-08-12 18:04:08 +08:00

67 lines
2.8 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.

/**
* Next.js Instrumentation
*
* 这个文件在应用启动时执行,用于:
* 1. 启动临时文件定时清理任务
* 2. 初始化其他需要在启动时运行的服务
*/
export async function register() {
// 只在 Node.js 服务端运行(不在 Edge 运行时)
if (process.env.NEXT_RUNTIME === 'nodejs') {
console.log('[Instrumentation] Next.js 服务端启动...')
// 启动临时文件清理任务
try {
const { startCleanupScheduler } = await import('./lib/temp-cleanup')
startCleanupScheduler()
console.log('[Instrumentation] 临时文件清理任务已启动')
} catch (error) {
console.error('[Instrumentation] 启动清理任务失败:', error)
}
const recoveryGlobal = globalThis as typeof globalThis & {
__taskDetailUploadRecoveryStarted?: boolean
}
if (!recoveryGlobal.__taskDetailUploadRecoveryStarted) {
recoveryGlobal.__taskDetailUploadRecoveryStarted = true
// 先注册周期任务,再做首次恢复。数据库启动瞬时不可用时,后续周期仍会重试,
// 不会因为一次失败让 processing/queued 任务永久无人处理。
setInterval(() => {
void import('./lib/task-detail-upload-jobs')
.then(({ recoverTaskDetailUploadJobs }) => recoverTaskDetailUploadJobs())
.catch((error) => {
console.error('[Instrumentation] 任务-详情后台队列周期恢复失败:', error)
})
}, 60_000)
}
try {
const { recoverTaskDetailUploadJobs } = await import('./lib/task-detail-upload-jobs')
await recoverTaskDetailUploadJobs()
console.log('[Instrumentation] 任务-详情后台队列恢复检查完成')
} catch (error) {
// 迁移未执行或数据库暂不可用时只记录;周期恢复已提前注册,会继续重试。
console.error('[Instrumentation] 任务-详情后台队列恢复失败:', error)
}
const videoRecoveryGlobal = globalThis as typeof globalThis & {
__videoTranscodeRecoveryScheduler?: {
initial: Promise<number>
}
}
if (!videoRecoveryGlobal.__videoTranscodeRecoveryScheduler) {
const { createVideoTranscodeRecoveryScheduler } = await import('./lib/video-transcode-recovery')
const scheduler = createVideoTranscodeRecoveryScheduler()
videoRecoveryGlobal.__videoTranscodeRecoveryScheduler = scheduler
try {
const recovered = await scheduler.initial
console.log(`[Instrumentation] 视频转码启动恢复完成,重新入队 ${recovered} 个任务`)
} catch (error) {
// 周期调度器已先注册;数据库瞬时不可用时,60 秒后会继续重试。
console.error('[Instrumentation] 视频转码启动恢复失败,已保留周期重试:', error)
}
}
}
}