package backoffimport ()// DefaultMaxElapsedTime sets a default limit for the total retry duration.constDefaultMaxElapsedTime = 15 * time.Minute// Operation is a function that attempts an operation and may be retried.typeOperation[ any] func() (, error)// Notify is a function called on operation error with the error and backoff duration.typeNotifyfunc(error, time.Duration)// retryOptions holds configuration settings for the retry mechanism.type retryOptions struct { BackOff BackOff// Strategy for calculating backoff periods. Timer timer// Timer to manage retry delays. Notify Notify// Optional function to notify on each retry error. MaxTries uint// Maximum number of retry attempts. MaxElapsedTime time.Duration// Maximum total time for all retries.}typeRetryOptionfunc(*retryOptions)// WithBackOff configures a custom backoff strategy.func ( BackOff) RetryOption {returnfunc( *retryOptions) { .BackOff = }}// withTimer sets a custom timer for managing delays between retries.func withTimer( timer) RetryOption {returnfunc( *retryOptions) { .Timer = }}// WithNotify sets a notification function to handle retry errors.func ( Notify) RetryOption {returnfunc( *retryOptions) { .Notify = }}// WithMaxTries limits the number of all attempts.func ( uint) RetryOption {returnfunc( *retryOptions) { .MaxTries = }}// WithMaxElapsedTime limits the total duration for retry attempts.func ( time.Duration) RetryOption {returnfunc( *retryOptions) { .MaxElapsedTime = }}// Retry attempts the operation until success, a permanent error, or backoff completion.// It ensures the operation is executed at least once.//// Returns the operation result or error if retries are exhausted or context is cancelled.func [ any]( context.Context, Operation[], ...RetryOption) (, error) {// Initialize default retry options. := &retryOptions{BackOff: NewExponentialBackOff(),Timer: &defaultTimer{},MaxElapsedTime: DefaultMaxElapsedTime, }// Apply user-provided options to the default settings.for , := range { () }defer .Timer.Stop() := time.Now() .BackOff.Reset()for := uint(1); ; ++ {// Execute the operation. , := ()if == nil {return , nil }// Stop retrying if maximum tries exceeded.if .MaxTries > 0 && >= .MaxTries {return , }// Handle permanent errors without retrying.var *PermanentErroriferrors.As(, &) {return , .Unwrap() }// Stop retrying if context is cancelled.if := context.Cause(); != nil {return , }// Calculate next backoff duration. := .BackOff.NextBackOff()if == Stop {return , }// Reset backoff if RetryAfterError is encountered.var *RetryAfterErroriferrors.As(, &) { = .Duration .BackOff.Reset() }// Stop retrying if maximum elapsed time exceeded.if .MaxElapsedTime > 0 && time.Since()+ > .MaxElapsedTime {return , }// Notify on error if a notifier function is provided.if .Notify != nil { .Notify(, ) }// Wait for the next backoff period or context cancellation. .Timer.Start()select {case<-.Timer.C():case<-.Done():return , context.Cause() } }}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.