diff --git a/backend/services/snapshot-service/src/application/services/snapshot-orchestrator.service.ts b/backend/services/snapshot-service/src/application/services/snapshot-orchestrator.service.ts index 752bc4a8..912b0cb1 100644 --- a/backend/services/snapshot-service/src/application/services/snapshot-orchestrator.service.ts +++ b/backend/services/snapshot-service/src/application/services/snapshot-orchestrator.service.ts @@ -36,12 +36,23 @@ export class SnapshotOrchestratorService implements OnModuleInit { } async onModuleInit(): Promise { + // 1. 标记数据库中遗留的 RUNNING 任务为 FAILED const stale = await this.repo.findByStatus(SnapshotStatus.RUNNING); for (const task of stale) { await this.repo.updateTaskStatus(task.id, SnapshotStatus.FAILED, '服务重启,任务中断'); this.localStorage.deleteTask(task.id); this.logger.warn(`遗留任务已标记失败: ${task.id}`); } + + // 2. 扫描临时目录,清理数据库中不存在的孤儿目录 + const dirIds = this.localStorage.listTaskDirs(); + for (const dirId of dirIds) { + const task = await this.repo.findById(dirId); + if (!task) { + this.localStorage.deleteTask(dirId); + this.logger.warn(`清理孤儿临时目录: ${dirId}`); + } + } } getAvailableTargets(): BackupTarget[] { diff --git a/backend/services/snapshot-service/src/infrastructure/storage/local-storage.adapter.ts b/backend/services/snapshot-service/src/infrastructure/storage/local-storage.adapter.ts index 6b56a55c..21b145c7 100644 --- a/backend/services/snapshot-service/src/infrastructure/storage/local-storage.adapter.ts +++ b/backend/services/snapshot-service/src/infrastructure/storage/local-storage.adapter.ts @@ -36,6 +36,14 @@ export class LocalStorageAdapter { } } + /** 列出临时目录中所有任务子目录的 ID */ + listTaskDirs(): string[] { + if (!fs.existsSync(this.tempDir)) return []; + return fs.readdirSync(this.tempDir, { withFileTypes: true }) + .filter((e) => e.isDirectory()) + .map((e) => e.name); + } + cleanupExpired(retentionHours: number): string[] { const threshold = Date.now() - retentionHours * 60 * 60 * 1000; const deletedIds: string[] = [];