There's a bunch of excellent retry-related Go libraries out there (and I took inspiration from some of them), like this one. Some of them are highly configurable (even more configurable than mine), but I was always lacking one feature: configurability by the error. I.e., most of the libraries allow you to configure the "retrier" in some or another way, making it behave the same way for all the "retriable" errors. What I needed for some of my usecases, is having different retry strategies for different errors. And that's why this library was made.
So, let's say we have a DB-related function that may return different types of errors: it returns sql.ErrNoRows
if the result-set of the lookup is empty, and it returns driver.ErrBadConn
if there's some trasient connectivity error. In the first case, I want to retry with the constant rate (let's say, every second
) and the maximum retry count of 3
. In the second case, I want to have an exponential back-off starting with 10 milliseconds
, but the retry delay should not exceed 1 second
. All together, I want the retry phase to not exceed 5 seconds
. Here's how one could implement it using the retro
library:
caller := NewCaller(). // instantiating the "retrier" aka "caller"
WithRetriableError(sql.ErrNoRows,
NewBackoffStrategy(NewConstant(1), time.Second).
WithMaxRetries(3)). // constant back-off at the rate of 1 second and 3 max retries for sql.ErrNoRows
WithRetriableError(driver.ErrBadConn,
NewBackoffStrategy(NewExponential(2), time.Millisecond).
WithCappedDuration(time.Second)). // exponential back-off with factor 2, 1 millisecond time unit and max retry delay of 1 second
WithMaxDuration(5 * time.Second) // maximum retry duration (across all retriable errors) - 5 seconds
if err := caller.Call(context.TODO(), func() error {
return queryDBFunction(...) // your function that runs a database query
}); err != nil {
panic(err)
}
You can also specify a retry startegy for any erro using WithRetryOnAnyError(...)
on the caller.
Please, take a look at the unit-tests for more examples.