-
Notifications
You must be signed in to change notification settings - Fork 5
/
retry.go
84 lines (70 loc) · 1.81 KB
/
retry.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// Copyright (c) 2022 AccelByte Inc. All Rights Reserved.
// This is licensed software from AccelByte Inc, for limitations
// and restrictions contact your company contract manager.
package utils
import (
"net/http"
"time"
)
type PersistentRoundTripper interface {
ShouldRetry(req *http.Request, res *http.Response, attempts int, elapsed time.Duration) bool
http.RoundTripper
}
type DefaultPersistentRoundTripper struct {
MaxAttempts *int
MaxElapsed *time.Duration
internalRoundTripper http.RoundTripper
}
func NewDefaultPersistentRoundTripper(maxAttempts *int, maxElapsed *time.Duration, internalRoundTripper http.RoundTripper) DefaultPersistentRoundTripper {
return DefaultPersistentRoundTripper{
MaxAttempts: maxAttempts,
MaxElapsed: maxElapsed,
internalRoundTripper: internalRoundTripper,
}
}
func (rt DefaultPersistentRoundTripper) ShouldRetry(req *http.Request, res *http.Response, attempts int, elapsed time.Duration) bool {
if rt.MaxAttempts != nil {
if attempts >= *rt.MaxAttempts {
return false
}
}
if rt.MaxElapsed != nil {
if elapsed >= *rt.MaxElapsed {
return false
}
}
if !IsStatusCodeError(res.StatusCode) {
return false
}
return true
}
func (rt DefaultPersistentRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
var res *http.Response
var err error
attempt := 0
elapsed := 0 * time.Second
for {
attempt += 1
internalRes, internalErr := rt.internalRoundTripper.RoundTrip(req)
if internalErr != nil {
return nil, internalErr
}
res = internalRes
shouldRetry := rt.ShouldRetry(req, res, attempt, elapsed)
if !shouldRetry {
break
}
}
return res, err
}
func IsStatusCodeError(statusCode int) bool {
if 400 <= statusCode &&
statusCode <= 499 {
return true
}
if 500 <= statusCode &&
statusCode <= 599 {
return true
}
return false
}