diff options
author | Cory Cooper <coopercory92@gmail.com> | 2022-10-05 21:34:49 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-05 22:34:49 -0600 |
commit | 498f32bab96ba00e1a7d04c6bc8b367c97d8a335 (patch) | |
tree | 14554ad81d2559a219bcc384de2bd5ed55929bd8 | |
parent | ed118f2b0900e6416ef202afb0f79caeae4fddcb (diff) |
caddyconfig: Implement retries into HTTPLoader (#5077)
* httploader: Add max_retries
* caddyconfig: dependency-free http config loading retries
* caddyconfig: support `retry_delay` in http loader
* httploader: Implement retries
* Apply suggestions from code review
Co-authored-by: Matt Holt <mholt@users.noreply.github.com>
Co-authored-by: Matt Holt <mholt@users.noreply.github.com>
-rw-r--r-- | caddyconfig/httploader.go | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/caddyconfig/httploader.go b/caddyconfig/httploader.go index 80eab44..f199219 100644 --- a/caddyconfig/httploader.go +++ b/caddyconfig/httploader.go @@ -94,7 +94,7 @@ func (hl HTTPLoader) LoadConfig(ctx caddy.Context) ([]byte, error) { } } - resp, err := client.Do(req) + resp, err := doHttpCallWithRetries(ctx, client, req) if err != nil { return nil, err } @@ -119,6 +119,37 @@ func (hl HTTPLoader) LoadConfig(ctx caddy.Context) ([]byte, error) { return result, nil } +func attemptHttpCall(client *http.Client, request *http.Request) (*http.Response, error) { + resp, err := client.Do(request) + if err != nil { + return nil, fmt.Errorf("problem calling http loader url: %v", err) + } else if resp.StatusCode < 200 || resp.StatusCode > 499 { + return nil, fmt.Errorf("bad response status code from http loader url: %v", resp.StatusCode) + } + return resp, nil +} + +func doHttpCallWithRetries(ctx caddy.Context, client *http.Client, request *http.Request) (*http.Response, error) { + var resp *http.Response + var err error + const maxAttempts = 10 + + // attempt up to 10 times + for i := 0; i < maxAttempts; i++ { + resp, err = attemptHttpCall(client, request) + if err != nil && i < maxAttempts-1 { + // wait 500ms before reattempting, or until context is done + select { + case <-time.After(time.Millisecond * 500): + case <-ctx.Done(): + return resp, ctx.Err() + } + } + } + + return resp, err +} + func (hl HTTPLoader) makeClient(ctx caddy.Context) (*http.Client, error) { client := &http.Client{ Timeout: time.Duration(hl.Timeout), |