github.com/prysmaticlabs/prysm@v1.4.4/shared/asyncutil/debounce.go (about) 1 package asyncutil 2 3 import ( 4 "context" 5 "time" 6 ) 7 8 // Debounce events fired over a channel by a specified duration, ensuring no events 9 // are handled until a certain interval of time has passed. 10 func Debounce(ctx context.Context, interval time.Duration, eventsChan <-chan interface{}, handler func(interface{})) { 11 var timer *time.Timer 12 defer func() { 13 if timer != nil { 14 timer.Stop() 15 } 16 }() 17 for { 18 select { 19 // Wait until an event is triggered. 20 case event := <-eventsChan: 21 timer = time.NewTimer(interval) 22 loop: 23 for { 24 // If an event is received, wait the specified interval before calling the handler. 25 // If another event is received before the interval has passed, store 26 // it and reset the timer. 27 select { 28 case event = <-eventsChan: 29 // Reset timer. 30 timer.Stop() 31 timer = time.NewTimer(interval) 32 case <-timer.C: 33 // Stop the current timer, handle the request, and wait for more events. 34 timer.Stop() 35 handler(event) 36 break loop 37 case <-ctx.Done(): 38 return 39 } 40 } 41 case <-ctx.Done(): 42 return 43 } 44 } 45 }