package monthlyusage import ( "context" "github.com/gogf/gf/v2/frame/g" "git.5iot.com/iotlcm-public/iotlcm-worker-svr/internal/fullsync/supply" "time" ) func (p *Producer) observe(key, stage string, pending int, added, ended bool) { if p.observation != nil { p.observation.Event(key, stage, pending, added, ended, time.Now()) } } func (p *Producer) startObservation(ctx context.Context, run string, keys []string, started time.Time) func(bool) { tracker := p.config.SupplyObservation if tracker == nil { return func(bool) {} } o := supply.New(newOwner(), started, keys) p.observation = o readCtx, readCancel := context.WithTimeout(context.Background(), 500*time.Millisecond) meta, err := p.store.GetRunMeta(readCtx, run) readCancel() if err != nil { o.Partial() } else if meta.SupplyObservation != nil { o.Restore(*meta.SupplyObservation) } tracker.Put(run, o) stop := make(chan struct{}) done := make(chan struct{}) flush := func() { writeCtx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) defer cancel() encoded, e := o.Encode() if e == nil { var saved bool saved, e = p.store.SaveSupply(writeCtx, run, p.config.RunLockKey, p.owner, encoded) if !saved && e == nil { o.Partial() } } if e != nil { o.Partial() g.Log().Warningf(writeCtx, "event=supply_observation status=partial runId=%s error=%q", run, e.Error()) } } go func() { defer close(done) sampleTicker := time.NewTicker(time.Second) defer sampleTicker.Stop() flushTicker := time.NewTicker(10 * time.Second) defer flushTicker.Stop() for { select { case <-stop: return case <-ctx.Done(): o.Partial() return case <-flushTicker.C: flush() case <-sampleTicker.C: views := o.Views() sampleCtx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) samples, e := p.store.ReadSupply(sampleCtx, run, keys, time.Now()) cancel() now := time.Now() for _, key := range keys { s := samples[key] if e != nil || !tracker.LocalConsumer || !tracker.ConsumerActive.Load() { s.Known = false } o.Apply(key, views[key], s, now) } } } }() return func(success bool) { close(stop) <-done if !success { o.Partial() } flush() tracker.Remove(run) p.observation = nil } }