Skip to content

Commit

Permalink
Keep a single retry loop
Browse files Browse the repository at this point in the history
  • Loading branch information
marselester committed Jan 26, 2024
1 parent 55ef27a commit f293697
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 41 deletions.
36 changes: 1 addition & 35 deletions pkg/geoipupdate/database/http_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import (
"strconv"
"time"

"github.com/cenkalti/backoff/v4"

"github.com/maxmind/geoipupdate/v6/pkg/geoipupdate/internal"
"github.com/maxmind/geoipupdate/v6/pkg/geoipupdate/vars"
)
Expand Down Expand Up @@ -71,39 +69,7 @@ func NewHTTPReader(
// It's the responsibility of the Writer to close the io.ReadCloser
// included in the response after consumption.
func (r *HTTPReader) Read(ctx context.Context, editionID, hash string) (*ReadResult, error) {
var result *ReadResult
var err error

// RetryFor value of 0 means that no retries should be performed.
// Max zero retries has to be set to achieve that
// because the backoff never stops if MaxElapsedTime is zero.
exp := backoff.NewExponentialBackOff()
exp.MaxElapsedTime = r.retryFor
b := backoff.BackOff(exp)
if exp.MaxElapsedTime == 0 {
b = backoff.WithMaxRetries(exp, 0)
}
err = backoff.RetryNotify(
func() error {
result, err = r.get(ctx, editionID, hash)
if err == nil {
return nil
}

var httpErr internal.HTTPError
if errors.As(err, &httpErr) && httpErr.StatusCode >= 400 && httpErr.StatusCode < 500 {
return backoff.Permanent(err)
}

return err
},
b,
func(err error, d time.Duration) {
if r.verbose {
log.Printf("Couldn't download %s, retrying in %v: %v", editionID, d, err)
}
},
)
result, err := r.get(ctx, editionID, hash)
if err != nil {
return nil, fmt.Errorf("getting update for %s: %w", editionID, err)
}
Expand Down
12 changes: 6 additions & 6 deletions pkg/geoipupdate/geoip_updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@ package geoipupdate
import (
"context"
"encoding/json"
"errors"
"fmt"
"log"
"os"
"sync"
"time"

"github.com/cenkalti/backoff/v4"
"golang.org/x/net/http2"

"github.com/maxmind/geoipupdate/v6/pkg/geoipupdate/database"
"github.com/maxmind/geoipupdate/v6/pkg/geoipupdate/internal"
Expand Down Expand Up @@ -147,14 +145,16 @@ func (c *Client) downloadEdition(
var edition *database.ReadResult
err = backoff.RetryNotify(
func() error {
edition, err = r.Read(ctx, editionID, editionHash)
if err != nil {
if edition, err = r.Read(ctx, editionID, editionHash); err != nil {
if internal.IsTemporaryError(err) {
return err
}

return backoff.Permanent(err)
}

if err = w.Write(edition); err != nil {
streamErr := http2.StreamError{}
if errors.As(err, &streamErr) && streamErr.Code == http2.ErrCodeInternal {
if internal.IsTemporaryError(err) {
return err
}

Expand Down
19 changes: 19 additions & 0 deletions pkg/geoipupdate/internal/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
package internal

import (
"errors"
"fmt"

"golang.org/x/net/http2"
)

// HTTPError is an error from performing an HTTP request.
Expand All @@ -14,3 +17,19 @@ type HTTPError struct {
func (h HTTPError) Error() string {
return fmt.Sprintf("received HTTP status code: %d: %s", h.StatusCode, h.Body)
}

// IsTemporaryError returns true if the error is temporary.
func IsTemporaryError(err error) bool {
var httpErr HTTPError
if errors.As(err, &httpErr) {
isPermanent := httpErr.StatusCode >= 400 && httpErr.StatusCode < 500
return !isPermanent
}

var streamErr http2.StreamError
if errors.As(err, &streamErr) && streamErr.Code == http2.ErrCodeInternal {
return true
}

return false
}

0 comments on commit f293697

Please sign in to comment.