feat: 抓取期间每 60 秒打一次进度心跳

单场秀几百张图要抓几十分钟,期间 done 不变。
后台按「progress_at 超过 10 分钟没变」判卡死,会把正常但慢的抓取误报成卡死。
心跳只刷新时间戳,不改进度数字。
This commit is contained in:
toom1996
2026-10-25 20:50:05 +08:00
parent 7fce365d75
commit fb9b6c4f6e
2 changed files with 32 additions and 0 deletions

View File

@ -133,6 +133,23 @@ func executeBrand(ctx context.Context, taskID uint32, brandUID, brandName string
if config.GlobalConfig.Media.Upload && IngestClient != nil { if config.GlobalConfig.Media.Upload && IngestClient != nil {
s.Media = media.New(IngestClient, "runway", config.GlobalConfig.Media.Concurrency) s.Media = media.New(IngestClient, "runway", config.GlobalConfig.Media.Concurrency)
} }
// 心跳:单场秀可能有几百张图,一抓就是几十分钟,期间进度数字不会变。
// 没有它,后台会按「progress_at 超过 10 分钟没变」把正常抓取误判成卡死。
stop := make(chan struct{})
go func() {
t := time.NewTicker(60 * time.Second)
defer t.Stop()
for {
select {
case <-stop:
return
case <-t.C:
s.Heartbeat()
}
}
}()
defer close(stop)
shows = s.RunBrand(brandUID, brandName, maxShows) shows = s.RunBrand(brandUID, brandName, maxShows)
return shows, "" return shows, ""
} }

View File

@ -52,6 +52,8 @@ type VogueSpider struct {
// 「3/25 场 · Fall 2020 Ready-to-Wear」。并发抓取,故用原子操作。 // 「3/25 场 · Fall 2020 Ready-to-Wear」。并发抓取,故用原子操作。
progressDone int32 progressDone int32
progressTotal int32 progressTotal int32
// progressText 最近一次上报的秀标题,心跳重发时复用它。
progressText atomic.Value // string
// Media 媒体机直传器(可为 nil:为 nil 时走旧路径,上报 URL 由后端下载)。 // Media 媒体机直传器(可为 nil:为 nil 时走旧路径,上报 URL 由后端下载)。
Media *media.Uploader Media *media.Uploader
// submitted 本次品牌执行中成功上报的场次数(服务化模式回报给后台用)。 // submitted 本次品牌执行中成功上报的场次数(服务化模式回报给后台用)。
@ -345,6 +347,9 @@ func (s *VogueSpider) reportProgress(title string, done bool) {
if s.Ingest == nil || s.TaskID == 0 { if s.Ingest == nil || s.TaskID == 0 {
return return
} }
if title != "" {
s.progressText.Store(title)
}
n := int(atomic.LoadInt32(&s.progressDone)) n := int(atomic.LoadInt32(&s.progressDone))
if done { if done {
n = int(atomic.AddInt32(&s.progressDone, 1)) n = int(atomic.AddInt32(&s.progressDone, 1))
@ -355,6 +360,16 @@ func (s *VogueSpider) reportProgress(title string, done bool) {
} }
} }
// Heartbeat 只刷新后台的心跳时间,进度数字不变。
//
// 为什么需要:一场秀可能有几百张图,光下载就要几十分钟,
// 期间 done 一直是同一个数。没有心跳,后台的「10 分钟没推进」判定
// 会把「正常但很慢」误报成「卡死」。
func (s *VogueSpider) Heartbeat() {
title, _ := s.progressText.Load().(string)
s.reportProgress(title, false)
}
// getDetail 获取并解析单个发布会详情 // getDetail 获取并解析单个发布会详情
func (s *VogueSpider) getDetail(brandUID string, info gjson.Result) { func (s *VogueSpider) getDetail(brandUID string, info gjson.Result) {
hed := info.Get("hed").String() hed := info.Get("hed").String()