Coder Social home page Coder Social logo

hyp3rd / go-again Goto Github PK

View Code? Open in Web Editor NEW
3.0 1.0 0.0 59 KB

`go-again` is an high-performance and thread-safe retry library with fine-grained access to the configuration options.

License: Mozilla Public License 2.0

Makefile 4.88% Go 95.12%
go retry retry-fuctions retry-library retryer

go-again's Introduction

go-again

Go CodeQL Codacy Security Scan

go-again thread safely wraps a given function and executes it until it returns a nil error or exceeds the maximum number of retries. The configuration consists of the maximum number of retries, the interval, a jitter to add a randomized backoff, the timeout, and a registry to store errors that you consider temporary, hence worth a retry.

The Do method takes a context, a function, and an optional list of temporary errors as arguments. It supports cancellation from the context and a channel invoking the Cancel() function. The returned type is Errors which contains the list of errors returned at each attempt and the last error returned by the function.

// Errors holds the error returned by the retry function along with the trace of each attempt.
type Errors struct {
    // Retries hold the trace of each attempt.
    Retries map[int]error
    // Last holds the last error returned by the retry function.
    Last error
}

The registry only allows you to retry a function if it returns a registered error:

    // Init with defaults.
    retrier, err := again.NewRetrier()
    if err != nil {
        // handle error
    }
    retrier.Registry.RegisterTemporaryError("http.ErrAbortHandler", func() TemporaryError {
        return http.ErrAbortHandler
    })

    defer retrier.Registry.UnRegisterTemporaryError("http.ErrAbortHandler")
    var retryCount int
    errs := retrier.Do(context.TODO(), func() error {
        retryCount++
        if retryCount < 3 {
            return http.ErrAbortHandler
        }
        return nil
    }, "http.ErrAbortHandler")

    if errs.Last != nil {
        // handle error
    }

Should you retry regardless of the error returned, that's easy. It's enough calling the Do function without passing a plausible set of registered error names:

    var retryCount int
    retrier, err := again.NewRetrier(again.WithTimeout(1*time.Second),
        again.WithJitter(500*time.Millisecond),
        again.WithMaxRetries(3))

    if err != nil {
        // handle error
    }
    errs := retrier.Do(context.TODO(), func() error {
        retryCount++
        if retryCount < 3 {
            return http.ErrAbortHandler
        }
        return nil
    })
    if errs.Last != nil {
        // handle error
    }

It's also possible to create a Registry with the temporary default errors: retrier.Registry.LoadDefaults(). You can extend the list with your errors by calling the RegisterTemporaryError method.

Walk through the documentation for further details about the settings, the programmability, the implementation.

Performance

A retrier certainly adds overhead to the execution of a function. go-again is designed to produce a minimal impact on the performance of your code, keeping thread safety and flexibility. The following benchmark shows the overhead of a retrier with 5 retries, 1s interval, 10ms jitter, and 1s timeout:

go test -bench=. -benchmem -benchtime=4s . -timeout 30m
goos: darwin
goarch: amd64
pkg: github.com/hyp3rd/go-again
cpu: Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
BenchmarkRetry-16         490851          8926 ns/op        5376 B/op          1 allocs/op
PASS
ok      github.com/hyp3rd/go-again  40.390s

Installation

go get github.com/hyp3rd/go-again

Usage

For examples with cancellation, see examples. To run the examples you can leverage the Makefile:

make run example=chan
make run example=context

Retrier

package main

import (
    "fmt"
    "time"

    "github.com/hyp3rd/go-again"
)

func main() {
    // Create a new retrier.
    retrier, err := again.NewRetrier(again.WithTimeout(1*time.Second),
        again.WithJitter(500*time.Millisecond),
        again.WithMaxRetries(3))

    if err != nil {
        // handle error
    }

    // Register a temporary error.
    retrier.Registry.RegisterTemporaryError("temporary error", func() again.TemporaryError {
        return fmt.Errorf("temporary error")
    })

    // Retry a function.
    errs := retrier.Do(context.TODO(), func() error {
        // Do something here.
        return fmt.Errorf("temporary error")
    }, "temporary error")
    if errs.Last != nil {
        fmt.Println(err)
    }
}

License

The code and documentation in this project are released under Mozilla Public License 2.0.

Author

I'm a surfer, a crypto trader, and a software architect with 15 years of experience designing highly available distributed production environments and developing cloud-native apps in public and private clouds. Feel free to hook me up on LinkedIn.

go-again's People

Contributors

hyp3rd avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar

go-again's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.