gitee.com/quant1x/gox@v1.21.2/coroutine/periodic_once.go (about) 1 package coroutine 2 3 import ( 4 "gitee.com/quant1x/gox/cron" 5 "gitee.com/quant1x/gox/logger" 6 "gitee.com/quant1x/gox/runtime" 7 "sync" 8 "sync/atomic" 9 "time" 10 ) 11 12 const ( 13 cronPreMinute = "*/1 * * * *" 14 cronPreSecond = "*/1 * * * * ?" 15 cronDefaultInterval = "@every 1s" 16 periodicInitTime = "09:00:00" 17 ) 18 19 // PeriodicOnce 周期性懒加载机制 20 // 21 // Deprecated: 推荐 RollingOnce [wangfeng on 2024/1/22 10:33] 22 type PeriodicOnce struct { 23 done uint32 24 m sync.Mutex 25 once sync.Once 26 timer *cron.Cron 27 date string 28 lazyFunc func() 29 } 30 31 func (o *PeriodicOnce) Do(f func()) { 32 if o.lazyFunc == nil { 33 o.lazyFunc = f 34 } 35 o.once.Do(o.initTimer) 36 if atomic.LoadUint32(&o.done) == 0 { 37 o.doSlow(f) 38 } 39 } 40 41 func (o *PeriodicOnce) doSlow(f func()) { 42 o.m.Lock() 43 defer o.m.Unlock() 44 if o.done == 0 { 45 defer atomic.StoreUint32(&o.done, 1) 46 f() 47 } 48 } 49 50 func (o *PeriodicOnce) isExpired() bool { 51 currentDate := o.date 52 if currentDate < onceDefaultDate { 53 currentDate = onceDefaultDate 54 } 55 now := time.Now() 56 timestamp := now.Format(time.TimeOnly) 57 if timestamp >= periodicInitTime { 58 currentDate = now.Format(time.DateOnly) 59 } 60 if currentDate > o.date { 61 return true 62 } 63 return false 64 } 65 66 func (o *PeriodicOnce) initTimer() { 67 if o.timer == nil { 68 funcName := runtime.FuncName(o.lazyFunc) 69 o.timer = cron.New(cron.WithSeconds()) 70 _, err := o.timer.AddFuncWithSkipIfStillRunning(cronDefaultInterval, func() { 71 if o.isExpired() { 72 if runtime.Debug() { 73 logger.Infof("PeriodicOnce[%s]: reset begin", funcName) 74 } 75 o.Reset() 76 if runtime.Debug() { 77 logger.Infof("PeriodicOnce[%s]: reset end", funcName) 78 } 79 } 80 }) 81 if err == nil { 82 o.timer.Start() 83 } 84 } 85 } 86 87 // Reset 被动的方式重置初始化done标志 88 func (o *PeriodicOnce) Reset() { 89 if atomic.LoadUint32(&o.done) == 1 { 90 o.resetSlow() 91 } 92 } 93 94 func (o *PeriodicOnce) resetSlow() { 95 o.m.Lock() 96 defer o.m.Unlock() 97 if o.done == 1 { 98 atomic.StoreUint32(&o.done, 0) 99 // 重置日期 100 now := time.Now() 101 o.date = now.Format(time.DateOnly) 102 } 103 }