package flaky
Import Path
go.pact.im/x/flaky (on go.dev)
Dependency Relation
imports 7 packages, and imported by 0 packages
Involved Source Files
backoff.go
deadline.go
debounce.go
Package flaky implements mechanisms for executing flaky operations.
jitter.go
once.go
permanent.go
retry.go
schedule.go
watchdog.go
Code Examples
package main
import (
"context"
"fmt"
"go.pact.im/x/flaky"
"net/http"
"net/http/httputil"
"time"
)
func main() {
ctx := context.Background()
executor := flaky.Retry(flaky.Limit(5, flaky.Exp2(time.Second)))
req, _ := http.NewRequest(http.MethodGet, "https://example.com", nil)
client := http.DefaultClient
var dump []byte
var err error
err = executor.Execute(ctx, func(ctx context.Context) error {
ctx, cancel := context.WithTimeout(ctx, time.Second)
defer cancel()
var resp *http.Response
resp, err = client.Do(req.WithContext(ctx))
if err != nil {
return err
}
dump, err = httputil.DumpResponse(resp, false)
return err
})
if err != nil {
panic(err)
}
fmt.Println(string(dump))
}
Package-Level Type Names (total 20, in which 13 are exported)
Backoff is a function that, given the current count of retries, returns
backoff delay before the next attempt, or false if an executor should stop
with the last error.
Backoff implements the BackoffProvider interface.
Backoff : BackoffProvider
func Constant(xs ...time.Duration) Backoff
func Exp2(unit time.Duration) Backoff
func Limit(limit uint, backoff Backoff) Backoff
func Backoff.Backoff() Backoff
func BackoffProvider.Backoff() Backoff
func Jitter.Backoff(b Backoff, v JitterInterval) Backoff
func Limit(limit uint, backoff Backoff) Backoff
func Jitter.Backoff(b Backoff, v JitterInterval) Backoff
BackoffProvider provides a potentially stateful backoff function for
executing an operation.
( BackoffProvider) Backoff() Backoff
Backoff
func Retry(b BackoffProvider) *RetryExecutor
DebounceExecutor is an executor that debounces an operation. That is, it
performs an operation once it stops being called for the specified debounce
duration.
Keep in mind that using DebounceExecutor introduces latency to the operation
for at least the specified debounce duration. In most cases it should be used
when the operation is expensive to execute or under high event rate or load.
As a side effect, DebounceExecutor guarantees that at most one operation is
executing at a time.
c *clock.Clock
debounceState debounceState
debounceState.exec chan struct{}
debounceState.lock chan struct{}
debounceState.next chan struct{}
debounceState.steal chan struct{}
once sync.Once
timer clock.Timer
w time.Duration
Execute calls the function f if and only if Execute is not called again
during the debounce interval. Context expiration cancels an operation. It
returns ErrDebounced error if the given operation f was superseded by another
Execute call. If Execute is called concurrently, the last invocation wins.
When another operation is already executing, it returns ErrDebounced.
Callers should handle ErrDebounced error to avoid breaking assumptions when
running under another DebounceExecutor.
As a side effect, it guarantees that at most one f is executing at a time.
That is, it is safe to avoid locking if the state is mutated exclusively
under the DebounceExecutor.
WithClock returns a copy of the executor that uses the given clock.
WithWait returns a copy of the executor that uses the given wait duration.
It shares the underlying state and can be used to debounce operation with
non-default wait duration.
clone returns a copy of the executor.
init initializes the internal debouncer state.
*DebounceExecutor : Executor
func Debounce(t time.Duration) *DebounceExecutor
func (*DebounceExecutor).WithClock(c *clock.Clock) *DebounceExecutor
func (*DebounceExecutor).WithWait(t time.Duration) *DebounceExecutor
func (*DebounceExecutor).clone() *DebounceExecutor
Executor is an executor for flaky operations.
Execute executes a flaky operation f using the execution policy.
*DebounceExecutor
*RetryExecutor
*ScheduleExecutor
*WatchdogExecutor
*onceExecutor
*untilPermanentExecutor
func Once() Executor
func UntilPermanent() Executor
func Watchdog(e Executor, s Schedule) *WatchdogExecutor
func WithSchedule(e Executor, s Schedule) *ScheduleExecutor
Jitter is a function that, given a closed interval v, returns a random
value on that interval.
Backoff returns a new Backoff with jitter for the given interval.
Jitter implements the JitterProvider interface.
Schedule returns a new Schedule with jitter for the given interval.
Jitter : JitterProvider
func RandomJitter(f func(n int64) int64) Jitter
func Jitter.Jitter() Jitter
func JitterProvider.Jitter() Jitter
JitterInterval describes a closed jitter interval. The final jitter value
for random number N is computed as N - L/Q where N ∈ (0; L] for L > 0 and
N ∈ [L; 0) for L < 0. If L = 0 then the final jitter value is always zero.
L is the length of the jitter interval.
Q specifies 1/q quotient of the interval length to subtract from the
random number.
func Jitter.Backoff(b Backoff, v JitterInterval) Backoff
func Jitter.Schedule(s Schedule, v JitterInterval) Schedule
func randomJitter(v JitterInterval, f func(n int64) int64) time.Duration
Op is an operation that is likely to fail.
func (*DebounceExecutor).Execute(ctx context.Context, f Op) error
func Executor.Execute(ctx context.Context, f Op) error
func (*RetryExecutor).Execute(ctx context.Context, f Op) error
func (*ScheduleExecutor).Execute(ctx context.Context, f Op) error
func (*WatchdogExecutor).Execute(ctx context.Context, f Op) error
PermanentError indicates that a permanent error has been encountered during a
retry attempt.
err error
unwrap bool
Error implements the error interface.
Internal returns whether the permanent error is internal. It is guaranteed
that Executor’s Execute method does not return internal errors.
Unwrap unwraps the underlying error.
*PermanentError : error
func AsPermanentError(err error) (*PermanentError, bool)
func Internal(err error) *PermanentError
func Permanent(err error) *PermanentError
RetryExecutor is an executor that retries executing an operation using the
provided backoff. It allows executing operations that may succeed after a few
attempts.
backoff BackoffProvider
clock *clock.Clock
Execute implements the Executor interface.
WithClock returns a copy of the executor that uses the given clock.
*RetryExecutor : Executor
func Retry(b BackoffProvider) *RetryExecutor
func (*RetryExecutor).WithClock(c *clock.Clock) *RetryExecutor
Schedule defines the schedule to use for WithSchedule.
Next returns the next schedule time relative to now. If there is no
schedule past the given time, it returns zero time or a value before
now.
github.com/robfig/cron/v3.ConstantDelaySchedule
github.com/robfig/cron/v3.Schedule (interface)
*github.com/robfig/cron/v3.SpecSchedule
*jitterSchedule
*midnightSchedule
sleepSchedule
*untilSchedule
Schedule : github.com/robfig/cron/v3.Schedule
func Midnight(d time.Duration, loc *time.Location) Schedule
func Sleep(d time.Duration) Schedule
func Until(s Schedule, t time.Time) Schedule
func Jitter.Schedule(s Schedule, v JitterInterval) Schedule
func Until(s Schedule, t time.Time) Schedule
func Watchdog(e Executor, s Schedule) *WatchdogExecutor
func WithSchedule(e Executor, s Schedule) *ScheduleExecutor
func Jitter.Schedule(s Schedule, v JitterInterval) Schedule
ScheduleExecutor is an executor that restricts operation execution to the
specified schedule. It allows executing operations that may only succeed
at the given time.
clock *clock.Clock
exec Executor
sched Schedule
Execute implements the Executor interface.
WithClock returns a copy of the executor that uses the given clock.
*ScheduleExecutor : Executor
func WithSchedule(e Executor, s Schedule) *ScheduleExecutor
func (*ScheduleExecutor).WithClock(c *clock.Clock) *ScheduleExecutor
WatchdogExecutor is an executor that keeps executing an operation on schedule
using the underlying executor until an error is returned or context expires.
It allow monitoring a resource that should not fail.
exec *ScheduleExecutor
Execute implements the Executor interface.
WithClock returns a copy of the executor that uses the given clock.
*WatchdogExecutor : Executor
func Watchdog(e Executor, s Schedule) *WatchdogExecutor
func (*WatchdogExecutor).WithClock(c *clock.Clock) *WatchdogExecutor
Package-Level Functions (total 20, in which 17 are exported)
AsPermanentError attempts to extract PermanentError from err’s error chain.
Constant returns a constant backoff that uses nth duration for the arguments.
It returns the last element if the attempt count is greater than the number
of arguments. Passing no arguments is equivalent to no backoff.
Debounce returns a new DebounceExecutor instance for the given wait duration.
Exp2 returns an exponential backoff that returns base-2 exponential of
failed attempts count times the given duration unit.
Note that the backoff stops after wait duration reaches max positive value of
time.Duration or once n is equal to math.MaxUint.
Internal marks an error as a permanent internal error. Executors unwrap
internal errors prior to returning them.
IsPermanentError returns whether err’s error chain contains PermanentError.
Limit limits the number of retries for the given backoff. That is, it stops
the backoff once retries counter reaches the given limit. Passing a limit of
zero retries is equivalent to no backoff.
Midnight returns a repeated Schedule for the duration d since midnight in the
given in location. If the location is nil, it defaults to UTC.
Passing a non-positive duration is equivalent to not using a schedule.
Once returns a new executor that does not retry operations. That is,
it executes the operation exactly once and returns the result.
Permanent marks an error as permanent. That is, returning permanent error
from retry attempt would stop the retry process.
RandomJitter returns a Jitter function for function f that defaults to
math/rand.Int63n if it is nil.
Retry returns a new executor that uses the backoff provider to retry
operation execution.
It attempts to execute f until a backoff function returns false, an attempt
returns permanent error or a context expires. On failure it returns the last
error encountered.
It requests a new backoff function from provider for each Execute invocation.
Sleep returns a Schedule that delays execution for a fixed interval d.
Passing a non-positive duration is equivalent to not using a schedule.
Until returns a schedule that stops at the given time. It allows defining the
schedule for operations that should fail after the given time.
UntilPermanent returns a new executor that retries operations until either a
permanent error or context expiration.
Watchdog executes an operation on the given schedule using the executor until
an error is returned or the context expires. It allow monitoring a resource
that should not fail.
Note that it returns a nil error iff context expires. Otherwise an error from
the executor indicates an operation failure.
This design allows interrupting execution using the context but the tradeoff
is that an error is discarded. That is mostly noticeable when the executor
retries operations and a context expires after a failure. In that case the
error would not be propagated to the watchdog user.
Unlike a simple loop that executes the given executor and waits a certain
amount of time, watchdog enforces the use of a configurable schedule.
WithSchedule restricts the executor to wait for the given scheduled time
before executing an operation.
Package-Level Variables (total 3, all are exported)
ErrDebounced is an error that DebounceExecutor returns when an Execute call
is superseded by another operation.
ErrNoNextSchedule is an error that is returned by ScheduleExecutor
if there is no next scheduled time or it is before current time.
ErrScheduleDeadline is an error that is returned by ScheduleExecutor
if scheduled time exceeds the context deadline.
The pages are generated with Golds v0.4.9. (GOOS=linux GOARCH=amd64)