MCPcopy
hub / github.com/cenkalti/backoff

github.com/cenkalti/backoff @v7.0.0 sqlite

repository ↗ · DeepWiki ↗ · release v7.0.0 ↗
97 symbols 360 edges 12 files 48 documented · 49%
README

Exponential Backoff GoDoc

This is a Go port of the exponential backoff algorithm from Google's HTTP Client Library for Java.

Exponential backoff is an algorithm that uses feedback to multiplicatively decrease the rate of some process, in order to gradually find an acceptable rate. The retries exponentially increase and stop increasing when a certain threshold is met.

Install

go get github.com/cenkalti/backoff/v7

Note the /v7 at the end of the import path.

Usage

For most cases, wrap the operation you want to retry in Retry:

result, err := backoff.Retry(ctx, func() (string, error) {
    resp, err := http.Get("https://www.example.com")
    if err != nil {
        return "", err // transient: Retry will try again
    }
    defer resp.Body.Close()

    switch {
    case resp.StatusCode >= 500:
        return "", fmt.Errorf("server error: %s", resp.Status) // retried
    case resp.StatusCode >= 400:
        // client errors won't fix themselves, so stop retrying.
        return "", backoff.Permanent(fmt.Errorf("client error: %s", resp.Status))
    }
    return "ok", nil
}, backoff.WithMaxTries(5))

Retry runs the operation at least once and keeps retrying with exponential backoff until it succeeds, returns a Permanent error, or a limit is reached. See example_test.go for a fuller example, and the package docs for the available options (WithBackOff, WithMaxTries, WithMaxElapsedTime, WithNotify).

If Retry does not fit your needs, copy it from retry.go and adapt it.

Handling errors

On failure, Retry always returns a *RetryError. It carries the last operation error (LastErr) and the reason retrying stopped (Cause). Inspect it with errors.Is, or reach the struct with AsRetryError:

result, err := backoff.Retry(ctx, operation)
switch {
case errors.Is(err, backoff.ErrPermanent):
    // the operation returned a Permanent error
case errors.Is(err, context.Canceled), errors.Is(err, context.DeadlineExceeded):
    // the caller's context was cancelled or its deadline expired
case errors.Is(err, backoff.ErrMaxElapsedTime):
    // the WithMaxElapsedTime budget was exhausted
case errors.Is(err, backoff.ErrExhausted):
    // WithMaxTries was reached or the backoff policy returned Stop
}

// The last operation error is always available, whatever the cause:
if re := backoff.AsRetryError(err); re != nil {
    log.Printf("gave up after last error: %v", re.LastErr)
}

Mark an error non-retriable with backoff.Permanent(err); Retry stops immediately and returns a *RetryError whose Cause is ErrPermanent and whose LastErr is err.

Bounding total time

Two independent limits cap how long Retry runs, and they behave differently:

  • A context deadline (context.WithTimeout) is reactive: it interrupts the wait between attempts and — if your operation observes the context — can abort an in-flight attempt. Retry reports it as context.DeadlineExceeded.
  • WithMaxElapsedTime bounds only retry scheduling: it is checked between attempts, never interrupts a running operation, and is reported as ErrMaxElapsedTime.

WithMaxElapsedTime defaults to 15 minutes, so both limits are active unless you override it — pass backoff.WithMaxElapsedTime(0) to rely solely on the context.

Contributing

  • I would like to keep this library as small as possible.
  • Please don't send a PR without opening an issue and discussing it first.
  • If proposed change is not a common use case, I will probably not accept it.

Extension points exported contracts — how you extend this code

BackOff (Interface)
BackOff is a backoff policy for retrying an operation. [5 implementers]
backoff.go
Operation (FuncType)
Operation is the function Retry calls. It is invoked at least once and may be retried on error. Return a Permanent error
retry.go
Notify (FuncType)
Notify is called after a failed attempt that will be retried, with the operation error and the backoff duration before t
retry.go
RetryOption (FuncType)
RetryOption configures the behavior of Retry.
retry.go

Core symbols most depended-on inside this repo

Is
called by 30
error.go
Retry
called by 20
retry.go
withTimer
called by 19
retry.go
WithBackOff
called by 12
retry.go
Error
called by 11
error.go
Permanent
called by 8
error.go
NewExponentialBackOff
called by 7
exponential.go
getRandomValueFromInterval
called by 7
exponential.go

Shape

Function 44
Method 35
Struct 13
FuncType 3
Interface 2

Languages

Go100%

Modules by API surface

retry_test.go27 symbols
error.go13 symbols
backoff.go13 symbols
retry.go10 symbols
timer.go8 symbols
exponential.go6 symbols
ticker.go5 symbols
exponential_test.go4 symbols
ticker_test.go3 symbols
example_test.go3 symbols
backoff_test.go3 symbols
tries_test.go2 symbols

For agents

$ claude mcp add backoff \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact