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 }