Gists a3f9c1d27b8e

Go retry helper with jitter

M mkappworks Public
Edit

retry.go

25 lines · 0.5 KB
package retry

import (
	"context"
	"math/rand"
	"time"
)

// Do calls fn until it succeeds, the attempts run out, or ctx is done.
func Do(ctx context.Context, attempts int, base time.Duration, fn func() error) error {
	var err error
	for i := 0; i < attempts; i++ {
		if err = fn(); err == nil {
			return nil
		}
		jitter := time.Duration(rand.Int63n(int64(base)))
		select {
		case <-ctx.Done():
			return ctx.Err()
		case <-time.After(base<<i + jitter):
		}
	}
	return err
}

retry_test.go

20 lines · 0.3 KB
package retry_test

import (
	"context"
	"errors"
	"testing"
	"time"
)

func TestDoGivesUp(t *testing.T) {
	calls := 0
	err := Do(context.Background(), 3, time.Millisecond, func() error {
		calls++
		return errors.New("boom")
	})
	if err == nil || calls != 3 {
		t.Fatalf("calls=%d err=%v", calls, err)
	}
}