fix(snapshot): 修复备份进行中被删除导致容器崩溃的问题

1. checkDone 中 statSync 加 try-catch,文件被删时 reject 而非 uncaught crash
2. 删除 API 禁止删除 RUNNING 状态的任务,返回 409 Conflict
3. compose 补充 restart: unless-stopped,防止异常退出后服务不可用

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-02-25 01:30:44 -08:00
parent 18675f083c
commit 27db2a5aa2
4 changed files with 20 additions and 4 deletions

View File

@ -14,6 +14,7 @@ services:
context: ./snapshot-service
dockerfile: Dockerfile
container_name: rwa-snapshot-service-2
restart: unless-stopped
ports:
- "3199:3199"
environment:

View File

@ -85,6 +85,11 @@ export class SnapshotController {
@Delete(':id')
@ApiOperation({ summary: '删除备份' })
async deleteSnapshot(@Param('id') id: string) {
const task = await this.repo.findById(id);
if (!task) throw new NotFoundException('备份任务不存在');
if (task.status === 'RUNNING') {
throw new ConflictException('备份任务正在执行中,无法删除,请等待完成后再操作');
}
await this.orchestrator.deleteSnapshot(id);
return { message: '备份已删除' };
}

View File

@ -185,6 +185,10 @@ export class SnapshotOrchestratorService implements OnModuleInit {
const task = await this.repo.findById(taskId);
if (!task) throw new Error(`任务不存在: ${taskId}`);
if (task.status === SnapshotStatus.RUNNING) {
throw new Error('备份任务正在执行中,无法删除,请等待完成后再操作');
}
if (task.storageType === StorageType.LOCAL) {
this.localStorage.deleteTask(taskId);
} else if (task.storageType === StorageType.MINIO) {

View File

@ -119,10 +119,16 @@ export class PostgresBackupHandler implements BackupHandler {
if (dumpExitCode === null || gzipExitCode === null) return;
if (dumpExitCode === 0 && gzipExitCode === 0) {
try {
const stat = fs.statSync(filePath);
this.logger.log(`PostgreSQL 备份完成: ${fileName}, 压缩后: ${stat.size} bytes, 原始输出: ${bytesRead} bytes`);
onProgress(100, 'PostgreSQL 备份完成');
resolve({ fileName, filePath, fileSize: stat.size });
} catch (err) {
const msg = `备份文件不可访问 (可能已被删除): ${filePath}`;
this.logger.error(msg);
reject(new Error(msg));
}
} else {
const error = `pg_dumpall 退出码: ${dumpExitCode}, gzip 退出码: ${gzipExitCode}, stderr: ${stderrBuffer.slice(-500)}`;
this.logger.error(error);