From fb9b6c4f6e7fbb59d28a1d4e7de03c07e25ea540 Mon Sep 17 00:00:00 2001 From: toom1996 <23cm.cn@gmail.com> Date: Sun, 25 Oct 2026 20:50:05 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8A=93=E5=8F=96=E6=9C=9F=E9=97=B4?= =?UTF-8?q?=E6=AF=8F=2060=20=E7=A7=92=E6=89=93=E4=B8=80=E6=AC=A1=E8=BF=9B?= =?UTF-8?q?=E5=BA=A6=E5=BF=83=E8=B7=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 单场秀几百张图要抓几十分钟,期间 done 不变。 后台按「progress_at 超过 10 分钟没变」判卡死,会把正常但慢的抓取误报成卡死。 心跳只刷新时间戳,不改进度数字。 --- cmd/serve.go | 17 +++++++++++++++++ internal/spider/vogue.go | 15 +++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/cmd/serve.go b/cmd/serve.go index 2968cd6..ba2fd0f 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -133,6 +133,23 @@ func executeBrand(ctx context.Context, taskID uint32, brandUID, brandName string if config.GlobalConfig.Media.Upload && IngestClient != nil { 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) return shows, "" } diff --git a/internal/spider/vogue.go b/internal/spider/vogue.go index 99d48e0..abeab72 100644 --- a/internal/spider/vogue.go +++ b/internal/spider/vogue.go @@ -52,6 +52,8 @@ type VogueSpider struct { // 「3/25 场 · Fall 2020 Ready-to-Wear」。并发抓取,故用原子操作。 progressDone int32 progressTotal int32 + // progressText 最近一次上报的秀标题,心跳重发时复用它。 + progressText atomic.Value // string // Media 媒体机直传器(可为 nil:为 nil 时走旧路径,上报 URL 由后端下载)。 Media *media.Uploader // submitted 本次品牌执行中成功上报的场次数(服务化模式回报给后台用)。 @@ -345,6 +347,9 @@ func (s *VogueSpider) reportProgress(title string, done bool) { if s.Ingest == nil || s.TaskID == 0 { return } + if title != "" { + s.progressText.Store(title) + } n := int(atomic.LoadInt32(&s.progressDone)) if done { 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 获取并解析单个发布会详情 func (s *VogueSpider) getDetail(brandUID string, info gjson.Result) { hed := info.Get("hed").String()