• Explore
  • About Us
  • Log In
  • Get Started
  • Explore
  • About Us
  • Log In
  • Get Started

Resilient Retry Mechanism with Exponential Backoff

In this exercise, you are working on a Golang service that interacts with unreliable external APIs. Often, network issues or temporary failures cause operations to fail. Your task is to implement a retry mechanism that attempts the operation multiple times with an exponential backoff strategy. The system should log each attempt, including the error and the delay before the next retry, until the operation succeeds or the maximum number of retries is reached. This realistic scenario will help you master error handling and improve the robustness of your applications.

Requirements

  • Create a function unreliableOperation that simulates an operation which fails most of the time, but can succeed occasionally.
  • Implement a function retryOperation that calls unreliableOperation and retries on failure using an exponential backoff strategy.
  • Allow configuration for the maximum number of retries and the initial delay duration.
  • On each attempt, log the attempt number, the error encountered (if any), and the waiting time before the next attempt.
  • If the operation succeeds within the allowed number of retries, print a success message along with the attempt number.
  • If the operation continues to fail and reaches the maximum retries, print a failure message and exit the retry loop.
  • Ensure the code follows Go best practices and is well structured for maintainability.

Expected output

When running the program, the output should log each attempt as follows:

[ATTEMPT 1] Operation failed: simulated error. Retrying in 1s...
[ATTEMPT 2] Operation failed: simulated error. Retrying in 2s...
[ATTEMPT 3] Operation succeeded on attempt 3.
[INFO] Operation completed successfully.

If the operation fails after all retries:

[ATTEMPT 1] Operation failed: simulated error. Retrying in 1s...
[ATTEMPT 2] Operation failed: simulated error. Retrying in 2s...
[ATTEMPT 3] Operation failed: simulated error. Retrying in 4s...
[ATTEMPT 4] Operation failed: simulated error. Retrying in 8s...
[ATTEMPT 5] Operation failed: simulated error. No more retries left.
[ERROR] Operation failed after maximum retries.

Program Structure

Project structure should look like this:

.
├── go.mod
└── main.go

Your program should have the following structure and implement these functions:

main.go

package main

import (
	"errors"
	"fmt"
	"math/rand"
	"time"
)

// unreliableOperation simulates an operation that may fail.
// It randomly succeeds or fails.
func unreliableOperation() error {
	// Simulate operation failure. Replace this with actual logic.
	// For example, succeed 30% of the time.
	
}

// retryOperation implements a retry mechanism with exponential backoff.
// It retries the unreliableOperation until success or maximum retries are reached.
func retryOperation(maxRetries int, initialDelay time.Duration) {
	
}

func main() {

	maxRetries := 5
	initialDelay := 1 * time.Second

	retryOperation(maxRetries, initialDelay)
}

Acceptance Criteria

  • The retry mechanism must call unreliableOperation and retry on failure.
  • The delay between retries must double after each attempt (exponential backoff).
  • The program must log each attempt with the attempt number, error message, and delay duration.
  • The operation should succeed if it eventually returns nil within the allowed number of retries.
  • If the maximum retries are reached without success, the program must log a failure message.

Hints

  • Use time.Sleep to introduce delays between retries.
  • Use a loop to implement retry logic.
  • Multiply the delay by 2 after each failed attempt to achieve exponential backoff.
  • Use a counter or random function to simulate operation success or failure.
  • Write clear and concise log messages for each attempt.

    Golang (Go) for Production Systems

    Unlock All Exercises

  • Getting Started
    • Important - Please Read
  • Error Handling
    • Finance Transaction Error
    • Resilient Retry Mechanism
    • Graceful Panic Recovery
    • Error Wrapping and Unwrapping
    • Aggregated Validation Errors
    • Transaction Rollback on Failure
  • Interfaces
    • Design a Payment Gateway Interface
    • Pluggable Logging System
    • Configurable Notification System
    • Dynamic Data Serializer
    • Dynamic Plugin System
  • Concurrency
    • File Word Counter
    • Traffic Lights Controller
    • Parking Lot Manager
    • Real-time Auction System
    • Safe Bank Account Balance Update
    • Build a Buffered Logger
    • Build a TTL Cache
    • Build an Elevator Control System
    • Debug and Fix Race Conditions - Part 1
    • Debug and Fix Race Conditions - Part 2
    • Debug and Fix Race Conditions - Part 3
    • Dynamic Feature Flag System
    • Real-Time Multiplayer Matchmaking
    • Lazy Database Connection
    • Distributed Task Deduplication
    • High Performance Request Counter
  • Core Networking
    • Simple TCP Echo Server
    • TCP Number Guessing Game
    • Looking Up Domain Information
    • UDP Time Broadcast Service
    • UDP Ping-Pong Client and Server
    • Building a Simple TCP Chat Server and Client
  • Winding Up
    • Final Notes