Skip to content

Commit

Permalink
feat: setup backoff retry strategy
Browse files Browse the repository at this point in the history
Signed-off-by: rare-magma <rare-magma@posteo.eu>
  • Loading branch information
rare-magma committed Jan 19, 2025
1 parent 320e0f2 commit 6dcdb8b
Showing 1 changed file with 54 additions and 9 deletions.
63 changes: 54 additions & 9 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"fmt"
"io"
"log"
"net"
"math"
"net/http"
"os"
"time"
Expand Down Expand Up @@ -39,6 +39,52 @@ type Config struct {
Org string `json:"Org"`
}

type retryableTransport struct {
transport http.RoundTripper
TLSHandshakeTimeout time.Duration
ResponseHeaderTimeout time.Duration
}

const retryCount = 3

func shouldRetry(err error, resp *http.Response) bool {
if err != nil {
return true
}
switch resp.StatusCode {
case http.StatusInternalServerError, http.StatusBadGateway, http.StatusServiceUnavailable, http.StatusGatewayTimeout:
return true
default:
return false
}
}

func (t *retryableTransport) RoundTrip(req *http.Request) (*http.Response, error) {
var bodyBytes []byte
if req.Body != nil {
bodyBytes, _ = io.ReadAll(req.Body)
req.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
}
resp, err := t.transport.RoundTrip(req)
retries := 0
for shouldRetry(err, resp) && retries < retryCount {
backoff := time.Duration(math.Pow(2, float64(retries))) * time.Second
time.Sleep(backoff)
if resp.Body != nil {
io.Copy(io.Discard, resp.Body)
resp.Body.Close()
}
if req.Body != nil {
req.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
}
log.Printf("Previous request failed with %s", resp.Status)
log.Printf("Retry %d of request to: %s", retries+1, req.URL)
resp, err = t.transport.RoundTrip(req)
retries++
}
return resp, err
}

func main() {
confFilePath := "pvpc_exporter.json"
confData, err := os.Open(confFilePath)
Expand Down Expand Up @@ -68,15 +114,14 @@ func main() {
flag.IntVar(&days, "days", 0, "Number of days in the past to fetch")
flag.Parse()

transport := &retryableTransport{
transport: &http.Transport{},
TLSHandshakeTimeout: 30 * time.Second,
ResponseHeaderTimeout: 30 * time.Second,
}
client := &http.Client{
Timeout: 30 * time.Second,
Transport: &http.Transport{
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
}).DialContext,
TLSHandshakeTimeout: 30 * time.Second,
ResponseHeaderTimeout: 30 * time.Second,
},
Timeout: 30 * time.Second,
Transport: transport,
}

date := time.Now().AddDate(0, 0, -days).Format("2006-01-02")
Expand Down

0 comments on commit 6dcdb8b

Please sign in to comment.