Documentation
¶
Overview ¶
Package retry executes explicitly classified operations under bounded retry policies. It never decides whether an operation is safe to repeat.
Index ¶
- Constants
- Variables
- func Permanent(err error) error
- func Retryable(err error) error
- type Attempt
- type Backoff
- func Constant(delay time.Duration) Backoff
- func DecorrelatedJitter(base time.Duration) Backoff
- func EqualJitter(backoff Backoff) Backoff
- func Exponential(initial time.Duration, multiplier uint64) Backoff
- func ExponentialJitter(initial time.Duration, multiplier uint64, factor float64) Backoff
- func Fibonacci(unit time.Duration) Backoff
- func FullJitter(backoff Backoff) Backoff
- func Linear(initial, increment time.Duration) Backoff
- func Polynomial(base, coefficient time.Duration, power uint) Backoff
- type BudgetError
- type BudgetKind
- type CanceledError
- type Classification
- type Classifier
- type ClassifyFunc
- type Clock
- type Config
- type DelayHint
- type ExhaustedError
- type Observation
- type ObserveFunc
- type Observer
- type PermanentError
- type Policy
- type Random
- type Reason
- type Result
- type RetryableError
- type SeededRandom
- type Sleeper
- type SystemClock
- type SystemSleeper
- type TimeoutClock
Examples ¶
Constants ¶
const MaxHistoryEntries = 1024
MaxHistoryEntries is the largest failure history retained by a policy.
Variables ¶
var ErrInvalidPolicy = errors.New("invalid retry policy")
ErrInvalidPolicy identifies contradictory, implicit, or unbounded policies.
Functions ¶
Types ¶
type Attempt ¶
type Attempt struct {
Attempt uint
Elapsed time.Duration
Delay time.Duration
Classification Classification
Err error
}
Attempt records bounded failure metadata. It never retains operation values.
type Backoff ¶
Backoff computes the delay before retry attempt. Attempt starts at one for the first retry. Previous is the previously selected delay and is used only by state-dependent strategies such as decorrelated jitter.
func DecorrelatedJitter ¶
DecorrelatedJitter chooses uniformly between base and three times the previous delay. The first retry uses base as its previous delay.
func EqualJitter ¶
EqualJitter retains half of the wrapped delay and uniformly jitters the remainder.
func Exponential ¶
Exponential returns initial*multiplier^(attempt-1) with saturation.
func ExponentialJitter ¶
ExponentialJitter applies centered proportional jitter to exponential backoff. Factor is clamped to [0, 1].
func Fibonacci ¶
Fibonacci returns unit multiplied by the attempt-th Fibonacci number, where the first two retry delays both equal unit.
func FullJitter ¶
FullJitter chooses uniformly between zero and the wrapped delay.
Example ¶
package main
import (
"fmt"
"time"
retry "github.com/faustbrian/go-retry"
)
func main() {
strategy := retry.FullJitter(retry.Exponential(100*time.Millisecond, 2))
delay := strategy.Delay(1, 0, retry.NewRandom(1, 2))
fmt.Println(delay >= 0 && delay <= 100*time.Millisecond)
}
Output: true
type BudgetError ¶
type BudgetError struct {
Kind BudgetKind
// contains filtered or unexported fields
}
BudgetError reports exhaustion of an elapsed, sleep, attempt, or shared-work budget.
func (*BudgetError) Error ¶
func (err *BudgetError) Error() string
func (*BudgetError) Result ¶
func (err *BudgetError) Result() Result
Result returns a defensive copy of terminal metadata.
func (*BudgetError) Unwrap ¶
func (err *BudgetError) Unwrap() error
type BudgetKind ¶
type BudgetKind string
BudgetKind identifies the configured budget that stopped execution.
const ( // BudgetElapsed identifies the total elapsed-time budget. BudgetElapsed BudgetKind = "elapsed" // BudgetSleep identifies the accumulated-sleep budget. BudgetSleep BudgetKind = "sleep" // BudgetAttempt identifies a per-attempt timeout. BudgetAttempt BudgetKind = "attempt" // BudgetWork identifies denial by the shared retry-plus-hedge work budget. BudgetWork BudgetKind = "work" )
type CanceledError ¶
type CanceledError struct {
// contains filtered or unexported fields
}
CanceledError reports cancellation by the caller or its deadline.
func (*CanceledError) Error ¶
func (err *CanceledError) Error() string
func (*CanceledError) Result ¶
func (err *CanceledError) Result() Result
Result returns a defensive copy of terminal metadata.
func (*CanceledError) Unwrap ¶
func (err *CanceledError) Unwrap() error
type Classification ¶
type Classification uint8
Classification is an explicit decision about one operation failure.
const ( // ClassificationPermanent stops execution and preserves the operation error. ClassificationPermanent Classification = iota + 1 // ClassificationRetryable permits another bounded attempt. ClassificationRetryable )
type Classifier ¶
type Classifier interface {
Classify(context.Context, error) (Classification, error)
}
Classifier classifies an operation failure. Returning an error means the classifier itself failed and execution stops.
func RetryableClassifier ¶
func RetryableClassifier() Classifier
RetryableClassifier returns a classifier that retries RetryableError values and treats every other error as permanent.
type ClassifyFunc ¶
type ClassifyFunc func(context.Context, error) (Classification, error)
ClassifyFunc adapts a function to Classifier.
func (ClassifyFunc) Classify ¶
func (function ClassifyFunc) Classify(ctx context.Context, err error) (Classification, error)
Classify invokes the adapted function.
type Clock ¶
Clock supplies policy time. Implementations may additionally implement TimeoutClock to make per-attempt timeouts deterministic.
type Config ¶
type Config struct {
Backoff Backoff
MaxAttempts uint
MaxElapsed time.Duration
AttemptTimeout time.Duration
MinDelay time.Duration
MaxDelay time.Duration
MaxSleep time.Duration
Clock Clock
Sleeper Sleeper
Random Random
Classifier Classifier
Observer Observer
HistoryLimit uint
// UseResilienceBudget consumes the shared work-amplification scope attached
// to the execution context. Existing standalone behavior is unchanged when false.
UseResilienceBudget bool
}
Config contains all dependencies and bounds for a Policy. MaxAttempts is mandatory so no policy can retry forever.
type DelayHint ¶
DelayHint is implemented by classified errors that carry a server-provided minimum retry delay, such as HTTP Retry-After.
type ExhaustedError ¶
type ExhaustedError struct {
// contains filtered or unexported fields
}
ExhaustedError reports that MaxAttempts stopped a retryable operation.
func (*ExhaustedError) Error ¶
func (err *ExhaustedError) Error() string
func (*ExhaustedError) Result ¶
func (err *ExhaustedError) Result() Result
Result returns a defensive copy of terminal metadata.
func (*ExhaustedError) Unwrap ¶
func (err *ExhaustedError) Unwrap() error
type Observation ¶
type Observation struct {
Attempt uint
Elapsed time.Duration
NextDelay time.Duration
Classification Classification
Reason Reason
}
Observation is a bounded notification for one completed attempt.
type ObserveFunc ¶
type ObserveFunc func(Observation)
ObserveFunc adapts a function to Observer.
func (ObserveFunc) Observe ¶
func (function ObserveFunc) Observe(observation Observation)
Observe invokes the adapted function.
type Observer ¶
type Observer interface {
Observe(Observation)
}
Observer receives bounded lifecycle metadata.
type PermanentError ¶
type PermanentError struct{ Cause error }
PermanentError explicitly marks a cause as ineligible for retry.
func (*PermanentError) Error ¶
func (err *PermanentError) Error() string
func (*PermanentError) Unwrap ¶
func (err *PermanentError) Unwrap() error
type Policy ¶
type Policy struct {
// contains filtered or unexported fields
}
Policy is an immutable, explicitly bounded retry policy.
type Random ¶
Random is an injected, concurrency-safe source of uniform integers in [0, upper). Implementations must return zero when upper is non-positive.
type Reason ¶
type Reason string
Reason identifies why execution stopped.
const ( // ReasonSucceeded identifies a successful operation. ReasonSucceeded Reason = "succeeded" // ReasonPermanent identifies an explicitly permanent failure. ReasonPermanent Reason = "permanent" // ReasonAttemptsExhausted identifies maximum-attempt exhaustion. ReasonAttemptsExhausted Reason = "attempts_exhausted" // ReasonCanceled identifies caller cancellation or deadline. ReasonCanceled Reason = "canceled" // ReasonElapsedBudget identifies total elapsed-time exhaustion. ReasonElapsedBudget Reason = "elapsed_budget" // ReasonSleepBudget identifies accumulated-sleep exhaustion. ReasonSleepBudget Reason = "sleep_budget" // ReasonAttemptBudget identifies a per-attempt timeout. ReasonAttemptBudget Reason = "attempt_budget" // ReasonClassifierFailure identifies a classifier error or invalid result. ReasonClassifierFailure Reason = "classifier_failure" // ReasonSleeperFailure identifies a non-context sleeper failure. ReasonSleeperFailure Reason = "sleeper_failure" // ReasonWorkBudget identifies local denial by the shared amplification budget. ReasonWorkBudget Reason = "work_budget" )
type Result ¶
type Result struct {
Attempts uint
Elapsed time.Duration
FinalDelay time.Duration
Reason Reason
History []Attempt
}
Result contains bounded execution metadata and never retains operation values.
func Do ¶
func Do[T any](ctx context.Context, policy *Policy, operation func(context.Context) (T, error)) (T, Result, error)
Do executes operation under policy. The caller remains solely responsible for deciding whether repeating operation is safe.
Example ¶
package main
import (
"context"
"errors"
"fmt"
retry "github.com/faustbrian/go-retry"
)
func main() {
policy, err := retry.NewPolicy(retry.Config{
Backoff: retry.Constant(0), MaxAttempts: 3,
Clock: retry.SystemClock{}, Sleeper: retry.SystemSleeper{},
Classifier: retry.RetryableClassifier(), HistoryLimit: 2,
})
if err != nil {
panic(err)
}
attempts := 0
value, result, err := retry.Do(context.Background(), policy, func(context.Context) (string, error) {
attempts++
if attempts == 1 {
return "", retry.Retryable(errors.New("temporary"))
}
return "ready", nil
})
fmt.Println(value, result.Attempts, err)
}
Output: ready 2 <nil>
type RetryableError ¶
type RetryableError struct{ Cause error }
RetryableError explicitly marks a cause as eligible for bounded retry.
func (*RetryableError) Error ¶
func (err *RetryableError) Error() string
func (*RetryableError) Unwrap ¶
func (err *RetryableError) Unwrap() error
type SeededRandom ¶
type SeededRandom struct {
// contains filtered or unexported fields
}
SeededRandom is a deterministic, concurrency-safe PCG random source.
func NewRandom ¶
func NewRandom(seed1, seed2 uint64) *SeededRandom
NewRandom constructs a deterministic random source from explicit seeds.
func (*SeededRandom) Int64n ¶
func (random *SeededRandom) Int64n(upper int64) int64
Int64n returns a uniform value in [0, upper).
type SystemClock ¶
type SystemClock struct{}
SystemClock uses the process monotonic wall clock. It contains no global mutable state.
func (SystemClock) WithTimeout ¶
func (SystemClock) WithTimeout(parent context.Context, timeout time.Duration) (context.Context, context.CancelFunc)
WithTimeout derives a standard context timeout.
type SystemSleeper ¶
type SystemSleeper struct{}
SystemSleeper waits with a context-owned timer and always stops the timer.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package retryadapter provides explicit classifier seams for integrations whose transient failures are domain-specific.
|
Package retryadapter provides explicit classifier seams for integrations whose transient failures are domain-specific. |
|
Package retryhttp classifies HTTP response failures and parses Retry-After.
|
Package retryhttp classifies HTTP response failures and parses Retry-After. |
|
Package retrylog adapts bounded retry observations to log/slog, the logging API used by log.
|
Package retrylog adapts bounded retry observations to log/slog, the logging API used by log. |
|
Package retrypgx classifies PostgreSQL errors by SQLSTATE.
|
Package retrypgx classifies PostgreSQL errors by SQLSTATE. |
|
Package retrytelemetry adapts bounded retry observations to the standard OpenTelemetry API accepted by telemetry.
|
Package retrytelemetry adapts bounded retry observations to the standard OpenTelemetry API accepted by telemetry. |