github.com/uber/kraken@v0.1.4/utils/dedup/interval_trap.go (about) 1 // Copyright (c) 2016-2019 Uber Technologies, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 package dedup 15 16 import ( 17 "sync" 18 "time" 19 20 "github.com/andres-erbsen/clock" 21 ) 22 23 // IntervalTask defines a task to run on some interval. 24 type IntervalTask interface { 25 Run() 26 } 27 28 // IntervalTrap manages trapping into some task which must run at a given interval. 29 type IntervalTrap struct { 30 sync.RWMutex 31 clk clock.Clock 32 interval time.Duration 33 prev time.Time 34 task IntervalTask 35 } 36 37 // NewIntervalTrap creates a new IntervalTrap. 38 func NewIntervalTrap( 39 interval time.Duration, clk clock.Clock, task IntervalTask) *IntervalTrap { 40 41 return &IntervalTrap{ 42 clk: clk, 43 interval: interval, 44 prev: clk.Now(), 45 task: task, 46 } 47 } 48 49 func (t *IntervalTrap) ready() bool { 50 return t.clk.Now().After(t.prev.Add(t.interval)) 51 } 52 53 // Trap quickly checks if the interval has passed since the last task run, and if 54 // it has, it runs the task. 55 func (t *IntervalTrap) Trap() { 56 t.RLock() 57 ready := t.ready() 58 t.RUnlock() 59 if !ready { 60 return 61 } 62 63 t.Lock() 64 defer t.Unlock() 65 if !t.ready() { 66 return 67 } 68 t.task.Run() 69 t.prev = t.clk.Now() 70 }