44 lines
949 B
Go
44 lines
949 B
Go
package handler
|
|
|
|
import "sync"
|
|
|
|
// singleflightGroup deduplicates concurrent calls keyed by string. If N
|
|
// goroutines call Do(key, fn) before the first one returns, fn runs once
|
|
// and all callers receive the same (val, err).
|
|
//
|
|
// Copy of internal/apps/singleflight.go (same pattern, no extra
|
|
// dependency). The convert package has its own copy too; if a third
|
|
// caller appears, lift to internal/sf/.
|
|
type singleflightGroup struct {
|
|
mu sync.Mutex
|
|
m map[string]*sfCall
|
|
}
|
|
|
|
type sfCall struct {
|
|
done chan struct{}
|
|
val any
|
|
err error
|
|
}
|
|
|
|
func (g *singleflightGroup) Do(key string, fn func() (any, error)) (any, error) {
|
|
g.mu.Lock()
|
|
if g.m == nil {
|
|
g.m = make(map[string]*sfCall)
|
|
}
|
|
if c, ok := g.m[key]; ok {
|
|
g.mu.Unlock()
|
|
<-c.done
|
|
return c.val, c.err
|
|
}
|
|
c := &sfCall{done: make(chan struct{})}
|
|
g.m[key] = c
|
|
g.mu.Unlock()
|
|
|
|
c.val, c.err = fn()
|
|
close(c.done)
|
|
|
|
g.mu.Lock()
|
|
delete(g.m, key)
|
|
g.mu.Unlock()
|
|
return c.val, c.err
|
|
}
|