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  }