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  }