github.com/trezor/blockbook@v0.4.1-0.20240328132726-e9a08582ee2c/common/utils.go (about)

     1  package common
     2  
     3  import (
     4  	"time"
     5  )
     6  
     7  // TickAndDebounce calls function f on trigger channel or with tickTime period (whatever is sooner) with debounce
     8  func TickAndDebounce(tickTime time.Duration, debounceTime time.Duration, trigger chan struct{}, f func()) {
     9  	timer := time.NewTimer(tickTime)
    10  	var firstDebounce time.Time
    11  Loop:
    12  	for {
    13  		select {
    14  		case _, ok := <-trigger:
    15  			if !timer.Stop() {
    16  				<-timer.C
    17  			}
    18  			// exit loop on closed input channel
    19  			if !ok {
    20  				break Loop
    21  			}
    22  			if firstDebounce.IsZero() {
    23  				firstDebounce = time.Now()
    24  			}
    25  			// debounce for up to debounceTime period
    26  			// afterwards execute immediately
    27  			if firstDebounce.Add(debounceTime).After(time.Now()) {
    28  				timer.Reset(debounceTime)
    29  			} else {
    30  				timer.Reset(0)
    31  			}
    32  		case <-timer.C:
    33  			// do the action, if not in shutdown, then start the loop again
    34  			if !IsInShutdown() {
    35  				f()
    36  			}
    37  			timer.Reset(tickTime)
    38  			firstDebounce = time.Time{}
    39  		}
    40  	}
    41  }