github.com/mailru/activerecord@v1.12.2/pkg/iproto/syncutil/throttle.go (about) 1 package syncutil 2 3 import ( 4 "sync" 5 "time" 6 ) 7 8 // NewThrottle creates new Throttle with given period. 9 func NewThrottle(p time.Duration) *Throttle { 10 return &Throttle{ 11 period: p, 12 } 13 } 14 15 // Throttle helps to run a function only a once per given time period. 16 type Throttle struct { 17 mu sync.RWMutex 18 period time.Duration 19 last time.Time 20 } 21 22 // Do executes fn if Throttle's last execution time is far enough in the past. 23 func (t *Throttle) Next() (ok bool) { 24 now := time.Now() 25 26 t.mu.RLock() 27 28 ok = now.Sub(t.last) >= t.period 29 t.mu.RUnlock() 30 31 if !ok { 32 return 33 } 34 35 t.mu.Lock() 36 37 ok = now.Sub(t.last) >= t.period 38 if ok { 39 t.last = now 40 } 41 42 t.mu.Unlock() 43 44 return 45 } 46 47 // Reset resets the throttle timeout such that next Next() will return true. 48 func (t *Throttle) Reset() { 49 t.mu.Lock() 50 t.last = time.Time{} 51 t.mu.Unlock() 52 } 53 54 // Set sets throttle point such that Next() will return true only after given 55 // moment p. 56 func (t *Throttle) Set(p time.Time) { 57 t.mu.Lock() 58 t.last = p.Add(-t.period) 59 t.mu.Unlock() 60 }