This commit is contained in:
toom1996
2026-09-07 00:04:01 +08:00
parent 6a5a4378ab
commit 10d8a96e8c
29 changed files with 5349 additions and 0 deletions

View File

@ -0,0 +1,57 @@
package model
// IngestJob 爬虫上报的走秀入库任务队列。
//
// 设计:爬虫 POST 到 :8092 的 ingest 接口(HMAC 验签后)只做「入队 + 立即 202」,
// 真正的去重 / 补分类 / 下载图 / 写正式表 由后台 worker 异步处理,
// 因此接口本身很薄、不会被慢任务(尤其是 OSS 上传)拖垮。
//
// 并发安全靠 MySQL 的 `SELECT ... FOR UPDATE SKIP LOCKED`:多个 worker 同时
// Claim 不会抢到同一条,未提交的行对其它 worker 不可见。
type IngestJob struct {
ID uint32 `gorm:"primaryKey;column:id" json:"id"`
CreatedAt uint32 `gorm:"column:created_at" json:"created_at"`
UpdatedAt uint32 `gorm:"column:updated_at" json:"updated_at"`
LockedAt uint32 `gorm:"column:locked_at" json:"locked_at"` // worker 领取时间;用于超时兜底回收
SourceURL string `gorm:"column:source_url" json:"source_url"`
Status string `gorm:"column:status;size:16;not null;default:'pending'" json:"status"` // pending|processing|done|failed
Attempts uint8 `gorm:"column:attempts;not null;default:0" json:"attempts"`
Payload string `gorm:"column:payload;type:text" json:"payload"` // 原始 JSON(RunwayIngest 或 MediaCleanupPayload)
LastError string `gorm:"column:last_error;type:text" json:"last_error"`
Kind string `gorm:"column:kind;size:16;not null;default:'crawl'" json:"kind"` // crawl|media_cleanup
NextAttemptAt uint32 `gorm:"column:next_attempt_at;not null;default:0" json:"next_attempt_at"` // 重试退避:到达该 unix 时间才可被领取
}
// TableName 指定队列表名。
func (IngestJob) TableName() string { return "ingest_jobs" }
// IngestJob 状态常量。
const (
IngestStatusPending = "pending"
IngestStatusProcessing = "processing"
IngestStatusDone = "done"
IngestStatusFailed = "failed"
)
// IngestJob 任务类型(kind 列):区分「爬虫入库」与「清理七牛孤儿图」两条管线。
const (
IngestKindCrawl = "crawl" // 爬虫上报的走秀/街拍入库
IngestKindMediaCleanup = "media_cleanup" // 删除图集时异步清理七牛孤儿文件
)
// IngestMaxAttempts 单条任务最大处理次数(含首次)。达上限仍未成功则置 failed,需后台手动重试。
const IngestMaxAttempts = 3
// IngestStuckTimeoutSec 任务「卡死」判定阈值:worker 领取后 processing 状态持续超过该秒数,
// 视为 worker 崩溃/被杀遗留,由 Claim 兜底回收为 pending 重领。下载图/传图正常远低于此值。
const IngestStuckTimeoutSec = 300
// IngestRetryBackoff 返回第 attempts 次失败后的退避秒数(指数退避,封顶 600s)。
// attempts 从 1 起算:30s / 60s / 120s。用于失败任务的自动重试调度。
func IngestRetryBackoff(attempts int) int {
d := 30 * (1 << uint(attempts-1))
if d > 600 {
d = 600
}
return d
}