github.com/iron-io/functions@v0.0.0-20180820112432-d59d7d1c40b2/api/server/singleflight.go (about)

     1  package server
     2  
     3  // Imported from https://github.com/golang/groupcache/blob/master/singleflight/singleflight.go
     4  
     5  import (
     6  	"sync"
     7  
     8  	"github.com/iron-io/functions/api/models"
     9  )
    10  
    11  // call is an in-flight or completed do call
    12  type call struct {
    13  	wg  sync.WaitGroup
    14  	val interface{}
    15  	err error
    16  }
    17  
    18  type singleflight struct {
    19  	mu sync.Mutex                   // protects m
    20  	m  map[models.RouteFilter]*call // lazily initialized
    21  }
    22  
    23  // do executes and returns the results of the given function, making
    24  // sure that only one execution is in-flight for a given key at a
    25  // time. If a duplicate comes in, the duplicate caller waits for the
    26  // original to complete and receives the same results.
    27  func (g *singleflight) do(key models.RouteFilter, fn func() (interface{}, error)) (interface{}, error) {
    28  	g.mu.Lock()
    29  	if g.m == nil {
    30  		g.m = make(map[models.RouteFilter]*call)
    31  	}
    32  	if c, ok := g.m[key]; ok {
    33  		g.mu.Unlock()
    34  		c.wg.Wait()
    35  		return c.val, c.err
    36  	}
    37  	c := new(call)
    38  	c.wg.Add(1)
    39  	g.m[key] = c
    40  	g.mu.Unlock()
    41  
    42  	c.val, c.err = fn()
    43  	c.wg.Done()
    44  
    45  	g.mu.Lock()
    46  	delete(g.m, key)
    47  	g.mu.Unlock()
    48  
    49  	return c.val, c.err
    50  }