I am using the https://pkg.go.dev/github.com/sethvargo/go-retry package to make retry attempts on the GitHub API server from my application. The package is the simplest of the lot, that assists in making retry attempts of a web API call.
The issue that is bugging me is the RetryFunc
in https://pkg.go.dev/github.com/sethvargo/go-retry#RetryFunc takes a closure of the form
type RetryFunc func(ctx context.Context) error
I have a lot of GitHub APIs wrapped around this retry logic, with varying number of arguments.
Sample code below
func retryDecision(resp *github.Response) error {
if resp.StatusCode == 0 || (resp.StatusCode >= 500 && resp.StatusCode != http.StatusNotImplemented) {
return retry.RetryableError(fmt.Errorf("unexpected HTTP status %s", resp.Status))
}
return nil
}
func retryWithExpBackoff(ctx context.Context, f func(ctx context.Context) error) error {
b := retry.NewExponential(1 * time.Second)
b = retry.WithMaxRetries(5, b)
b = retry.WithMaxDuration(5*time.Second, b)
return retry.Do(ctx, b, f)
}
func NewGitHubClient(ctx context.Context, token, repo string) (*github.Client, error) {
r := strings.Split(repo, "/")
client := github.NewClient(nil).WithAuthToken(token)
if err := retryWithExpBackoff(ctx, func(ctx context.Context) error {
_, resp, err := client.Repositories.Get(ctx, r[0], r[1])
if retryErr := retryDecision(resp); retryErr != nil {
return retryErr
}
return err
}); err != nil {
return nil, err
}
return client, nil
}
I end up nesting calls like below for each of the API that I’m implementing with retry, i.e. this part of code is repeating in each of the APIs I plan to implement
if err := retryWithExpBackoff(ctx, func(ctx context.Context) error {
_, resp, err := client.Repositories.Get(ctx, r[0], r[1])
if retryErr := retryDecision(resp); retryErr != nil {
return retryErr
}
return err
}); err != nil {
return nil, err
}
How can I re-write this to make the retryWithExpBackoff
take any API that I plan to implement, but adopt a retry mechanism?
The GitHub API referenced in the code is from https://pkg.go.dev/github.com/google/go-github/v61/github