Skip to content

Instantly share code, notes, and snippets.

@IhsanMujdeci
Last active November 10, 2021 23:48
Show Gist options
  • Save IhsanMujdeci/7b7715127120b86300235580921be432 to your computer and use it in GitHub Desktop.
Save IhsanMujdeci/7b7715127120b86300235580921be432 to your computer and use it in GitHub Desktop.
type Accumulation struct {
messages []interface{}
t *time.Timer
}
// Accumulator debounces and accumulates values then sends them to function passed in the Add method
// Implements a concurrency safe map that can accumulate messages based on a key
type Accumulator struct {
acc map[string]*Accumulation
mu sync.Mutex
delay time.Duration
}
func MakeAccumulator(delay time.Duration) *Accumulator {
return &Accumulator{
acc: make(map[string]*Accumulation),
delay: delay,
}
}
// Add creates a key in the map if it doesn't exist then assigns a callback value,
// then a waitTimer is called with that registeredCallback
// Subsequent calls to initialised entry in map doesn't re-register a callback function
// only the first one is used
func (d *Accumulator) Add(key string, message interface{}, callback func([]interface{})) {
d.mu.Lock()
if acc, exists := d.acc[key]; !exists {
t := time.NewTimer(d.delay)
d.acc[key] = &Accumulation{
messages: []interface{}{message},
t: t,
}
go d.waitTimer(key, callback, t)
} else {
acc.messages = append(acc.messages, message)
acc.t.Reset(d.delay)
}
d.mu.Unlock()
}
func (d *Accumulator) waitTimer(key string, callback func([]interface{}), t *time.Timer) {
<-t.C
d.mu.Lock()
acc, exists := d.acc[key]
if !exists {
return
}
callback(acc.messages)
d.acc[key] = nil
d.mu.Unlock()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment