wait

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Mar 5, 2022 License: BSD-3-Clause Imports: 6 Imported by: 4

README

Tideland Go Wait

GitHub release GitHub license Go Module GoDoc Workflow Go Report Card

Description

Tideland Go Wait provides provides a flexible and controlled waiting for wanted conditions by polling. The function for testing has to be defined, different tickers for the polling can be generated for

  • simple constant intervals,
  • a maximum number of constant intervals,
  • a constant number of intervals with a deadline,
  • a onstant number of intervals with a timeout, and
  • jittering intervals.

Own tickers, e.g. with changing intervals, can be implemented too.

Another component of the package is the throttle, others would call it limiter. It allows the limited processing of events per second. Events are closures or functions with a defined signature. Depending on the burst size of the throttle multiple events can be processed with one call.

I hope you like it. ;)

Examples

Polling

A simple check for an existing file by polling every second for maximal 30 seconds.

// Tick every second for maximal 30 seconds.
ticker := wait.MakeExpiringIntervalTicker(time.Second, 30*time.Second),

// Check for existence of a file.
contition := func() (bool, error) {
    _, err := os.Stat("myfile.txt")
    if err != nil {
        if os.IsNotExist(err) {
            return false, nil
        }
        return false, err
    }
    // Found file.
    return true, nil
}

// And now poll.
wait.Poll(ctx, ticker, condition)
Throttling

A throttled wrapper of a http.Handler.

type ThrottledHandler struct {
    throttle *wait.Throttle
    handler  http.Handler
}

func NewThrottledHandler(limit wait.Limit, handler http.Handler) http.Handler {
    return &ThrottledHandler{
        throttle: wait.NewThrottle(limit, 1),
        handler:  handler,
    }
}

func (h *ThrottledHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    evt := func() error {
        h.ServeHTTP(w, r)
        return nil
    }
    h.throttle.Process(context.Background(), evt)
}

Contributors

Documentation

Overview

Package wait provides a generic waiting for conditions by polling, some standard tickers for the polling are already pre-defined.

Additionally the package provide a throttle for the limited processing of events per second.

Index

Constants

View Source
const (
	InfiniteLimit    = math.MaxFloat64
	InfiniteDuration = time.Duration(math.MaxInt64)
)

Variables

This section is empty.

Functions

func Poll

func Poll(ctx context.Context, ticker TickerFunc, condition ConditionFunc) error

Poll provides different ways to wait for conditions by polling. The conditions are checked by user defined functions with the signature

func() (ok bool, err error)

Here the bool return value signals if the condition is fulfilled, e.g. a file you're waiting for has been written into the according directory.

This signal for check a condition is returned by a ticker with the signature

func(ctx context.Context) <-chan struct{}

The context is for signalling the ticker to end working, the channel for the signals. Pre-defined tickers support

- simple constant intervals, - a maximum number of constant intervals, - a constant number of intervals with a deadline, - a constant number of intervals with a timeout, and - jittering intervals.

The behaviour of changing intervals can be user-defined by functions with the signature

func(in time.Duration) (out time.Duration, ok bool)

Here the argument is the current interval, return values are the wanted interval and if the polling shall continue. For the predefined tickers according convenience functions named With...() exist.

Example (waiting for a file to exist):

// Tick every second for maximal 30 seconds.
ticker := wait.MakeExpiringIntervalTicker(time.Second, 30*time.Second),

// Check for existence of a file.
condition := func() (bool, error) {
    _, err := os.Stat("myfile.txt")
    if err != nil {
        if os.IsNotExist(err) {
            return false, nil
        }
        return false, err
    }
    // Found file.
    return true, nil
}

// And now poll.
wait.Poll(ctx, ticker, condition)

From outside the polling can be stopped by cancelling the context.

func WithDeadline

func WithDeadline(
	ctx context.Context,
	interval time.Duration,
	deadline time.Time,
	condition ConditionFunc,
) error

WithDeadline is convenience for Poll() with MakeDeadlinedIntervalTicker().

func WithInterval

func WithInterval(
	ctx context.Context,
	interval time.Duration,
	condition ConditionFunc,
) error

WithInterval is convenience for Poll() with MakeIntervalTicker().

func WithJitter

func WithJitter(
	ctx context.Context,
	interval time.Duration,
	factor float64,
	timeout time.Duration,
	condition ConditionFunc,
) error

WithJitter is convenience for Poll() with MakeJitteringTicker().

func WithMaxIntervals

func WithMaxIntervals(
	ctx context.Context,
	interval time.Duration,
	max int,
	condition ConditionFunc,
) error

WithMaxIntervals is convenience for Poll() with MakeMaxIntervalsTicker().

func WithTimeout

func WithTimeout(
	ctx context.Context,
	interval, timeout time.Duration,
	condition ConditionFunc,
) error

WithTimeout is convenience for Poll() with MakeExpiringIntervalTicker().

Types

type ConditionFunc

type ConditionFunc func() (bool, error)

ConditionFunc has to be implemented for checking the wanted condition. A positive condition will return true and nil, a negative false and nil. In case of failure during the check false and the error have to be returned. The function will be used by the poll functions.

type Event added in v0.2.0

type Event func() error

Event wraps the event to be processed inside a function executed by a throttle.

type Limit added in v0.2.0

type Limit float64

Limit defines the number of allowed job starts per second by the throttle.

type Throttle added in v0.2.0

type Throttle struct {
	// contains filtered or unexported fields
}

Throttle controls the maximum number of events processed seconds per second. Here it internally uses a token bucket like described at https://en.wikipedia.org/wiki/Token_bucket. A throttle is created with the limit of allowed events per second and an additional burst size. A higher burst size allows to process more than event with the Process() method in one call.

func NewThrottle added in v0.2.0

func NewThrottle(limit Limit, burst int) *Throttle

NewThrottle creates a new throttle with a limit of allowed events to process per second and a burst size for a possible number of events per call.

func (*Throttle) Burst added in v0.2.0

func (t *Throttle) Burst() int

Burst returns the current burst of the throttle.

func (*Throttle) Limit added in v0.2.0

func (t *Throttle) Limit() Limit

Limit returns the current limit of the throttle.

func (*Throttle) Process added in v0.2.0

func (t *Throttle) Process(ctx context.Context, events ...Event) error

Process executes one or more events in a given context. If the limit is not infinite and the number of events is higher than the burst size or if the number of events is too high for the maximum duration, then the call will be declined. Also waiting may be too long if the context timeout is reached earlier which leads to an error.

type TickChangerFunc

type TickChangerFunc func(in time.Duration) (out time.Duration, ok bool)

TickChangerFunc allows to work with changing intervals. The current one is the argument, the next has to be returned. In case the bool return value is false the ticker will stop.

type TickerFunc

type TickerFunc func(ctx context.Context) <-chan struct{}

TickerFunc defines a function sending signals for each condition check when polling. The ticker can be canceled via the given context. Closing the returned signal channel means that the ticker ended. Sending ticks should be able to handle not received ones in case the condition check of the poller is working.

func MakeDeadlinedIntervalTicker

func MakeDeadlinedIntervalTicker(interval time.Duration, deadline time.Time) TickerFunc

MakeDeadlinedIntervalTicker returns a ticker signalling in intervals and stopping after a deadline.

func MakeExpiringIntervalTicker

func MakeExpiringIntervalTicker(interval, timeout time.Duration) TickerFunc

MakeExpiringIntervalTicker returns a ticker signalling in intervals and stopping after a timeout.

func MakeGenericIntervalTicker

func MakeGenericIntervalTicker(changer TickChangerFunc) TickerFunc

MakeGenericIntervalTicker is a factory for tickers based on time intervals. The given changer is responsible for the intervals and if the ticker shall signal a stopping. The changer is called initially with a duration of zero to allow the changer stopping the ticker even before a first tick.

func MakeIntervalTicker

func MakeIntervalTicker(interval time.Duration) TickerFunc

MakeIntervalTicker returns a ticker signalling in intervals.

func MakeJitteringTicker

func MakeJitteringTicker(interval time.Duration, factor float64, timeout time.Duration) TickerFunc

MakeJitteringTicker returns a ticker signalling in jittering intervals. This avoids converging on periadoc behavior during condition check. The returned intervals jitter between the given interval and interval + factor * interval. The ticker stops after reaching timeout.

func MakeMaxIntervalsTicker

func MakeMaxIntervalsTicker(interval time.Duration, max int) TickerFunc

MakeMaxIntervalsTicker returns a ticker signalling in intervals. It stops after a maximum number of signals.

Jump to

Keyboard shortcuts

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