26 lines
2.2 KiB
TypeScript
26 lines
2.2 KiB
TypeScript
import { DeleteObjectCommand, type S3Client } from '@aws-sdk/client-s3';
|
|
import type { Database } from '@atlas/database';
|
|
import type { OutboxJob } from './outbox-dispatcher.js';
|
|
|
|
type DeletionRow = { status: string; objects: Array<{ storage_provider: string; bucket: string; object_key: string }> };
|
|
/** 清理对象可重复执行;保留数据库事实,只有全部存储删除成功才报告完成。 */
|
|
export async function runMediaAssetDeletion(database: Database, storageFor: (provider: string) => S3Client, job: OutboxJob) {
|
|
const id = String(job.payload.deletion_id);
|
|
await database.workspaceTransaction(job.workspaceId, async tx => {
|
|
const result = await tx.query<DeletionRow>('SELECT status, objects FROM atlas.product_image_deletions WHERE id = $1 FOR UPDATE', [id]);
|
|
const row = result.rows[0];
|
|
if (!row || row.status === 'succeeded') return;
|
|
await tx.query("UPDATE atlas.operations SET status = 'running', started_at = coalesce(started_at, now()), attempt_count = attempt_count + 1 WHERE id = $1", [id]);
|
|
for (const object of row.objects) await storageFor(object.storage_provider).send(new DeleteObjectCommand({ Bucket: object.bucket, Key: object.object_key }));
|
|
await tx.query("UPDATE atlas.operations SET status = 'succeeded', error_code = NULL, error_message = NULL, completed_at = now() WHERE id = $1", [id]);
|
|
await tx.query("UPDATE atlas.product_image_deletions SET status = 'succeeded', error_code = NULL, completed_at = now() WHERE id = $1", [id]);
|
|
});
|
|
}
|
|
export async function markMediaAssetDeletionFailed(database: Database, job: OutboxJob) {
|
|
await database.workspaceTransaction(job.workspaceId, async tx => {
|
|
const id = String(job.payload.deletion_id);
|
|
const result = await tx.query("UPDATE atlas.product_image_deletions SET status = 'failed', error_code = 'MEDIA_STORAGE_DELETE_FAILED', completed_at = now() WHERE id = $1 AND status <> 'succeeded'", [id]);
|
|
if (result.rowCount) await tx.query("UPDATE atlas.operations SET status = 'failed', error_code = 'MEDIA_STORAGE_DELETE_FAILED', error_message = '图片存储文件清理失败,可重试', completed_at = now() WHERE id = $1", [id]);
|
|
});
|
|
}
|