chore(influxv2plugin): Increase accepted retry-after header values. (#9619)
This commit is contained in:
parent
8e8074e47b
commit
8daba8aa19
|
|
@ -36,8 +36,9 @@ func (e APIError) Error() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultRequestTimeout = time.Second * 5
|
defaultRequestTimeout = time.Second * 5
|
||||||
defaultMaxWait = 60 // seconds
|
defaultMaxWaitSeconds = 60
|
||||||
|
defaultMaxWaitRetryAfterSeconds = 10 * 60
|
||||||
)
|
)
|
||||||
|
|
||||||
type HTTPConfig struct {
|
type HTTPConfig struct {
|
||||||
|
|
@ -306,8 +307,9 @@ func (c *httpClient) writeBatch(ctx context.Context, bucket string, metrics []te
|
||||||
// retryDuration takes the longer of the Retry-After header and our own back-off calculation
|
// retryDuration takes the longer of the Retry-After header and our own back-off calculation
|
||||||
func (c *httpClient) getRetryDuration(headers http.Header) time.Duration {
|
func (c *httpClient) getRetryDuration(headers http.Header) time.Duration {
|
||||||
// basic exponential backoff (x^2)/40 (denominator to widen the slope)
|
// basic exponential backoff (x^2)/40 (denominator to widen the slope)
|
||||||
// at 40 denominator, it'll take 35 retries to hit the max defaultMaxWait of 30s
|
// at 40 denominator, it'll take 49 retries to hit the max defaultMaxWait of 60s
|
||||||
backoff := math.Pow(float64(c.retryCount), 2) / 40
|
backoff := math.Pow(float64(c.retryCount), 2) / 40
|
||||||
|
backoff = math.Min(backoff, defaultMaxWaitSeconds)
|
||||||
|
|
||||||
// get any value from the header, if available
|
// get any value from the header, if available
|
||||||
retryAfterHeader := float64(0)
|
retryAfterHeader := float64(0)
|
||||||
|
|
@ -319,11 +321,12 @@ func (c *httpClient) getRetryDuration(headers http.Header) time.Duration {
|
||||||
// there was a value but we couldn't parse it? guess minimum 10 sec
|
// there was a value but we couldn't parse it? guess minimum 10 sec
|
||||||
retryAfterHeader = 10
|
retryAfterHeader = 10
|
||||||
}
|
}
|
||||||
|
// protect against excessively large retry-after
|
||||||
|
retryAfterHeader = math.Min(retryAfterHeader, defaultMaxWaitRetryAfterSeconds)
|
||||||
}
|
}
|
||||||
// take the highest value from both, but not over the max wait.
|
// take the highest value of backoff and retry-after.
|
||||||
retry := math.Max(backoff, retryAfterHeader)
|
retry := math.Max(backoff, retryAfterHeader)
|
||||||
retry = math.Min(retry, defaultMaxWait)
|
return time.Duration(retry*1000) * time.Millisecond
|
||||||
return time.Duration(retry) * time.Second
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *httpClient) makeWriteRequest(url string, body io.Reader) (*http.Request, error) {
|
func (c *httpClient) makeWriteRequest(url string, body io.Reader) (*http.Request, error) {
|
||||||
|
|
|
||||||
|
|
@ -56,12 +56,12 @@ func TestExponentialBackoffCalculation(t *testing.T) {
|
||||||
expected time.Duration
|
expected time.Duration
|
||||||
}{
|
}{
|
||||||
{retryCount: 0, expected: 0},
|
{retryCount: 0, expected: 0},
|
||||||
{retryCount: 1, expected: 0},
|
{retryCount: 1, expected: 25 * time.Millisecond},
|
||||||
{retryCount: 5, expected: 0},
|
{retryCount: 5, expected: 625 * time.Millisecond},
|
||||||
{retryCount: 10, expected: 2 * time.Second},
|
{retryCount: 10, expected: 2500 * time.Millisecond},
|
||||||
{retryCount: 30, expected: 22 * time.Second},
|
{retryCount: 30, expected: 22500 * time.Millisecond},
|
||||||
{retryCount: 40, expected: 40 * time.Second},
|
{retryCount: 40, expected: 40 * time.Second},
|
||||||
{retryCount: 50, expected: 60 * time.Second},
|
{retryCount: 50, expected: 60 * time.Second}, // max hit
|
||||||
{retryCount: 100, expected: 60 * time.Second},
|
{retryCount: 100, expected: 60 * time.Second},
|
||||||
{retryCount: 1000, expected: 60 * time.Second},
|
{retryCount: 1000, expected: 60 * time.Second},
|
||||||
}
|
}
|
||||||
|
|
@ -72,3 +72,29 @@ func TestExponentialBackoffCalculation(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestExponentialBackoffCalculationWithRetryAfter(t *testing.T) {
|
||||||
|
c := &httpClient{}
|
||||||
|
tests := []struct {
|
||||||
|
retryCount int
|
||||||
|
retryAfter string
|
||||||
|
expected time.Duration
|
||||||
|
}{
|
||||||
|
{retryCount: 0, retryAfter: "0", expected: 0},
|
||||||
|
{retryCount: 0, retryAfter: "10", expected: 10 * time.Second},
|
||||||
|
{retryCount: 0, retryAfter: "60", expected: 60 * time.Second},
|
||||||
|
{retryCount: 0, retryAfter: "600", expected: 600 * time.Second},
|
||||||
|
{retryCount: 0, retryAfter: "601", expected: 600 * time.Second}, // max hit
|
||||||
|
{retryCount: 40, retryAfter: "39", expected: 40 * time.Second}, // retryCount wins
|
||||||
|
{retryCount: 40, retryAfter: "41", expected: 41 * time.Second}, // retryAfter wins
|
||||||
|
{retryCount: 100, retryAfter: "100", expected: 100 * time.Second},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(fmt.Sprintf("%d_retries", test.retryCount), func(t *testing.T) {
|
||||||
|
c.retryCount = test.retryCount
|
||||||
|
hdr := http.Header{}
|
||||||
|
hdr.Add("Retry-After", test.retryAfter)
|
||||||
|
require.EqualValues(t, test.expected, c.getRetryDuration(hdr))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue