### HTTP GET with Retry and Data Return Source: https://github.com/avast/retry-go/blob/main/README.md Execute an HTTP GET request and return data upon successful completion, with retry logic. This is suitable when the operation needs to return a value. ```go url := "http://example.com" body, err := retry.DoWithData(retry.New(), func() ([]byte, error) { resp, err := http.Get(url) if err != nil { return nil, err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } return body, nil }, ) if err != nil { // handle error } fmt.Println(string(body)) ``` -------------------------------- ### Execute Callback on Each Retry Source: https://github.com/avast/retry-go/blob/main/README.md Use OnRetry to provide a callback function that is executed on each retry attempt. The example logs each retry event. ```go retry.New( retry.OnRetry(func(n uint, err error) { log.Printf("#%d: %s\n", n, err) }), ).Do( func() error { return errors.New("some error") }, ) ``` -------------------------------- ### HTTP GET with Retry Source: https://github.com/avast/retry-go/blob/main/README.md Perform an HTTP GET request with a specified number of retry attempts and delay. This is useful for transient network issues. ```go url := "http://example.com" var body []byte err := retry.New( retry.Attempts(5), retry.Delay(100*time.Millisecond), ).Do( func() error { resp, err := http.Get(url) if err != nil { return err } defer resp.Body.Close() body, err = ioutil.ReadAll(resp.Body) if err != nil { return err } return nil }, ) if err != nil { // handle error } fmt.Println(string(body)) ``` -------------------------------- ### Inspect Multi-Attempt Errors with retry.Error Source: https://context7.com/avast/retry-go/llms.txt `retry.Error` wraps multiple attempt errors and implements `errors.Is`, `errors.As`, `Unwrap() []error` (Go 1.20), `WrappedErrors()` (hashicorp/errwrap), and `LastError()`. Use `errors.Is` to check for specific errors across attempts and `LastError()` to get the final error. ```go import ( "errors" "os" "github.com/avast/retry-go/v5" ) err := retry.New(retry.Attempts(3)).Do(func() error { return os.ErrNotExist }) // Check if any attempt returned a specific error if errors.Is(err, os.ErrNotExist) { fmt.Println("at least one attempt got ErrNotExist") } // Get the last error only if re, ok := err.(retry.Error); ok { fmt.Printf("failed %d times; last: %v\n", len(re), re.LastError()) } // Full error string: "All attempts fail:\n#1: ...\n#2: ...\n#3: ..." fmt.Println(err) ``` -------------------------------- ### BackOffDelay Strategy in retry-go Source: https://context7.com/avast/retry-go/llms.txt Uses BackOffDelay to double the delay between each attempt, starting from 100ms. This is useful for scenarios where a gradual increase in delay is desired. ```go // BackOffDelay: doubles delay each attempt (100ms → 200ms → 400ms → ...) retry.New(retry.DelayType(retry.BackOffDelay), retry.Delay(100*time.Millisecond)).Do(op) ``` -------------------------------- ### Use Custom Timer for Retries Source: https://github.com/avast/retry-go/blob/main/README.md Use WithTimer to inject a custom Timer implementation, useful for testing or mocking. The example shows augmenting time.After with a print statement. ```go type struct MyTimer {} func (t *MyTimer) After(d time.Duration) <- chan time.Time { fmt.Print("Timer called!") return time.After(d) } retry.New( retry.WithTimer(&MyTimer{}), ).Do( func() error { ... }, ) ``` -------------------------------- ### Set Retry Context Source: https://github.com/avast/retry-go/blob/main/README.md Use the Context option to set a custom context for retries. The default is the background context. Example shows immediate cancellation. ```go ctx, cancel := context.WithCancel(context.Background()) cancel() retry.New( retry.Context(ctx), ).Do( func() error { ... }, ) ``` -------------------------------- ### Control Retry Attempt Based on Error Source: https://github.com/avast/retry-go/blob/main/README.md Use RetryIf to define a condition for whether a retry should be attempted after an error. The example skips retries for a specific error message. ```go retry.New( retry.RetryIf(func(err error) bool { if err.Error() == "special error" { return false } return true }), ).Do( func() error { return errors.New("special error") }, ) ``` ```go retry.New().Do( func() error { return retry.Unrecoverable(errors.New("special error")) }, ) ``` -------------------------------- ### Get Max Jitter for RetrierWithData Source: https://github.com/avast/retry-go/blob/main/README.md Implements DelayContext by returning the maximum jitter duration for randomized delays. ```go func (r RetrierWithData) MaxJitter() time.Duration ``` -------------------------------- ### Get Max Back Off N for RetrierWithData Source: https://github.com/avast/retry-go/blob/main/README.md Implements DelayContext by returning the maximum back-off count for the retrier. ```go func (r RetrierWithData) MaxBackOffN() uint ``` -------------------------------- ### Get Max Delay for RetrierWithData Source: https://github.com/avast/retry-go/blob/main/README.md Implements DelayContext by returning the maximum delay duration allowed for retries. ```go func (r RetrierWithData) MaxDelay() time.Duration ``` -------------------------------- ### Getting the Last Error from Retry Error Source: https://github.com/avast/retry-go/blob/main/README.md Shows how to retrieve the last error from a `retry.Error` type, primarily for migration purposes from older versions of the library. Note that `errors.Is` and `errors.As` are generally preferred. ```go if retryErr, ok := err.(retry.Error); ok { lastErr := retryErr.LastError() } ``` -------------------------------- ### Error Handling with errors.Is and errors.As Source: https://github.com/avast/retry-go/blob/main/README.md Demonstrates how to use `errors.Is` to check for specific errors and `errors.As` to extract error details from a retry operation. This approach checks all wrapped errors. ```go err := retry.New(retry.Attempts(3)).Do(func() error { return os.ErrNotExist }) if errors.Is(err, os.ErrNotExist) { // Handle not exist error } ``` ```go var pathErr *fs.PathError if errors.As(err, &pathErr) { fmt.Println("Failed at path:", pathErr.Path) } ``` -------------------------------- ### Create a New Retrier Source: https://github.com/avast/retry-go/blob/main/README.md New creates a new Retrier with the given options. The returned Retrier can be safely reused. ```go func New(opts ...Option) *Retrier ``` -------------------------------- ### Choose Delay Strategy Source: https://context7.com/avast/retry-go/llms.txt Select a delay strategy using `DelayType`. Built-in options include `BackOffDelay`, `FixedDelay`, `RandomDelay`, and `FullJitterBackoffDelay`. Strategies can be combined using `CombineDelay`. ```go // Fixed delay err := retry.New( retry.DelayType(retry.FixedDelay), retry.Delay(1*time.Second), ).Do(op) ``` ```go // Exponential backoff with full jitter (AWS-style) err = retry.New( retry.DelayType(retry.FullJitterBackoffDelay), retry.Delay(100*time.Millisecond), retry.MaxDelay(30*time.Second), ).Do(op) ``` ```go // Custom: combine backoff + random jitter (the default) err = retry.New( retry.DelayType(retry.CombineDelay(retry.BackOffDelay, retry.RandomDelay)), ).Do(op) ``` -------------------------------- ### Create New RetrierWithData Instance Source: https://github.com/avast/retry-go/blob/main/README.md Function to create a new RetrierWithData instance with specified options. The returned retrier is safe for reuse. ```go func NewWithData[T any](opts ...Option) *RetrierWithData[T] ``` -------------------------------- ### Add Cancellation and Timeout Support with retry.Context Source: https://context7.com/avast/retry-go/llms.txt Attach a `context.Context` to the retrier using `retry.Context`. If the context is cancelled or times out between attempts, the retry loop stops and the context error is returned. ```go import ( "context" "time" "github.com/avast/retry-go/v5" ) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) deferr cancel() err := retry.New( retry.Attempts(0), // retry until success or context expires retry.Delay(500*time.Millisecond), retry.Context(ctx), ).Do(func() error { return connectToService() }) if err == context.DeadlineExceeded { fmt.Println("timed out after 10 seconds") } ``` -------------------------------- ### Create Retrier with Data Return Source: https://context7.com/avast/retry-go/llms.txt Use RetrierWithData for operations that return both a value and an error. Configure with attempts and delay. ```go import ( "io" "net/http" "github.com/avast/retry-go/v5" ) retrier := retry.NewWithData[[]byte]( retry.Attempts(3), retry.Delay(500*time.Millisecond), ) body, err := retrier.Do(func() ([]byte, error) { resp, err := http.Get("https://api.example.com/data") if err != nil { return nil, err } defer resp.Body.Close() return io.ReadAll(resp.Body) }) if err != nil { // err is a retry.Error containing all attempt errors } fmt.Println(string(body)) ``` -------------------------------- ### retry.New Source: https://context7.com/avast/retry-go/llms.txt Creates a new `*Retrier` configured with the provided options. The returned retrier is safe for concurrent reuse across many `.Do()` calls. Defaults: 10 attempts, 100ms base delay, exponential backoff + random jitter. ```APIDOC ## retry.New — Create a reusable Retrier Creates a new `*Retrier` configured with the provided options. The returned retrier is safe for concurrent reuse across many `.Do()` calls. Defaults: 10 attempts, 100ms base delay, exponential backoff + random jitter. ```go import ( "fmt" "log" "time" "github.com/avast/retry-go/v5" ) // Create once, reuse many times retrier := retry.New( retry.Attempts(5), retry.Delay(200*time.Millisecond), retry.MaxDelay(2*time.Second), ) for i := 0; i < 10; i++ { err := retrier.Do(func() error { return doWork() // retried up to 5 times per call }) if err != nil { log.Println("all attempts failed:", err) } } ``` ``` -------------------------------- ### Execute Function with Retry (Value + Error) Source: https://context7.com/avast/retry-go/llms.txt Execute a function returning a value and an error. Returns the first successful pair or a retry.Error after all attempts fail. ```go import ( "encoding/json" "net/http" "github.com/avast/retry-go/v5" ) type User struct { ID int `json:"id"` Name string `json:"name"` } user, err := retry.NewWithData[User](retry.Attempts(3)).Do(func() (User, error) { resp, err := http.Get("https://api.example.com/users/42") if err != nil { return User{}, err } defer resp.Body.Close() var u User if err := json.NewDecoder(resp.Body).Decode(&u); err != nil { return User{}, err } return u, nil }) if err == nil { fmt.Printf("Got user: %+v\n", user) } ``` -------------------------------- ### Execute Function with Retry (Error Only) Source: https://context7.com/avast/retry-go/llms.txt Execute a function returning only an error using the retrier's configuration. Returns nil on success or a retry.Error on failure. ```go import ( "database/sql" "errors" "log" "github.com/avast/retry-go/v5" ) var db *sql.DB err := retry.New(retry.Attempts(4)).Do(func() error { _, err := db.Exec("INSERT INTO events (name) VALUES (?)", "click") return err }) if err != nil { // Inspect individual attempt errors var retryErr retry.Error if errors.As(err, &retryErr) { log.Printf("Failed after %d attempts, last error: %v", len(retryErr), retryErr.LastError()) } } ``` -------------------------------- ### Create and Reuse a Retrier Source: https://context7.com/avast/retry-go/llms.txt Create a Retrier with custom options like attempts and delay. The returned retrier is safe for concurrent reuse across multiple operations. ```go import ( "fmt" "log" "time" "github.com/avast/retry-go/v5" ) // Create once, reuse many times retrier := retry.New( retry.Attempts(5), retry.Delay(200*time.Millisecond), retry.MaxDelay(2*time.Second), ) for i := 0; i < 10; i++ { err := retrier.Do(func() error { return doWork() // retried up to 5 times per call }) if err != nil { log.Println("all attempts failed:", err) } } ``` -------------------------------- ### Retry Indefinitely Until Succeeded Source: https://context7.com/avast/retry-go/llms.txt Use UntilSucceeded() as a convenience option equivalent to Attempts(0) for retrying until success or an unrecoverable error. ```go err := retry.New( retry.UntilSucceeded(), retry.Delay(1*time.Second), ).Do(func() error { return connectToDatabase() }) ``` -------------------------------- ### NewWithData Source: https://github.com/avast/retry-go/blob/main/README.md Creates a new RetrierWithData instance with specified options. The returned retrier is safe for concurrent reuse. ```APIDOC #### func NewWithData ```go func NewWithData[T any](opts ...Option) *RetrierWithData[T] ``` NewWithData creates a new RetrierWithData[T] with the given options. The returned retrier can be safely reused across multiple retry operations. ``` -------------------------------- ### FullJitterBackoffDelay Strategy in retry-go Source: https://context7.com/avast/retry-go/llms.txt Utilizes FullJitterBackoffDelay, recommended by AWS, for a randomized delay within a calculated range that grows exponentially but is capped. It includes options for base delay and maximum delay. ```go // FullJitterBackoffDelay: random in [0, min(cap, base*2^n)) — AWS recommended retry.New( retry.DelayType(retry.FullJitterBackoffDelay), retry.Delay(50*time.Millisecond), retry.MaxDelay(10*time.Second), ).Do(op) ``` -------------------------------- ### Retrier MaxDelay Method Source: https://github.com/avast/retry-go/blob/main/README.md MaxDelay returns the maximum delay configured for the retrier. ```go func (r Retrier) MaxDelay() time.Duration ``` -------------------------------- ### Implement DelayContext for RetrierWithData Source: https://github.com/avast/retry-go/blob/main/README.md Implements the DelayContext interface for RetrierWithData, returning the configured delay duration. ```go func (r RetrierWithData) Delay() time.Duration ``` -------------------------------- ### Inject Custom Timer with retry.WithTimer for Testing Source: https://context7.com/avast/retry-go/llms.txt Use `retry.WithTimer` to swap out the real `time.After`-based timer with a custom `Timer` interface implementation. This is primarily used in tests to avoid real sleeps and achieve instant retries. ```go type MockTimer struct{} func (m *MockTimer) After(d time.Duration) <-chan time.Time { ch := make(chan time.Time, 1) ch <- time.Now() // return immediately return ch } // In tests: instant retries with no real delays err := retry.New( retry.Attempts(5), retry.Delay(10*time.Second), // ignored by mock retry.WithTimer(&MockTimer{}), ).Do(func() error { return mayFail() }) ``` -------------------------------- ### RandomDelay Strategy in retry-go Source: https://context7.com/avast/retry-go/llms.txt Implements RandomDelay for a uniform random delay within a specified maximum jitter. This helps to avoid thundering herd problems by spreading out retries. ```go // RandomDelay: uniform random [0, maxJitter) retry.New(retry.DelayType(retry.RandomDelay), retry.MaxJitter(300*time.Millisecond)).Do(op) ``` -------------------------------- ### (*RetrierWithData[T]).Do Source: https://context7.com/avast/retry-go/llms.txt Executes a `RetryableFuncWithData[T]` (signature `func() (T, error)`), returning the first successful `(T, nil)` pair or `(zero, retry.Error)` after all attempts fail. ```APIDOC ## (*RetrierWithData[T]).Do — Execute with retry (value + error) Executes a `RetryableFuncWithData[T]` (signature `func() (T, error)`), returning the first successful `(T, nil)` pair or `(zero, retry.Error)` after all attempts fail. ```go import ( "encoding/json" "net/http" "github.com/avast/retry-go/v5" ) type User struct { ID int `json:"id"` Name string `json:"name"` } user, err := retry.NewWithData[User](retry.Attempts(3)).Do(func() (User, error) { resp, err := http.Get("https://api.example.com/users/42") if err != nil { return User{}, err } defer resp.Body.Close() var u User if err := json.NewDecoder(resp.Body).Decode(&u); err != nil { return User{}, err } return u, nil }) if err == nil { fmt.Printf("Got user: %+v\n", user) } ``` ``` -------------------------------- ### Execute Retryable Function Source: https://github.com/avast/retry-go/blob/main/README.md The Do method executes the provided retryable function using the Retrier's configuration. ```go func (r *Retrier) Do(retryableFunc RetryableFunc) error ``` -------------------------------- ### (*Retrier).Do Source: https://context7.com/avast/retry-go/llms.txt Executes the provided `RetryableFunc` (signature `func() error`) using the retrier's configuration. Returns `nil` on first success, or a `retry.Error` collecting all attempt errors after exhausting retries. ```APIDOC ## (*Retrier).Do — Execute with retry (error only) Executes the provided `RetryableFunc` (signature `func() error`) using the retrier's configuration. Returns `nil` on first success, or a `retry.Error` collecting all attempt errors after exhausting retries. ```go import ( "database/sql" "errors" "log" "github.com/avast/retry-go/v5" ) var db *sql.DB err := retry.New(retry.Attempts(4)).Do(func() error { _, err := db.Exec("INSERT INTO events (name) VALUES (?)", "click") return err }) if err != nil { // Inspect individual attempt errors var retryErr retry.Error if errors.As(err, &retryErr) { log.Printf("Failed after %d attempts, last error: %v", len(retryErr), retryErr.LastError()) } } ``` ``` -------------------------------- ### Use Custom Timer Implementation Source: https://github.com/avast/retry-go/blob/main/README.md Provides a mechanism to inject custom timer implementations, primarily useful for mocking and testing retry delays. ```APIDOC ## WithTimer ### Description WithTimer provides a way to swap out timer module implementations. This primarily is useful for mocking/testing, where you may not want to explicitly wait for a set duration for retries. ### Method ```go func WithTimer(t Timer) Option ``` ### Example ```go type struct MyTimer {} func (t *MyTimer) After(d time.Duration) <-chan time.Time { fmt.Print("Timer called!") return time.After(d) } retry.New( retry.WithTimer(&MyTimer{}), ).Do( func() error { ... }, ) ``` ``` -------------------------------- ### Register Callback with retry.OnRetry Source: https://context7.com/avast/retry-go/llms.txt Register a hook `func(attempt uint, err error)` using `retry.OnRetry` to be called after every failed attempt before the delay. This is useful for logging, metrics, or collecting intermediate errors. ```go import ( "log" "github.com/avast/retry-go/v5" ) var history []error err := retry.New( retry.Attempts(5), retry.OnRetry(func(n uint, err error) { log.Printf("attempt #%d failed: %v", n+1, err) history = append(history, err) }), ).Do(func() error { return callService() }) if err == nil { log.Printf("succeeded after %d failed attempt(s)", len(history)) } ``` -------------------------------- ### Execute Retryable Function with Data Source: https://github.com/avast/retry-go/blob/main/README.md Executes a retryable function using the RetrierWithData's configuration, returning the data and any error encountered. ```go func (r *RetrierWithData[T]) Do(retryableFunc RetryableFuncWithData[T]) (T, error) ``` -------------------------------- ### Reusable Retrier for High-Frequency Operations Source: https://github.com/avast/retry-go/blob/main/README.md Create a retrier instance once and reuse it for multiple operations to minimize allocations. This is efficient for loops or frequently called functions. ```go // Create retrier once, reuse many times retrier := retry.New( retry.Attempts(5), retry.Delay(100*time.Millisecond), ) // Minimal allocations in happy path for { err := retrier.Do( func() error { return doWork() }, ) if err != nil { // handle error } } ``` -------------------------------- ### Retry Until Function Succeeds Source: https://github.com/avast/retry-go/blob/main/README.md Use UntilSucceeded to configure the retrier to continue retrying until the function executes successfully. This is equivalent to setting Attempts(0). ```go func UntilSucceeded() Option ``` -------------------------------- ### Set Retry Delay Source: https://github.com/avast/retry-go/blob/main/README.md Use the Delay option to specify the duration between retries. The default delay is 100ms. ```go func Delay(delay time.Duration) Option ``` -------------------------------- ### FullJitterBackoffDelay Function Signature Source: https://github.com/avast/retry-go/blob/main/README.md Defines the FullJitterBackoffDelay function for exponential backoff with full jitter. The delay is randomized between 0 and the current backoff ceiling, using config.Delay as base and config.MaxDelay as cap. ```go func FullJitterBackoffDelay(n uint, err error, config DelayContext) time.Duration ``` -------------------------------- ### Set Maximum Retry Attempts Source: https://context7.com/avast/retry-go/llms.txt Configure the total number of times a function will be called. Setting attempts to 0 retries indefinitely. ```go // Retry exactly 3 times (3 total calls) err := retry.New(retry.Attempts(3)).Do(func() error { return callUnstableService() }) // Retry forever until success err = retry.New(retry.Attempts(0)).Do(func() error { return callUnstableService() }) ``` -------------------------------- ### DelayContext Source: https://github.com/avast/retry-go/blob/main/README.md DelayContext provides configuration values needed for delay calculation. ```APIDOC ## type DelayContext ### Description DelayContext provides configuration values needed for delay calculation. ### Interface Methods - `Delay() time.Duration` - `MaxJitter() time.Duration` - `MaxBackOffN() uint` - `MaxDelay() time.Duration` ``` -------------------------------- ### retry.WithTimer Source: https://context7.com/avast/retry-go/llms.txt Allows injecting a custom timer implementation, primarily for testing purposes to control delays. ```APIDOC ## retry.WithTimer — Inject a custom timer (for testing) Swaps out the real `time.After`-based timer with any implementation of the `Timer` interface. Primarily used in tests to avoid real sleeps. ```go type MockTimer struct{} func (m *MockTimer) After(d time.Duration) <-chan time.Time { ch := make(chan time.Time, 1) ch <- time.Now() // return immediately return ch } // In tests: instant retries with no real delays err := retry.New( retry.Attempts(5), retry.Delay(10*time.Second), // ignored by mock retry.WithTimer(&MockTimer{}), ).Do(func() error { return mayFail() }) ``` ``` -------------------------------- ### retry.Context Source: https://context7.com/avast/retry-go/llms.txt Integrates context.Context for cancellation and timeout support within the retry loop. ```APIDOC ## retry.Context — Cancellation and timeout support Attaches a `context.Context` to the retrier. If the context is cancelled or times out between attempts, the retry loop stops and the context error is returned. ```go import ( "context" "time" "github.com/avast/retry-go/v5" ) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() err := retry.New( retry.Attempts(0), // retry until success or context expires retry.Delay(500*time.Millisecond), retry.Context(ctx), ).Do(func() error { return connectToService() }) if err == context.DeadlineExceeded { fmt.Println("timed out after 10 seconds") } ``` ``` -------------------------------- ### New Retrier Creation Source: https://github.com/avast/retry-go/blob/main/README.md Creates a new Retrier instance with the specified options. The returned Retrier can be reused for multiple retry operations. ```APIDOC ## New ### Description Creates a new Retrier with the given options. The returned Retrier can be safely reused across multiple retry operations. ### Method ```go func New(opts ...Option) *Retrier ``` ``` -------------------------------- ### Retrier MaxBackOffN Method Source: https://github.com/avast/retry-go/blob/main/README.md MaxBackOffN returns the maximum backoff value for the retrier. ```go func (r Retrier) MaxBackOffN() uint ``` -------------------------------- ### Cap Delay Between Retries Source: https://context7.com/avast/retry-go/llms.txt Set an upper bound for the delay between retries with `MaxDelay`. This prevents exponential backoff from growing indefinitely. ```go err := retry.New( retry.Attempts(10), retry.Delay(100*time.Millisecond), retry.MaxDelay(5*time.Second), // never wait more than 5s ).Do(func() error { return callService() }) ``` -------------------------------- ### OnRetryFunc Source: https://github.com/avast/retry-go/blob/main/README.md Function signature of OnRetry function. ```APIDOC ## type OnRetryFunc ### Description Function signature of OnRetry function. ### Signature ```go type OnRetryFunc func(attempt uint, err error) ``` ``` -------------------------------- ### Set Maximum Retry Delay Source: https://github.com/avast/retry-go/blob/main/README.md Use MaxDelay to set an upper limit on the delay between retries. This option does not apply by default. ```go func MaxDelay(maxDelay time.Duration) Option ``` -------------------------------- ### Option Source: https://github.com/avast/retry-go/blob/main/README.md Option represents an option for retry. ```APIDOC ## type Option ### Description Option represents an option for retry. ### Signature ```go type Option func(*retrierCore) ``` ``` -------------------------------- ### Retrier Delay Method Source: https://github.com/avast/retry-go/blob/main/README.md The Delay method on a Retrier returns the configured delay duration. ```go func (r Retrier) Delay() time.Duration ``` -------------------------------- ### Set Maximum Jitter for Random Delay Source: https://github.com/avast/retry-go/blob/main/README.md Use MaxJitter to specify the maximum random jitter to be applied to the RandomDelay strategy. ```go func MaxJitter(maxJitter time.Duration) Option ``` -------------------------------- ### retry.UntilSucceeded Source: https://context7.com/avast/retry-go/llms.txt Convenience option equivalent to `Attempts(0)`. Retries the function until it returns `nil` or an unrecoverable error. ```APIDOC ## retry.UntilSucceeded — Retry indefinitely Convenience option equivalent to `Attempts(0)`. Retries the function until it returns `nil` or an unrecoverable error. ```go err := retry.New( retry.UntilSucceeded(), retry.Delay(1*time.Second), ).Do(func() error { return connectToDatabase() }) ``` ``` -------------------------------- ### CombineDelay Strategy in retry-go Source: https://context7.com/avast/retry-go/llms.txt Combines multiple delay strategies, such as BackOffDelay and RandomDelay, to create a custom retry delay behavior. The default combination is BackOff + Random. ```go // CombineDelay: sum multiple strategies (default = BackOff + Random) retry.New( retry.DelayType(retry.CombineDelay(retry.BackOffDelay, retry.RandomDelay)), ).Do(op) ``` -------------------------------- ### Combine Context and Last Error with retry.WrapContextErrorWithLastError Source: https://context7.com/avast/retry-go/llms.txt When retrying indefinitely with a context, `retry.WrapContextErrorWithLastError(true)` wraps the context cancellation error together with the last function error, allowing callers to inspect both. ```go ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) deferr cancel() err := retry.New( retry.Attempts(0), retry.Context(ctx), retry.WrapContextErrorWithLastError(true), ).Do(func() error { return unstableCall() }) // err is retry.Error{context.DeadlineExceeded, lastFuncError} if errors.Is(err, context.DeadlineExceeded) { var retryErr retry.Error errors.As(err, &retryErr) fmt.Println("timed out, last error was:", retryErr.LastError()) } ``` -------------------------------- ### retry.OnRetry Source: https://context7.com/avast/retry-go/llms.txt Registers a callback function that is executed after each failed attempt before the delay. ```APIDOC ## retry.OnRetry — Callback on each failed attempt Registers a hook `func(attempt uint, err error)` called after every failed attempt (before the delay). Useful for logging, metrics, or collecting intermediate errors. ```go import ( "log" "github.com/avast/retry-go/v5" ) var history []error err := retry.New( retry.Attempts(5), retry.OnRetry(func(n uint, err error) { log.Printf("attempt #%d failed: %v", n+1, err) history = append(history, err) }), ).Do(func() error { return callService() }) if err == nil { log.Printf("succeeded after %d failed attempt(s)", len(history)) } ``` ``` -------------------------------- ### Error.As Method Signature Source: https://github.com/avast/retry-go/blob/main/README.md Defines the As method for the Error type, which checks if any wrapped error matches the target type. ```go func (e Error) As(target interface{}) bool ``` -------------------------------- ### Set Context for Retries Source: https://github.com/avast/retry-go/blob/main/README.md Allows setting a context for the retry operations. Defaults to the background context. Useful for cancellation or timeouts. ```APIDOC ## Context ### Description Context allow to set context of retry default are Background context. ### Method ```go func Context(ctx context.Context) Option ``` ### Example ```go ctx, cancel := context.WithCancel(context.Background()) cancel() retry.New( retry.Context(ctx), ).Do( func() error { ... }, ) ``` ``` -------------------------------- ### Define Timer Interface Source: https://github.com/avast/retry-go/blob/main/README.md Defines the Timer interface, representing the mechanism used to track time for retries. It includes an After method for delayed channel operations. ```go type Timer interface { After(time.Duration) <-chan time.Time } ``` -------------------------------- ### DelayContext Interface Definition Source: https://github.com/avast/retry-go/blob/main/README.md Defines the DelayContext interface, which provides essential configuration values for calculating retry delays. ```go type DelayContext interface { Delay() time.Duration MaxJitter() time.Duration MaxBackOffN() uint MaxDelay() time.Duration } ``` -------------------------------- ### FullJitterBackoffDelay Source: https://github.com/avast/retry-go/blob/main/README.md FullJitterBackoffDelay is a DelayTypeFunc that calculates delay using exponential backoff with full jitter. The delay is a random value between 0 and the current backoff ceiling. ```APIDOC ## func FullJitterBackoffDelay ### Description FullJitterBackoffDelay is a DelayTypeFunc that calculates delay using exponential backoff with full jitter. The delay is a random value between 0 and the current backoff ceiling. Formula: sleep = random_between(0, min(cap, base * 2^attempt)) It uses config.Delay as the base delay and config.MaxDelay as the cap. ### Signature ```go func FullJitterBackoffDelay(n uint, err error, config DelayContext) time.Duration ``` ``` -------------------------------- ### Retrier MaxJitter Method Source: https://github.com/avast/retry-go/blob/main/README.md MaxJitter returns the maximum jitter configured for the retrier. ```go func (r Retrier) MaxJitter() time.Duration ``` -------------------------------- ### FixedDelay Strategy in retry-go Source: https://context7.com/avast/retry-go/llms.txt Employs FixedDelay to maintain a constant 500ms delay between every retry attempt. This is suitable for services with predictable latency or rate limits. ```go // FixedDelay: constant 500ms between every attempt retry.New(retry.DelayType(retry.FixedDelay), retry.Delay(500*time.Millisecond)).Do(op) ``` -------------------------------- ### RetrierWithData.MaxBackOffN Source: https://github.com/avast/retry-go/blob/main/README.md Returns the maximum number of back-off attempts, implementing the DelayContext interface. ```APIDOC #### func (RetrierWithData) MaxBackOffN ```go func (r RetrierWithData) MaxBackOffN() uint ``` MaxBackOffN implements DelayContext ``` -------------------------------- ### Set Custom Delay Strategy Source: https://github.com/avast/retry-go/blob/main/README.md Allows defining a custom function to determine the delay between retries. Defaults to a combination of exponential backoff and jitter. ```APIDOC ## DelayType ### Description DelayType set type of the delay between retries default is a combination of BackOffDelay and RandomDelay for exponential backoff with jitter. ### Method ```go func DelayType(delayType DelayTypeFunc) Option ``` ``` -------------------------------- ### Set Base Delay Between Retries Source: https://context7.com/avast/retry-go/llms.txt Configure the base delay duration between retry attempts using `Delay`. The default is `100ms`. This value can be modified by the chosen `DelayType`. ```go err := retry.New( retry.Attempts(5), retry.Delay(500*time.Millisecond), // 500ms base, grows with BackOffDelay ).Do(func() error { return fetchFromSlowAPI() }) ``` -------------------------------- ### Mark Unrecoverable Errors with retry.Unrecoverable Source: https://context7.com/avast/retry-go/llms.txt Wrap errors with `retry.Unrecoverable` to immediately stop all retries and surface the error. Use `retry.IsRecoverable` to check if an error permits retrying, often used in custom `RetryIf` logic. ```go err := retry.New(retry.Attempts(10)).Do(func() error { result, err := callAPI() if err != nil { if isAuthError(err) { // no point retrying auth failures return retry.Unrecoverable(err) } return err // transient — will be retried } _ = result return nil }) // IsRecoverable can also be used in custom RetryIf logic retry.New( retry.RetryIf(retry.IsRecoverable), ).Do(op) ``` -------------------------------- ### RetrierWithData.Do Source: https://github.com/avast/retry-go/blob/main/README.md Executes a retryable function using the configuration of the RetrierWithData instance. This method handles the retry logic for functions that return data and an error. ```APIDOC #### func (*RetrierWithData[T]) Do ```go func (r *RetrierWithData[T]) Do(retryableFunc RetryableFuncWithData[T]) (T, error) ``` Do executes the retryable function using this RetrierWithData's configuration. ``` -------------------------------- ### BackOffDelay Function Signature Source: https://github.com/avast/retry-go/blob/main/README.md Defines the BackOffDelay function, which increases delay between consecutive retries. It takes the attempt number, an error, and delay context to return the duration. ```go func BackOffDelay(n uint, _ error, config DelayContext) time.Duration ``` -------------------------------- ### retry.MaxDelay Source: https://context7.com/avast/retry-go/llms.txt Sets an upper bound on the computed delay so exponential backoff does not grow unboundedly. ```APIDOC ## `retry.MaxDelay` — Cap the delay between retries Sets an upper bound on the computed delay so exponential backoff does not grow unboundedly. ```go err := retry.New( retry.Attempts(10), retry.Delay(100*time.Millisecond), retry.MaxDelay(5*time.Second), // never wait more than 5s ).Do(func() error { return callService() }) ``` ``` -------------------------------- ### Retry Until Success Source: https://github.com/avast/retry-go/blob/main/README.md Configures the retrier to continue retrying indefinitely until the retryable function succeeds. This is equivalent to setting Attempts(0). ```APIDOC ## UntilSucceeded ### Description UntilSucceeded will retry until the retried function succeeds. Equivalent to setting Attempts(0). ### Method ```go func UntilSucceeded() Option ``` ``` -------------------------------- ### Limit Retries for Specific Errors Source: https://context7.com/avast/retry-go/llms.txt Use `AttemptsForError` to set a retry limit for a particular sentinel error. This limit counts against the total attempts. ```go import "errors" var ErrRateLimit = errors.New("rate limited") err := retry.New( retry.Attempts(20), retry.AttemptsForError(3, ErrRateLimit), // stop after 3 rate-limit errors ).Do(func() error { result, err := callAPI() if isRateLimited(err) { return ErrRateLimit } _ = result return err }) ``` -------------------------------- ### retry.DelayType Source: https://context7.com/avast/retry-go/llms.txt Choose or compose a delay strategy. Replaces the default delay strategy. Built-in strategies: `BackOffDelay`, `FixedDelay`, `RandomDelay`, `FullJitterBackoffDelay`. Use `CombineDelay` to combine multiple strategies. ```APIDOC ## `retry.DelayType` — Choose or compose a delay strategy Replaces the default delay strategy. Built-in strategies: `BackOffDelay`, `FixedDelay`, `RandomDelay`, `FullJitterBackoffDelay`. Use `CombineDelay` to combine multiple strategies. ```go // Fixed delay err := retry.New( retry.DelayType(retry.FixedDelay), retry.Delay(1*time.Second), ).Do(op) // Exponential backoff with full jitter (AWS-style) err = retry.New( retry.DelayType(retry.FullJitterBackoffDelay), retry.Delay(100*time.Millisecond), retry.MaxDelay(30*time.Second), ).Do(op) // Custom: combine backoff + random jitter (the default) err = retry.New( retry.DelayType(retry.CombineDelay(retry.BackOffDelay, retry.RandomDelay)), ).Do(op) ``` ``` -------------------------------- ### Attempts Source: https://github.com/avast/retry-go/blob/main/README.md Attempts set count of retry. Setting to 0 will retry until the retried function succeeds. default is 10. ```APIDOC ## func Attempts ### Description Attempts set count of retry. Setting to 0 will retry until the retried function succeeds. default is 10. ### Signature ```go func Attempts(attempts uint) Option ``` ``` -------------------------------- ### retry.NewWithData Source: https://context7.com/avast/retry-go/llms.txt Creates a `*RetrierWithData[T]` for operations that return both a typed result and an error, avoiding the need for a shared variable. ```APIDOC ## retry.NewWithData — Create a Retrier that returns a value Creates a `*RetrierWithData[T]` for operations that return both a typed result and an error, avoiding the need for a shared variable. ```go import ( "io" "net/http" "github.com/avast/retry-go/v5" ) retrier := retry.NewWithData[[]byte]( retry.Attempts(3), retry.Delay(500*time.Millisecond), ) body, err := retrier.Do(func() ([]byte, error) { resp, err := http.Get("https://api.example.com/data") if err != nil { return nil, err } defer resp.Body.Close() return io.ReadAll(resp.Body) }) if err != nil { // err is a retry.Error containing all attempt errors } fmt.Println(string(body)) ``` ``` -------------------------------- ### Execute Retryable Function Source: https://github.com/avast/retry-go/blob/main/README.md Executes a given retryable function using the Retrier's current configuration. Returns an error if the function fails after all retries. ```APIDOC ## Do ### Description Do executes the retryable function using this Retrier's configuration. ### Method ```go func (r *Retrier) Do(retryableFunc RetryableFunc) error ``` ``` -------------------------------- ### Error.Unwrap Method Signature Source: https://github.com/avast/retry-go/blob/main/README.md Defines the Unwrap method for the Error type, returning the list of wrapped errors. This implements the Go 1.20 multi-error unwrapping interface. ```go func (e Error) Unwrap() []error ``` -------------------------------- ### Define RetrierWithData Type Source: https://github.com/avast/retry-go/blob/main/README.md Defines the RetrierWithData struct, used for retry operations that return both data and an error. ```go type RetrierWithData[T any] struct { } ``` -------------------------------- ### Attempts Function Signature Source: https://github.com/avast/retry-go/blob/main/README.md Defines the Attempts function, which returns an Option to set the maximum number of retry attempts. A value of 0 means retrying indefinitely. ```go func Attempts(attempts uint) Option ``` -------------------------------- ### RandomDelay Source: https://github.com/avast/retry-go/blob/main/README.md RandomDelay is a DelayType which picks a random delay up to maxJitter. ```APIDOC ## func RandomDelay ### Description RandomDelay is a DelayType which picks a random delay up to maxJitter. ### Signature ```go func RandomDelay(_ uint, _ error, config DelayContext) time.Duration ``` ``` -------------------------------- ### Timer Interface Source: https://github.com/avast/retry-go/blob/main/README.md Represents a timer mechanism used for managing delays in retry operations. ```APIDOC #### type Timer ```go type Timer interface { After(time.Duration) <-chan time.Time } ``` Timer represents the timer used to track time for a retry. ``` -------------------------------- ### BackOffDelay Source: https://github.com/avast/retry-go/blob/main/README.md BackOffDelay is a DelayType which increases delay between consecutive retries. ```APIDOC ## func BackOffDelay ### Description BackOffDelay is a DelayType which increases delay between consecutive retries. ### Signature ```go func BackOffDelay(n uint, _ error, config DelayContext) time.Duration ``` ``` -------------------------------- ### Conditional Retry Predicate Source: https://context7.com/avast/retry-go/llms.txt Use `RetryIf` to define a predicate function that determines whether a given error should trigger a retry. Returning `false` will stop retries immediately. ```go import ( "net/http" "strings" "github.com/avast/retry-go/v5" ) err := retry.New( retry.RetryIf(func(err error) bool { // only retry on network or 5xx errors, not on 4xx client errors if herr, ok := err.(*url.Error); ok && herr.Timeout() { return true } return strings.Contains(err.Error(), "server error") }), ).Do(func() error { resp, err := http.Get("https://api.example.com") if err != nil { return err } defer resp.Body.Close() if resp.StatusCode >= 400 { return fmt.Errorf("HTTP %d: server error", resp.StatusCode) } return nil }) ``` -------------------------------- ### FixedDelay Function Signature Source: https://github.com/avast/retry-go/blob/main/README.md Defines the FixedDelay function, which maintains a constant delay across all retry attempts. It accepts attempt number, error, and delay context. ```go func FixedDelay(_ uint, _ error, config DelayContext) time.Duration ``` -------------------------------- ### Define RetryableFuncWithData Signature Source: https://github.com/avast/retry-go/blob/main/README.md Defines the function signature for a retryable operation that returns data and an error. ```go type RetryableFuncWithData[T any] func() (T, error) ``` -------------------------------- ### RandomDelay Function Signature Source: https://github.com/avast/retry-go/blob/main/README.md Defines the RandomDelay function, which selects a random delay duration up to a specified maximum jitter. ```go func RandomDelay(_ uint, _ error, config DelayContext) time.Duration ``` -------------------------------- ### Set Delay Between Retries Source: https://github.com/avast/retry-go/blob/main/README.md Configures the fixed duration to wait between retry attempts. Defaults to 100ms. ```APIDOC ## Delay ### Description Delay set delay between retry default is 100ms. ### Method ```go func Delay(delay time.Duration) Option ``` ``` -------------------------------- ### RetrierWithData.MaxDelay Source: https://github.com/avast/retry-go/blob/main/README.md Returns the maximum duration allowed for a delay between retries, implementing the DelayContext interface. ```APIDOC #### func (RetrierWithData) MaxDelay ```go func (r RetrierWithData) MaxDelay() time.Duration ``` MaxDelay implements DelayContext ``` -------------------------------- ### retry.Error Source: https://context7.com/avast/retry-go/llms.txt Provides methods to inspect errors accumulated across multiple retry attempts. ```APIDOC ## retry.Error — Inspecting multi-attempt errors `retry.Error` is `[]error` and implements `errors.Is`, `errors.As`, `Unwrap() []error` (Go 1.20), `WrappedErrors()` (hashicorp/errwrap), and `LastError()`. ```go import ( "errors" "os" "github.com/avast/retry-go/v5" ) err := retry.New(retry.Attempts(3)).Do(func() error { return os.ErrNotExist }) // Check if any attempt returned a specific error if errors.Is(err, os.ErrNotExist) { fmt.Println("at least one attempt got ErrNotExist") } // Get the last error only if re, ok := err.(retry.Error); ok { fmt.Printf("failed %d times; last: %v\n", len(re), re.LastError()) } // Full error string: "All attempts fail:\n#1: ...\n#2: ...\n#3: ..." fmt.Println(err) ``` ``` -------------------------------- ### Set Retry Attempts for Specific Errors Source: https://github.com/avast/retry-go/blob/main/README.md Use AttemptsForError to set the number of retries for a specific error. These attempts are counted against the total retries. ```go func AttemptsForError(attempts uint, err error) Option ``` -------------------------------- ### retry.AttemptsForError Source: https://context7.com/avast/retry-go/llms.txt Limits the number of retries for a specific sentinel error. Retries for this error count against the total attempt budget. Stops as soon as either limit is exhausted. ```APIDOC ## `retry.AttemptsForError` — Per-error attempt limit Limits the number of retries for a specific sentinel error. Retries for this error count against the total attempt budget. Stops as soon as either limit is exhausted. ```go import "errors" var ErrRateLimit = errors.New("rate limited") err := retry.New( retry.Attempts(20), retry.AttemptsForError(3, ErrRateLimit), // stop after 3 rate-limit errors ).Do(func() error { result, err := callAPI() if isRateLimited(err) { return ErrRateLimit } _ = result return err }) ``` ``` -------------------------------- ### Option Function Type Definition Source: https://github.com/avast/retry-go/blob/main/README.md Defines the Option function type, used for configuring the retry behavior through functional options. ```go type Option func(*retrierCore) ``` -------------------------------- ### Error.Error Method Signature Source: https://github.com/avast/retry-go/blob/main/README.md Defines the Error method for the Error type, implementing the error interface to return a string representation of the error list. ```go func (e Error) Error() string ``` -------------------------------- ### retry.Attempts Source: https://context7.com/avast/retry-go/llms.txt Sets the total number of times the function will be called. Setting to `0` retries indefinitely until success or an unrecoverable error. Default is `10`. ```APIDOC ## retry.Attempts — Set maximum retry count Sets the total number of times the function will be called. Setting to `0` retries indefinitely until success or an unrecoverable error. Default is `10`. ```go // Retry exactly 3 times (3 total calls) err := retry.New(retry.Attempts(3)).Do(func() error { return callUnstableService() }) // Retry forever until success err = retry.New(retry.Attempts(0)).Do(func() error { return callUnstableService() }) ``` ``` -------------------------------- ### RetrierWithData.MaxJitter Source: https://github.com/avast/retry-go/blob/main/README.md Returns the maximum jitter duration to be added to the delay, implementing the DelayContext interface. ```APIDOC #### func (RetrierWithData) MaxJitter ```go func (r RetrierWithData) MaxJitter() time.Duration ``` MaxJitter implements DelayContext ``` -------------------------------- ### Error.Is Method Signature Source: https://github.com/avast/retry-go/blob/main/README.md Defines the Is method for the Error type, checking if any wrapped error matches the target error. ```go func (e Error) Is(target error) bool ``` -------------------------------- ### retry.Delay Source: https://context7.com/avast/retry-go/llms.txt Sets the base delay duration used between attempts. Default is `100ms`. The actual delay depends on the `DelayType` in use (e.g., BackOffDelay multiplies this value exponentially). ```APIDOC ## `retry.Delay` — Set base delay between retries Sets the base delay duration used between attempts. Default is `100ms`. The actual delay depends on the `DelayType` in use (e.g., BackOffDelay multiplies this value exponentially). ```go err := retry.New( retry.Attempts(5), retry.Delay(500*time.Millisecond), // 500ms base, grows with BackOffDelay ).Do(func() error { return fetchFromSlowAPI() }) ``` ```