retry

package
v0.21.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 14, 2026 License: MIT Imports: 7 Imported by: 0

README ¶

Contributions Welcome Release

🔄 Retry Package

The Retry Package provides a robust and extensible interface for automatically retrying operations in Go. It supports configurable retry strategies like fixed delays, jitter, and exponential backoff, ensuring reliability in API calls, database queries, and distributed systems.

Features

  • Customizable Backoff Strategies – Supports Fixed, Jitter, and Exponential backoff
  • Context-Aware – Automatically stops retries when the context is canceled
  • Configurable Retry Conditions – Choose which errors should trigger retries

Installation

go get github.com/kittipat1413/go-common/framework/retry

Documentation

Go Reference

For detailed API documentation, examples, and usage patterns, visit the Go Package Documentation.

Usage

🧩 Interface
type Retrier interface {
    ExecuteWithRetry(ctx context.Context, fn RetryFunc, retryOn RetryOnFunc) error
}

ExecuteWithRetry: Executes a function with automatic retry logic.

  • Params:
    • ctx: Context for request tracing and cancellation
    • fn: The function to retry (must return an error if it fails)
    • retryOn: Custom function to determine retry conditions
  • Returns:
    • error: The final result after retries.
Example: Basic Retry
package main

import (
	"context"
	"errors"
	"fmt"
	"log"
	"time"

	"github.com/kittipat1413/go-common/framework/retry"
)

func main() {
	ctx := context.Background()

	// Define backoff strategy
	backoff, err := retry.NewFixedBackoffStrategy(2 * time.Second)
	if err != nil {
		log.Fatalf("Failed to create backoff strategy: %v", err)
	}
	// Define retry configuration
	config := retry.Config{
		MaxAttempts: 3,
		Backoff:     backoff,
	}
	// Create Retrier
	retrier, err := retry.NewRetrier(config)
	if err != nil {
		log.Fatalf("Failed to create retrier: %v", err)
	}

	// Execute function with retry logic
	err = retrier.ExecuteWithRetry(ctx, func(ctx context.Context) error {
		fmt.Println("Attempting API request...")
		return errors.New("network timeout")
	}, func(attempt int, err error) bool {
		fmt.Printf("Retry %d due to: %v\n", attempt, err)
		return err.Error() == "network timeout" // Retry only for network timeouts
	})

	if err != nil {
		fmt.Println("Final failure:", err)
	} else {
		fmt.Println("Operation succeeded!")
	}
}

You can find a complete working example in the repository under framework/retry/example.

Backoff Strategies

1. Fixed Backoff

backoff, _ := retry.NewFixedBackoffStrategy(2 * time.Second)
  • Constant delay between retries
  • Simple and predictable retry behavior

2. Jitter Backoff

backoff, _ := retry.NewJitterBackoffStrategy(2*time.Second, 500*time.Millisecond)
  • Adds randomness to prevent synchronized retries (thundering herd problem)

3. Exponential Backoff

backoff, _ := retry.NewExponentialBackoffStrategy(
	100*time.Millisecond, // base
	2.0,                  // factor
	5*time.Second,        // upper limit of delay
)
  • Delays grow exponentially (BaseDelay * Factor^attempt)
  • Prevents excessive load on failing services

Documentation ¶

Index ¶

Constants ¶

This section is empty.

Variables ¶

View Source
var ErrInvalidConfig = errors.New("invalid retry configuration")

ErrInvalidConfig is returned when the Retrier configuration is invalid.

Functions ¶

This section is empty.

Types ¶

type Config ¶

type Config struct {
	MaxAttempts int      // Maximum number of retry attempts (must be >= 1)
	Backoff     Strategy // Backoff strategy for calculating delays between retries
}

Config holds retry configuration parameters including attempt limits and backoff behavior.

func (*Config) Validate ¶

func (c *Config) Validate() error

Validate checks if the retry configuration is valid and properly configured.

type ExponentialBackoff ¶

type ExponentialBackoff struct {
	BaseDelay time.Duration // Initial delay for first retry (must be > 0)
	Factor    float64       // Exponential growth factor (must be > 1.0, typically 2.0)
	MaxDelay  time.Duration // Upper limit to prevent excessive delays (must be >= baseDelay)
}

ExponentialBackoff increases delay exponentially with each retry attempt. Starts with baseDelay and multiplies by factor for each retry, capped at maxDelay.

func (*ExponentialBackoff) Next ¶

func (e *ExponentialBackoff) Next(retryCount int) time.Duration

Next calculates exponential delay: baseDelay * factor^retryCount, capped at maxDelay.

func (*ExponentialBackoff) Validate ¶

func (e *ExponentialBackoff) Validate() error

Validate ensures baseDelay is positive, factor enables growth, and maxDelay is reasonable.

type FixedBackoff ¶

type FixedBackoff struct {
	Interval time.Duration // Fixed delay between retries (must be > 0)
}

FixedBackoff applies a constant delay between all retry attempts. Simple strategy that waits the same duration regardless of retry count.

func (*FixedBackoff) Next ¶

func (f *FixedBackoff) Next(retryCount int) time.Duration

Next returns the fixed interval regardless of retry count.

func (*FixedBackoff) Validate ¶

func (f *FixedBackoff) Validate() error

Validate ensures the interval is positive.

type JitterBackoff ¶

type JitterBackoff struct {
	BaseDelay time.Duration // Base delay before adding jitter (must be > 0)
	MaxJitter time.Duration // Maximum random delay to add (must be >= 0)
	// contains filtered or unexported fields
}

JitterBackoff adds randomness to base delay to avoid thundering herd problems. Prevents multiple clients from retrying simultaneously by adding random delays.

func (*JitterBackoff) Next ¶

func (j *JitterBackoff) Next(retryCount int) time.Duration

Next returns base delay plus random jitter up to maxJitter.

func (*JitterBackoff) Validate ¶

func (j *JitterBackoff) Validate() error

Validate ensures baseDelay is positive and maxJitter is non-negative.

type Retrier ¶

type Retrier interface {
	// ExecuteWithRetry attempts to execute a function with retry logic and context support.
	ExecuteWithRetry(ctx context.Context, fn RetryFunc, retryOn RetryOnFunc) error
}

Retrier defines the interface for executing operations with retry logic.

func NewRetrier ¶

func NewRetrier(config Config) (Retrier, error)

NewRetrier creates a new Retrier with the specified configuration. Validates configuration before creating the retrier instance to ensure proper setup.

Parameters:

  • config: Retry configuration with max attempts and backoff strategy

Returns:

  • Retrier: Configured retry instance
  • error: ErrInvalidConfig if configuration is invalid

Example:

backoff, _ := NewFixedBackoffStrategy(2*time.Second)
retrier, err := NewRetrier(Config{
    MaxAttempts: 5,
    Backoff:     backoff,
})
if err != nil {
    log.Fatal("Failed to create retrier:", err)
}

type RetryFunc ¶

type RetryFunc func(ctx context.Context) error

RetryFunc represents a function that can be retried on failure. Should return nil on success or an error on failure that may trigger retry.

Parameters:

  • ctx: Context for cancellation and timeout control

Returns:

  • error: nil on success, error on failure

type RetryOnFunc ¶

type RetryOnFunc func(attempt int, err error) bool

RetryOnFunc determines whether a retry should be attempted based on the attempt and error. Provides flexible control over retry conditions, allowing custom error classification.

Parameters:

  • attempt: Current attempt number
  • err: Error from the failed operation

Returns:

  • bool: true to retry the operation, false to stop and return the error

type Strategy ¶

type Strategy interface {
	// Validate checks if the strategy configuration is valid and properly set up.
	Validate() error

	// Next calculates the delay duration before the next retry attempt.
	Next(retryCount int) time.Duration
}

Strategy defines the interface for backoff delay calculation between retry attempts. Implementations provide different algorithms for calculating wait times based on retry count.

func NewExponentialBackoffStrategy ¶ added in v0.14.0

func NewExponentialBackoffStrategy(baseDelay time.Duration, factor float64, maxDelay time.Duration) (Strategy, error)

NewExponentialBackoffStrategy creates a new exponential backoff strategy with validation. Delay grows exponentially: baseDelay * factor^retryCount, capped at maxDelay.

Parameters:

  • baseDelay: Initial delay duration (must be positive)
  • factor: Exponential multiplier per retry (must be > 1.0, common values: 1.5, 2.0)
  • maxDelay: Maximum delay cap to prevent infinite growth (must be >= baseDelay)

Returns:

  • Strategy: Configured exponential backoff strategy
  • error: Validation error if parameters are invalid

func NewFixedBackoffStrategy ¶ added in v0.14.0

func NewFixedBackoffStrategy(interval time.Duration) (Strategy, error)

NewFixedBackoffStrategy creates a new fixed backoff strategy with validation. Applies the same delay duration for all retry attempts.

Parameters:

  • interval: Fixed delay between retries (must be positive)

Returns:

  • Strategy: Configured fixed backoff strategy
  • error: Validation error if interval is invalid

func NewJitterBackoffStrategy ¶ added in v0.14.0

func NewJitterBackoffStrategy(baseDelay time.Duration, maxJitter time.Duration) (Strategy, error)

NewJitterBackoffStrategy creates a new jitter backoff strategy with validation. Combines base delay with random jitter to prevent synchronized retry attempts.

Parameters:

  • baseDelay: Minimum delay before adding randomness (must be positive)
  • maxJitter: Maximum random delay to add (must be non-negative)

Returns:

  • Strategy: Configured jitter backoff strategy
  • error: Validation error if parameters are invalid

Directories ¶

Path Synopsis
Package retry_mocks is a generated GoMock package.
Package retry_mocks is a generated GoMock package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL