Resilient wrapper around Go http.Client that uses exponential backoff and jitter for retries.

Hardy

Hardy is a very simple wrapper around http.Client that enables you to add more resilience and reliability for your HTTP calls through retries. As retry strategy, Hardy will use the exponential algorithm and jitter to ensure that our services doesn't cause total outage to their dependencies.

You can read more:

Usage

Install

go get github.com/diegohordi/hardy

Creating the client

In order to create the Hardy client you will need to provide a http.Client and a log.Logger instances. If no log.Logger instance was given, the log will be disabled.

Additional parameters:

  • WithMaxRetries - will determine how many retries should be attempted.
  • WithWaitInterval - will define the base duration between each retry.
  • WithMultiplier - the multiplier that should be used to calculate the backoff interval. Should be greater than the hardy.DefaultMultiplier.
  • WithMaxInterval - the max interval between each retry. If no one was given, the interval between each retry will grow exponentially.
httpClient := &http.Client{Timeout: 3 * time.Second}
client := hardy.NewClient(httpClient, log.Default()).
		    WithMaxRetries(4).
		    WithWaitInterval(3 * time.Millisecond).
		    WithMultiplier(hardy.DefaultMultiplier).
		    WithMaxInterval(3 * time.Second)

Using the client

The wrapper adds the method Try(context.Context, *http.Request, hardy.ReaderFunc, hardy.FallbackFunc), which receives:

  • context.Context a proper context to the request, mandatory. Hardy is also enabled to deal with context deadline/cancellation.
  • *http.Request an instance of the request that should be performed, mandatory.
  • hardy.ReaderFunc a reader function, mandatory, that will be responsible to handle each request result.
  • hardy.FallbackFunc a fallback function that will be called if all retries fail, optional.

hardy.ReaderFunc

The ReaderFunc defines the function responsible to read the HTTP response and also determines if a new retry must be performed returning an error or not, returning nil.

Keep in mind while writing your reader function that we shouldn't perform a retry if the response contains an error due to a client error (400-499 HTTP error codes), but consider only the ones not caused by them instead, as 500 and 503 HTTP error codes, for instance.

Example


type TestService struct {
	Client *hardy.Client
}

func (s *TestService) GetHelloMessage(ctx context.Context, name string) (string, error) {
	if s.Client == nil {
		return "", fmt.Errorf("no client was given")
	}
	var helloMessage string
	request, err := http.NewRequest(http.MethodGet, "https://httpbin.org/status/500,200,300", nil)
	if err != nil {
		return "", err
	}
	readerFunc := func(message *string) hardy.ReaderFunc {
		return func(response *http.Response) error {
			if response.StatusCode == http.StatusOK {
				*message = fmt.Sprintf("hello from reader, %s!", name)
				return nil
			}
			return fmt.Errorf(response.Status)
		}
	}
	fallbackFunc := func(message *string) hardy.FallbackFunc {
		return func() error {
			*message = fmt.Sprintf("hello from fallback, %s!", name)
			return nil
		}
	}
	err = s.Client.Try(ctx, request, readerFunc(&helloMessage), fallbackFunc(&helloMessage))
	if err != nil {
		return "", err
	}
	return helloMessage, nil
}

...

httpClient := &http.Client{Timeout: 3 * time.Second}
client := hardy.NewClient(httpClient, log.Default()).
		WithMaxRetries(4).
		WithWaitInterval(3 * time.Millisecond).
		WithMultiplier(hardy.DefaultMultiplier).
		WithMaxInterval(3 * time.Second)
testService := &TestService{Client: client}

msg, err := testService.GetHelloMessage(ctx, tt.args.name)

Tests

The coverage so far is greater than 90%, covering also failure scenarios. Also, there are no race conditions detected in the -race tests.

You can run the tests and the benchmark from Makefile, as below:

Test

make test

Benchmarks

make benchmark

TODO

  • Improve logs
Similar Resources

Official provider for VMware desktop products: Fusion, Player, and Workstation.

Vagrant VMware Desktop Providers This is the common codebase for the official providers for VMware desktop products: Fusion, Player, and Workstation.

Jan 7, 2023

A complete guide to undersatnd golang programming language, web requests, JSON and creating web APIs with mongodb

Golang series A complete guide to undersatnd golang programming language, web requests, JSON and creating web APIs with mongodb LearnCodeonline.in 01

Jan 1, 2023

Golang Clean Architecture based on Uncle Bob's Clean Architecture and Summer internship in 2021

clean-architecture-api Description This is an example of implemention of Clean Architecture in Golang projects. This project has 4 layer : Infrastruct

Feb 20, 2022

Learning and Practice - Go Lang

Go Lang - Learning and Practice All the code stored here is provided by Tour of Go Basics Packages, variables, and functions Flow control statements:

Jan 14, 2022

Comparison of Pixel and Ebiten API on the trees tutorial

Rewriting the trees tutorial of Pixel with Ebiten for API comparison I tried Pixel and really liked the clean API but the dev seems to be on pause sin

Dec 7, 2021

Example skills and a cli utility written in Go for interacting with Webex Assistant Skills

Webex Assistant Skills - Go This repository holds example skills and a cli utility written in Go for interacting with Webex Assistant Skills. It is in

Oct 29, 2021

Cook amazing genetic parts using our cookbook. Recipes and synthetic biology tools to take your breath away.

friendzymes-cookbook Friendly tools for a friendly community. A collection of tutorials and genetic tools for synthetic biology. This cookbook is a su

Aug 19, 2022

A go blog demo by gin and gorm!

A go blog demo by gin and gorm!

Dec 7, 2022

This is an example of a keep-it-simple directory layout for Go projects that was created using DDD principles, please copy and share if you like it.

DDD Go Template This project was created to illustrate a great architectural structure I developed together with @fabiorodrigues in the period I was w

Dec 5, 2022
Simple Notifier/Listener utility package to pass around messages in-memory

Simple Observer (go) A small simple library to use for sending around messages in-memory. It uses a notifier/listener style messaging. Installation go

Dec 7, 2021
Patternfinder - Find patterns in http output based on regex string. Display occurences

Patternfinder Find patterns in HTTP output based on regex string. Display occurr

Feb 18, 2022
Client-go examples
Client-go examples

client-go examples 参考 k8s-client-go kube-client-example client-go 实战的文章、 client-go 实战的代码 client-go/example Kubernetes API Reference Docs 关于 Group、Vers

Sep 16, 2022
Tool (in Go!) to compare and diff container and host environments. Dinosaur fun!

Compe compare environments and other things between containers, and host ??️ This is a simple tool to compare environments and other features of conta

Sep 24, 2022
Go Cheat Sheet - An overview of Go syntax and features.

Go Cheat Sheet - An overview of Go syntax and features.

Dec 31, 2022
An online book focusing on Go syntax/semantics and runtime related things

Go 101 is a book focusing on Go syntax/semantics and all kinds of runtime related things. It tries to help gophers gain a deep and thorough understanding of Go. This book also collects many details of Go and in Go programming. The book is expected to be helpful for both beginner and experienced Go programmers.

Dec 29, 2022
This slide deck and supporting material is part of the Introduction to Go training course by Dave Cheney

This slide deck and supporting material is part of the Introduction to Go training course by Dave Cheney.

Nov 14, 2022
📖 Build a RESTful API on Go: Fiber, PostgreSQL, JWT and Swagger docs in isolated Docker containers.
📖 Build a RESTful API on Go: Fiber, PostgreSQL, JWT and Swagger docs in isolated Docker containers.

?? Tutorial: Build a RESTful API on Go Fiber, PostgreSQL, JWT and Swagger docs in isolated Docker containers. ?? The full article is published on Marc

Dec 27, 2022
Assert your Go code is inlined and bounds-check eliminated

gcassert gcassert is a program for making assertions about compiler decisions in Golang programs, via inline comment directives like //gcassert:inline

Oct 27, 2022
1000+ Hand-Crafted Go Examples, Exercises, and Quizzes

A Huge Number of Go Examples, Exercises and Quizzes Best way of learning is doing. Inside this repository, you will find thousands of Go examples, exe

Jan 1, 2023