/
exponential_backoff.go
64 lines (53 loc) · 1.53 KB
/
exponential_backoff.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
package expobackoff
import (
"google.golang.org/api/googleapi"
"google.golang.org/api/photoslibrary/v1"
"math/rand"
"net/http"
"time"
)
const EXPO_LIM = 9
const NUM_RETRIES = 20
type Response interface {
}
func Calculate(num_retries int) []time.Duration {
retryDurations := make([]time.Duration, num_retries)
for i := 0; i < num_retries; i++ {
if i < EXPO_LIM {
retryDurations[i] = time.Duration(1e9*rand.Float64()) + (1<<uint32(i))*time.Second
} else {
retryDurations[i] = time.Duration(1e9*rand.Float64()) + (1<<uint32(EXPO_LIM))*time.Second
}
}
return retryDurations
}
func RequestUntilSuccess(action func(*http.Request) (*http.Response, error), r *http.Request) (*http.Response, error) {
resp, err := action(r)
if err != nil || resp.StatusCode == 429 {
durations := Calculate(NUM_RETRIES)
for _, sleepDur := range durations {
duration := time.Duration(sleepDur)
time.Sleep(duration)
resp, err = action(r)
if err == nil && resp.StatusCode == 200 {
return resp, err
}
}
}
return resp, err
}
func DoUntilSuccess(action func(opts ...googleapi.CallOption) (*photoslibrary.BatchCreateMediaItemsResponse, error)) (*photoslibrary.BatchCreateMediaItemsResponse, error) {
resp, err := action()
if err != nil || resp.HTTPStatusCode == 429 {
durations := Calculate(NUM_RETRIES)
for _, sleepDur := range durations {
duration := time.Duration(sleepDur)
time.Sleep(duration)
resp, err = action()
if err == nil && resp.HTTPStatusCode == 200 {
return resp, err
}
}
}
return resp, err
}