converge/pkg/support/throttling/throttler.go

59 lines
1.6 KiB
Go

package throttling
import (
"time"
)
// Throttling notifications to prometheus and web clients
// TO be used in a single-threaded manner.
//
// NOTE: the null value of type T is considered as a not-set value.
//
// The best usage of Throttler is with a pointer type.
type Throttler[T comparable] struct {
minDelay time.Duration
// ucntion to call to implement the notification.
notifier func(t T)
lastReportedTime time.Time
pendingValue T
lastValue T
}
func NewThrottler[T comparable](notifier func(t T), minDelay time.Duration) Throttler[T] {
throttler := Throttler[T]{
minDelay: minDelay,
notifier: notifier,
lastReportedTime: time.Time{},
pendingValue: *new(T),
lastValue: *new(T),
}
return throttler
}
// Notify there is a new value. Performs notification if it was long enough ago
// for the last notification to be sent. If not, it is stored as a pending event to
// be sent later. New events that come in before a notification is sent override the
// pending event.
func (throttler *Throttler[T]) Notify(value T) {
if throttler.lastValue == value {
// duplicate events are not sent.
return
}
if clock.time().Sub(throttler.lastReportedTime) >= throttler.minDelay {
throttler.notifier(value)
throttler.lastReportedTime = clock.time()
throttler.lastValue = value
throttler.pendingValue = *new(T)
return
}
throttler.pendingValue = value
}
// To be called periodically. It sends out any pending events if the time the last
// notification was sent is long enough ago.
func (throttler *Throttler[T]) Ping() {
if throttler.pendingValue != *new(T) {
throttler.Notify(throttler.pendingValue)
}
}