feat(worker): watermark versioning with atomic history regeneration

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-09-20 17:53:44 +08:00
parent 6723a0ce88
commit 243b2f8721
34 changed files with 3057 additions and 78 deletions
+39
View File
@@ -65,7 +65,15 @@ model albums {
publicEnabled Boolean @default(true)
downloadEnabled Boolean @default(true)
originalDownloadEnabled Boolean @default(false)
// ── 水印版本化(P4a Task 3)── 双版本位语义(权威表述见 contracts watermark.ts):
// watermarkVersion = 最新「已创建」配置版本(POST 即推进,新照片发布即刻套用,
// 也就是契约 AlbumSummary.watermarkVersion / WatermarkJobCreated.configVersion);
// watermarkEnabled + watermarkEffectiveVersion = 「有效」版本位——仅当该版本的
// 历史重生成任务 done 才推进(worker 完成事务维护,禁用版同样推进以翻转
// enabled=false)。ov 副本与公开侧变体选择以有效版本为准(对象存在性保证)。
watermarkVersion Int @default(0)
watermarkEnabled Boolean @default(false)
watermarkEffectiveVersion Int @default(0)
entityVersion Int @default(1) // P2 Task 3:album.updated 事件版本(同 photos 模式)
// P2 Task 9 统计回传副本位(ov→cn):viewCountReplica 为 ov album_stats
// 权威值的替换式副本;statsVersion 是回传替换版本(仅更高 statVersion 替换,
@@ -205,6 +213,37 @@ model photo_jobs {
@@unique([photoId, type])
@@index([state, nextRetryAt])
}
// —— 水印版本化(P4a Task 3)——
// watermark_configs:配置版本账本(append-only,每 POST 一行,config 为归一化
// StoredWatermarkConfig——contracts watermark.ts 的形状,缺省已填齐);
// watermark_jobs:历史重生成任务(id 兼作对外 jobId 与 BullMQ jobId——cuid 无
// ':',满足 BullMQ 保留分隔符约束)。state 语义:pending=已入队待消费;
// running=消费中(progress/failed 随照片逐张推进);done=全部处理完成(允许
// failed>0 的部分成功——失败张数记录在案,重试=重新 POST 新任务,按照片粒度
// 幂等);failed=整任务中止(配置缺失等任务级错误,errorCode 必有)。
model watermark_configs {
id String @id @default(cuid())
albumId String @db.VarChar(64)
configVersion Int
config Json
createdAt DateTime @default(now()) @db.DateTime(6)
@@unique([albumId, configVersion])
}
model watermark_jobs {
id String @id @default(cuid())
albumId String @db.VarChar(64)
configVersion Int
state String @default("pending") @db.VarChar(16) // pending|running|done|failed
progress Int @default(0)
total Int @default(0)
failed Int @default(0)
errorCode String? @db.VarChar(64)
createdAt DateTime @default(now()) @db.DateTime(6)
updatedAt DateTime @updatedAt @db.DateTime(6)
@@index([albumId, createdAt])
}
model outbox_events {
id String @id @default(cuid())
type String @db.VarChar(64)