package service import ( "log" "sync" "time" ) var ( rebateReleaseOnce sync.Once rebateReleaseStopMu sync.Mutex rebateReleaseStopCh chan struct{} rebateReleaseStopped bool rebateReleaseRunMu sync.Mutex rebateReleaseActive bool ) func StartRebateReleaseTask() { rebateReleaseOnce.Do(func() { rebateReleaseStopMu.Lock() defer rebateReleaseStopMu.Unlock() rebateReleaseStopCh = make(chan struct{}) rebateReleaseStopped = false go runRebateReleaseLoop(rebateReleaseStopCh) }) } func StopRebateReleaseTask() { rebateReleaseStopMu.Lock() defer rebateReleaseStopMu.Unlock() if rebateReleaseStopCh != nil && !rebateReleaseStopped { close(rebateReleaseStopCh) rebateReleaseStopped = true } } func RunRebateReleaseOnce() error { if !markRebateReleaseRunning() { return nil } defer unmarkRebateReleaseRunning() return ReleaseExpiredRebates() } func runRebateReleaseLoop(stopCh <-chan struct{}) { if err := RunRebateReleaseOnce(); err != nil { log.Printf("rebate release: %v", err) } ticker := time.NewTicker(time.Hour) defer ticker.Stop() for { select { case <-ticker.C: if err := RunRebateReleaseOnce(); err != nil { log.Printf("rebate release: %v", err) } case <-stopCh: return } } } func markRebateReleaseRunning() bool { rebateReleaseRunMu.Lock() defer rebateReleaseRunMu.Unlock() if rebateReleaseActive { return false } rebateReleaseActive = true return true } func unmarkRebateReleaseRunning() { rebateReleaseRunMu.Lock() defer rebateReleaseRunMu.Unlock() rebateReleaseActive = false }