74 lines
1.2 KiB
Go
74 lines
1.2 KiB
Go
|
package queue
|
||
|
|
||
|
import (
|
||
|
"sync"
|
||
|
"time"
|
||
|
|
||
|
"github.com/pkg/errors"
|
||
|
)
|
||
|
|
||
|
type DebouncerMap struct {
|
||
|
debouncers sync.Map
|
||
|
}
|
||
|
|
||
|
func NewDebouncerMap() *DebouncerMap {
|
||
|
return &DebouncerMap{
|
||
|
debouncers: sync.Map{},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (m *DebouncerMap) Do(key string, after time.Duration, fn func()) {
|
||
|
newDebouncer := NewDebouncer(after)
|
||
|
rawDebouncer, loaded := m.debouncers.LoadOrStore(key, newDebouncer)
|
||
|
|
||
|
debouncer, ok := rawDebouncer.(*Debouncer)
|
||
|
if !ok {
|
||
|
panic(errors.Errorf("unexpected debouncer value, expected '%T', got '%T'", newDebouncer, rawDebouncer))
|
||
|
}
|
||
|
|
||
|
if loaded {
|
||
|
debouncer.Update(after)
|
||
|
}
|
||
|
|
||
|
debouncer.Do(fn)
|
||
|
}
|
||
|
|
||
|
func NewDebouncer(after time.Duration) *Debouncer {
|
||
|
return &Debouncer{after: after}
|
||
|
}
|
||
|
|
||
|
type Debouncer struct {
|
||
|
mu sync.Mutex
|
||
|
after time.Duration
|
||
|
timer *time.Timer
|
||
|
fn func()
|
||
|
}
|
||
|
|
||
|
func (d *Debouncer) Do(fn func()) {
|
||
|
d.mu.Lock()
|
||
|
defer d.mu.Unlock()
|
||
|
|
||
|
if d.timer != nil {
|
||
|
d.timer.Stop()
|
||
|
}
|
||
|
|
||
|
d.fn = fn
|
||
|
d.timer = time.AfterFunc(d.after, d.fn)
|
||
|
}
|
||
|
|
||
|
func (d *Debouncer) Update(after time.Duration) {
|
||
|
d.mu.Lock()
|
||
|
defer d.mu.Unlock()
|
||
|
|
||
|
if after == d.after {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if d.timer != nil {
|
||
|
d.timer.Stop()
|
||
|
}
|
||
|
|
||
|
d.after = after
|
||
|
d.timer = time.AfterFunc(d.after, d.fn)
|
||
|
}
|