interval

package
v0.0.0-...-5c79d48 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 15, 2024 License: AGPL-3.0 Imports: 7 Imported by: 0

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

func New(cfg Config) *Interval

New creates a new interval instance. This function panics on non-positive interval durations (equivalent to time.NewTicker).

func NewNoop

func NewNoop() *Interval

NewNoop creates a new interval that will never fire.

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.

func (*Interval) Next

func (i *Interval) Next() <-chan time.Time

Next is the channel over which the intervals are delivered.

func (*Interval) Reset

func (i *Interval) Reset()

Reset resets the interval without pausing it (i.e. it will now fire in jitter(duration) regardless of current timer progress).

func (*Interval) Stop

func (i *Interval) 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 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

type Tick[T any] struct {
	Key  T
	Time time.Time
}

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) Dec

func (v *VariableDuration) Dec()

Dec decrements the counter.

func (*VariableDuration) Duration

func (v *VariableDuration) Duration() time.Duration

Duration calculates the current duration value.

func (*VariableDuration) Inc

func (v *VariableDuration) Inc()

Inc increments the counter.

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL