package worker import ( "log" "sync/atomic" "time" "git.gozeros.com/wsk/eightbf-analysis-go/internal/domain" "git.gozeros.com/wsk/eightbf-analysis-go/internal/repo" ) // LiveWorker 定时扫 queued,最多并发 2 场交给 LiveChainRunner。 type LiveWorker struct { Repo *repo.JobRepo Runner *LiveChainRunner PollEvery time.Duration inflight int32 } func (w *LiveWorker) Start() { if w.PollEvery <= 0 { w.PollEvery = time.Second } go func() { t := time.NewTicker(w.PollEvery) defer t.Stop() for range t.C { w.poll() } }() } func (w *LiveWorker) poll() { if atomic.LoadInt32(&w.inflight) >= 2 { return } queued, err := w.Repo.FindQueuedJobs() if err != nil { log.Printf("LiveWorker 扫队列失败: %v", err) return } for _, job := range queued { if atomic.LoadInt32(&w.inflight) >= 2 { break } job.Status = domain.StatusRunning job.Phase = "claimed" if err := w.Repo.UpdateProgress(job); err != nil { log.Printf("LiveWorker 占坑失败 jobId=%s: %v", job.ID, err) continue } atomic.AddInt32(&w.inflight, 1) jobID := job.ID go func() { defer atomic.AddInt32(&w.inflight, -1) fresh, err := w.Repo.FindByID(jobID) if err != nil || fresh == nil { return } log.Printf("开始真模型会商 jobId=%s", jobID) w.Runner.Run(fresh) }() } }