feat: 抓取任务队列 + 媒体机直传 + 向量回填
crawl(品牌抓取任务队列) - /admin/internal/crawl/tasks 领取 / :id/result 回报,spider 可常驻拉任务 - 后台品牌列表支持「加入抓取队列」,队列页可看状态与重试 - 租约超时的 running 自动回收为 queued,避免 worker 崩溃后任务卡死 media(媒体机直传) - ingest 载荷新增 main_key/detail_keys/main_size/detail_sizes: 有 key 就直接落库,跳过下载与上传;与 URL 形态可逐图混用 - 细节图按 Details/DetailKeys 两者较长者遍历(只给 key 时不再丢图) - 媒体机上传的 key 不进失败回滚清单(内容寻址、可能与他人共享) - /admin/internal/upload-url 签发 S4 PUT 预签名(spider 不持有 AK/SK) embeddings(向量回填) - GET /admin/internal/embeddings/pending 派发缺向量的图(含可直接下载的 url) - POST /admin/internal/embeddings 回写向量并重算近邻;失败项计入 image_embedding_failures,连续失败到上限后退出队列(坏图不占位) - 近邻重算改为异步串行:同步会让 100 张的批次 POST 超时(实测 >60s) - 新增 key 分支单测:混用 key/url、细节图只给 key、字节数、回滚清单、向量占位
This commit is contained in:
57
internal/model/crawl_task.go
Normal file
57
internal/model/crawl_task.go
Normal file
@ -0,0 +1,57 @@
|
||||
package model
|
||||
|
||||
// CrawlTask 后台派发给爬虫服务的「品牌抓取任务」。
|
||||
//
|
||||
// 与 ingest_jobs 的分工:
|
||||
// - ingest_jobs:一场走秀的入库任务,由后端 worker 消费(下载图 / 写库 / 编码);
|
||||
// - crawl_tasks:一个品牌的抓取任务,由 spider 服务领取执行(可能在另一台机器)。
|
||||
//
|
||||
// 两层解耦的好处:后台只需表达「我要爬哪些品牌」,不必关心 spider 在哪、跑几个。
|
||||
// spider 拉不到任务就空转,任务积压也不会影响已有数据的读写。
|
||||
const (
|
||||
CrawlQueued = "queued" // 待领取
|
||||
CrawlRunning = "running" // 已被某个 worker 领取
|
||||
CrawlDone = "done" // 执行完成(不代表每场都入库成功,见 last_error)
|
||||
CrawlFailed = "failed" // 执行失败(spider 进程报错 / 品牌在 Vogue 无页面等)
|
||||
CrawlCanceled = "canceled" // 后台手动取消
|
||||
)
|
||||
|
||||
// CrawlStuckTimeoutSec 是 running 任务的租约时长:超过该时长仍未回报,
|
||||
// 视为 worker 已崩溃(断电 / 被杀),任务可被重新领取,避免永久卡在 running。
|
||||
const CrawlStuckTimeoutSec = 900
|
||||
|
||||
// CrawlMaxAttempts 自动重试上限;达到后置 failed,需后台手动「重试」。
|
||||
const CrawlMaxAttempts = 3
|
||||
|
||||
// CrawlTask 品牌抓取任务。
|
||||
// 时间字段与项目其它表一致,统一用 Unix 秒(uint32)。
|
||||
type CrawlTask struct {
|
||||
ID uint32 `gorm:"primaryKey;column:id" json:"id"`
|
||||
BrandID uint32 `gorm:"column:brand_id;not null" json:"brand_id"`
|
||||
// Status 见上方常量;默认 queued。
|
||||
Status string `gorm:"column:status;size:16;not null;default:'queued'" json:"status"`
|
||||
// Priority 越大越先被领取;用于「手动加的」优先于「批量加的」。
|
||||
Priority int16 `gorm:"column:priority;not null;default:0" json:"priority"`
|
||||
// MaxShows 单品牌最多抓几场(0=不限)。批量重爬历史品牌时用它控制入库量。
|
||||
MaxShows int16 `gorm:"column:max_shows;not null;default:0" json:"max_shows"`
|
||||
// Worker 领取者标识(主机名 + 进程号),便于排查「谁跑的」。
|
||||
Worker string `gorm:"column:worker;size:64;not null;default:''" json:"worker"`
|
||||
// LockedAt 领取时间,配合 CrawlStuckTimeoutSec 做租约回收。
|
||||
LockedAt uint32 `gorm:"column:locked_at;not null;default:0" json:"locked_at"`
|
||||
// Attempts 已被领取次数;用于自动重试与放弃判定。
|
||||
Attempts int16 `gorm:"column:attempts;not null;default:0" json:"attempts"`
|
||||
// ShowsSubmitted 本任务向 ingest 提交了多少场走秀(spider 回报)。
|
||||
ShowsSubmitted int32 `gorm:"column:shows_submitted;not null;default:0" json:"shows_submitted"`
|
||||
LastError string `gorm:"column:last_error;type:text" json:"last_error"`
|
||||
CreatedAt uint32 `gorm:"column:created_at;not null;default:0" json:"created_at"`
|
||||
UpdatedAt uint32 `gorm:"column:updated_at;not null;default:0" json:"updated_at"`
|
||||
}
|
||||
|
||||
// TableName 指定表名。
|
||||
func (CrawlTask) TableName() string { return "crawl_tasks" }
|
||||
|
||||
// CrawlTaskRow 是列表/领取接口用的投影行,附带品牌名(列表展示与拼 Vogue URL 都用得上)。
|
||||
type CrawlTaskRow struct {
|
||||
CrawlTask
|
||||
BrandName string `gorm:"column:brand_name"`
|
||||
}
|
||||
Reference in New Issue
Block a user