Skip to content

Commit

Permalink
Merge pull request #216 from tjhop/fix/no-retries-in-maintenance-mode
Browse files Browse the repository at this point in the history
fix: don't retry requests during API maintenance events
  • Loading branch information
LBGarber authored Sep 10, 2021
2 parents ab5afcc + 8bc2a55 commit 76e9a77
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 2 deletions.
17 changes: 15 additions & 2 deletions retries.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import (
"github.com/go-resty/resty/v2"
)

const retryAfterHeaderName = "Retry-After"
const (
retryAfterHeaderName = "Retry-After"
maintenanceModeHeaderName = "X-Maintenance-Mode"
)

// type RetryConditional func(r *resty.Response) (shouldRetry bool)
type RetryConditional resty.RetryConditionFunc
Expand Down Expand Up @@ -54,7 +57,17 @@ func tooManyRequestsRetryCondition(r *resty.Response, _ error) bool {
}

func serviceUnavailableRetryCondition(r *resty.Response, _ error) bool {
return r.StatusCode() == http.StatusServiceUnavailable
serviceUnavailable := r.StatusCode() == http.StatusServiceUnavailable

// During maintenance events, the API will return a 503 and add
// an `X-MAINTENANCE-MODE` header. Don't retry during maintenance
// events, only for legitimate 503s.
if serviceUnavailable && r.Header().Get(maintenanceModeHeaderName) != "" {
log.Printf("[INFO] Linode API is under maintenance, request will not be retried - please see status.linode.com for more information")
return false
}

return serviceUnavailable
}

func requestTimeoutRetryCondition(r *resty.Response, _ error) bool {
Expand Down
16 changes: 16 additions & 0 deletions retries_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,19 @@ func TestLinodeServiceUnavailableRetryCondition(t *testing.T) {
t.Errorf("expected retryAfter to be 20 but got %d", retryAfter)
}
}

func TestLinodeServiceMaintenanceModeRetryCondition(t *testing.T) {
request := resty.Request{}
rawResponse := http.Response{StatusCode: http.StatusServiceUnavailable, Header: http.Header{
retryAfterHeaderName: []string{"20"},
maintenanceModeHeaderName: []string{"Currently in maintenance mode."},
}}
response := resty.Response{
Request: &request,
RawResponse: &rawResponse,
}

if retry := serviceUnavailableRetryCondition(&response, nil); retry {
t.Error("expected retry to be skipped due to maintenance mode header")
}
}

0 comments on commit 76e9a77

Please sign in to comment.