github.com/sentienttechnologies/studio-go-runner@v0.0.0-20201118202441-6d21f2ced8ee/internal/runner/backoffs.go (about) 1 package runner 2 3 // This contains the implementation of a TTL cache that stores the timestamp of the intended absolute time 4 // of expiry as the value. 5 6 import ( 7 "sync" 8 "time" 9 10 ttlCache "github.com/karlmutch/go-cache" 11 ) 12 13 // Backoffs uses a cache with TTL on the cache items to maintain 14 // a set of blocking directive for resources, where the cache expiry time 15 // is the applicable time for the blocker 16 type Backoffs struct { 17 backoffs *ttlCache.Cache 18 } 19 20 var ( 21 singleGet sync.Mutex 22 backoffOnce sync.Once 23 backoffs *Backoffs 24 ) 25 26 // GetBackoffs retrieves a reference to a singleton of the Backoffs structure 27 func GetBackoffs() (b *Backoffs) { 28 singleGet.Lock() 29 defer singleGet.Unlock() 30 31 backoffOnce.Do( 32 func() { 33 backoffs = &Backoffs{backoffs: ttlCache.New(10*time.Second, time.Minute)} 34 }) 35 return backoffs 36 } 37 38 // Set will add a blocker for a named resource, but only if there is no blocking timer 39 // already in effect for the resource 40 func (b *Backoffs) Set(k string, d time.Duration) { 41 // Use the existing timer if there is one and find out which one is the 42 // longest and use that 43 if expires, isPresent := b.Get(k); isPresent && time.Now().Add(d).Before(expires) { 44 return 45 } 46 // is the longest time from now and use that 47 b.backoffs.Set(k, time.Now().Add(d), d) 48 } 49 50 // Get retrieves a blockers current expiry time if one exists for the named 51 // resource 52 func (b *Backoffs) Get(k string) (expires time.Time, isPresent bool) { 53 result, present := b.backoffs.Get(k) 54 if !present { 55 return expires, present 56 } 57 return result.(time.Time), present 58 }