Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct { // Duration is the duration on which the interval "ticks" (if a jitter is // applied, this represents the upper bound of the range). Duration time.Duration // FirstDuration is an optional special duration to be used for the first // "tick" of the interval. This duration is not jittered. FirstDuration time.Duration // Jitter is an optional jitter to be applied to each step of the interval. // It is usually preferable to use a smaller jitter (e.g. NewSeventhJitter()) // for this parameter, since periodic operations are typically costly and the // effect of the jitter is cumulative. Jitter retryutils.Jitter // Clock is the clock to use to control the interval. Clock clockwork.Clock }
Config configures an interval. The only required parameter is the Duration field which *must* be a positive duration.
type Interval ¶
type Interval struct {
// contains filtered or unexported fields
}
Interval functions similarly to time.Ticker, with the added benefit of being able to specify a custom duration for the first "tick", and an optional per-tick jitter. When attempting to stagger periodic operations it is recommended to apply a large jitter to the first duration, and provide a small jitter for the per-tick jitter. This will ensure that operations started at similar times will have varying initial interval states, while minimizing the amount of extra work introduced by the per-tick jitter.
func New ¶
New creates a new interval instance. This function panics on non-positive interval durations (equivalent to time.NewTicker).
func (*Interval) FireNow ¶
func (i *Interval) FireNow()
FireNow forces the interval to fire immediately regardless of how much time is left on the current interval. This also effectively resets the interval.
type MultiInterval ¶
type MultiInterval[T comparable] struct { // contains filtered or unexported fields }
MultiInterval is equivalent to Interval except that it supports multiple intervals simultanesouly, distinguishing them by key. The only real benefit to using this type instead of using multiple Intervals is that it only allocates one timer and one background goroutine regardless of the number of intervals. There are very few cases where this distinction matters. An example of a place where this *does* matter is when you need multiple intervals *per* connected instance on an auth or proxy server. In such a case, allocating only one timer and one goroutine per connected instance can be a significant saving (see the lib/inventory for an example of this usecase).
Note that MultiInterval behaves differently than time.Ticker or Interval in that it may yield the same timestamp multiple times. It will only do this for *different* keys (i.e. K1 and K2 may both tick at T0) but it is still a potential source of bugs/confusion when transitioning to using this type from one of the single-interval alternatives.
func NewMulti ¶
func NewMulti[T comparable](intervals ...SubInterval[T]) *MultiInterval[T]
NewMulti creates a new multi-interval instance. This function panics on non-positive interval durations (equivalent to time.NewTicker) or if no sub-intervals are provided.
func (*MultiInterval[T]) FireNow ¶
func (i *MultiInterval[T]) FireNow(key T)
FireNow forces the sub-interval to fire immediately regardless of how much time is left on the current interval. This also effectively resets the sub-interval.
func (*MultiInterval[T]) Next ¶
func (i *MultiInterval[T]) Next() <-chan Tick[T]
Next is the channel over which interval ticks are delivered.
func (*MultiInterval[T]) Push ¶
func (i *MultiInterval[T]) Push(sub SubInterval[T])
Push adds a new sub-interval, potentially overwriting an existing sub-interval with the same key. This method panics on non-positive durations (equivalent to time.NewTicker).
func (*MultiInterval[T]) Reset ¶
func (i *MultiInterval[T]) Reset(key T)
Reset resets the interval without pausing it (i.e. it will now fire in jitter(duration) regardless of current timer progress).
func (*MultiInterval[T]) Stop ¶
func (i *MultiInterval[T]) Stop()
Stop permanently stops the interval. Note that stopping an interval does not close its output channel. This is done in order to prevent concurrent stops from generating erroneous "ticks" and is consistent with the behavior of time.Ticker.
type SubInterval ¶
type SubInterval[T any] struct { // Key is the key that will uniquely identify this sub-interval. Key T // Duration is the duration on which the interval "ticks" (if a jitter is // applied, this represents the upper bound of the range). Duration time.Duration // VariableDuration, if supplied, replaces the 'Duration' paramater with a // variable duration generator. Variable durations are used to calculate // some heartbeat intervals so that the time between heartbeats scales up // as concurrent load increases. VariableDuration *VariableDuration // FirstDuration is an optional special duration to be used for the first // "tick" of the interval. This duration is not jittered. FirstDuration time.Duration // Jitter is an optional jitter to be applied to each step of the interval. // It is usually preferable to use a smaller jitter (e.g. NewSeventhJitter()) // for this parameter, since periodic operations are typically costly and the // effect of the jitter is cumulative. Jitter retryutils.Jitter }
SubInterval configures an interval. The only required parameters are the Duration field which *must* be a positive duration, and the Key field which can be any comparable value.
type Tick ¶
Tick represents a firing of the interval. The Key field denominates the sub-interval that fired, and the Time field represents the time at which the firing occurred.
type VariableDuration ¶
type VariableDuration struct {
// contains filtered or unexported fields
}
VariableDuration is a duration generator that varies its output based on a counter. This type is used to implement intervals that should become less frequent as load increases, namely heartbeats. Typically, heartbeats should happen very frequently to ensure that changes become visible quickly. This becomes problematic at large scales, where the resource consumption of heartbeats becomes onerous. This type attempts to provide a reasonable compromise between frequency and scalabiltiy by slowly scaling up the duration as the associated counter is increased. Scaling is determined by the square root of the quotient of Counter / Step. Min and max duration should be selected based on the needs of the resource in question. How quickly/slowly the duration scales is then controlled by picking a step size, with larger step sizes resulting in slower scaling.
func NewVariableDuration ¶
func NewVariableDuration(cfg VariableDurationConfig) *VariableDuration
NewVariableDuration sets up a new variable duration instance.
func (*VariableDuration) Count ¶
func (c *VariableDuration) Count() int64
Count loads the current counter value.
func (*VariableDuration) Duration ¶
func (v *VariableDuration) Duration() time.Duration
Duration calculates the current duration value.
type VariableDurationConfig ¶
type VariableDurationConfig struct { // MinDuration is the minimum duration value to be emitted when the counter // is at or near zero, and the base point of the scaling curve. MinDuration time.Duration // MaxDuration is the upper limit of the output duration. Once hit, further increases // to the counter have no effect. MaxDuration time.Duration // Step is the step size used to calculate the scaling curve. A larger step size results // in a slower/shallower increase in the output duration. Step int64 }
VariableDurationConfig holds input parameters for a variable duration.