package main import "time" type TimeProvider interface { Now() time.Time Sleep(d time.Duration) NewTicker(d time.Duration) Ticker } type Ticker interface { C() <-chan time.Time Stop() } type realTimeProvider struct{} func (realTimeProvider) Now() time.Time { return time.Now() } func (realTimeProvider) Sleep(d time.Duration) { time.Sleep(d) } func (realTimeProvider) NewTicker(d time.Duration) Ticker { return realTicker{time.NewTicker(d)} } type realTicker struct { *time.Ticker } func (rt realTicker) C() <-chan time.Time { return rt.Ticker.C } // Return ticker for cron which tick at 0 and ticker for reloading config ticking 10 secounds before func createTickers(tp TimeProvider) (<-chan time.Time, <-chan time.Time) { nextTick := func(targetSecond int) time.Duration { now := tp.Now() next := now.Truncate(time.Minute).Add(time.Duration(targetSecond) * time.Second) if !next.After(now) { next = next.Add(time.Minute) } return next.Sub(now) } tickAt := func(targetSecond int) <-chan time.Time { ch := make(chan time.Time) go func() { tp.Sleep(nextTick(targetSecond)) ticker := tp.NewTicker(time.Minute) for { ch <- tp.Now() <-ticker.C() } }() return ch } return tickAt(0), tickAt(50) }