...
1 package eventsource
2
3 import (
4 "math"
5 "math/rand"
6 "time"
7 )
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 type retryDelayStrategy struct {
23 baseDelay time.Duration
24 backoff backoffStrategy
25 jitter jitterStrategy
26 resetInterval time.Duration
27 retryCount int
28 goodSince time.Time
29 }
30
31
32 type backoffStrategy interface {
33 applyBackoff(baseDelay time.Duration, retryCount int) time.Duration
34 }
35
36
37 type jitterStrategy interface {
38 applyJitter(computedDelay time.Duration) time.Duration
39 }
40
41 type defaultBackoffStrategy struct {
42 maxDelay time.Duration
43 }
44
45
46
47
48
49
50
51 func newDefaultBackoff(maxDelay time.Duration) backoffStrategy {
52 return defaultBackoffStrategy{maxDelay}
53 }
54
55 func (s defaultBackoffStrategy) applyBackoff(baseDelay time.Duration, retryCount int) time.Duration {
56 d := math.Min(float64(baseDelay)*math.Pow(2, float64(retryCount)), float64(s.maxDelay))
57 return time.Duration(d)
58 }
59
60 type defaultJitterStrategy struct {
61 ratio float64
62 random *rand.Rand
63 }
64
65
66
67 func newDefaultJitter(ratio float64, randSeed int64) jitterStrategy {
68 if randSeed <= 0 {
69 randSeed = time.Now().UnixNano()
70 }
71 if ratio > 1.0 {
72 ratio = 1.0
73 }
74 return &defaultJitterStrategy{ratio, rand.New(rand.NewSource(randSeed))}
75 }
76
77 func (s *defaultJitterStrategy) applyJitter(computedDelay time.Duration) time.Duration {
78
79 jitter := time.Duration(s.random.Int63n(int64(float64(computedDelay) * s.ratio)))
80 return computedDelay - jitter
81 }
82
83
84 func newRetryDelayStrategy(
85 baseDelay time.Duration,
86 resetInterval time.Duration,
87 backoff backoffStrategy,
88 jitter jitterStrategy,
89 ) *retryDelayStrategy {
90 return &retryDelayStrategy{
91 baseDelay: baseDelay,
92 resetInterval: resetInterval,
93 backoff: backoff,
94 jitter: jitter,
95 }
96 }
97
98
99
100
101
102 func (r *retryDelayStrategy) NextRetryDelay(currentTime time.Time) time.Duration {
103 if !r.goodSince.IsZero() && r.resetInterval > 0 && (currentTime.Sub(r.goodSince) >= r.resetInterval) {
104 r.retryCount = 0
105 }
106 r.goodSince = time.Time{}
107 delay := r.baseDelay
108 if r.backoff != nil {
109 delay = r.backoff.applyBackoff(delay, r.retryCount)
110 }
111 r.retryCount++
112 if r.jitter != nil {
113 delay = r.jitter.applyJitter(delay)
114 }
115 return delay
116 }
117
118
119 func (r *retryDelayStrategy) SetGoodSince(goodSince time.Time) {
120 r.goodSince = goodSince
121 }
122
123
124
125
126
127
128
129 func (r *retryDelayStrategy) SetBaseDelay(baseDelay time.Duration) {
130 r.baseDelay = baseDelay
131 r.retryCount = 0
132 }
133
134 func (r *retryDelayStrategy) hasJitter() bool {
135 return r.jitter != nil
136 }
137
View as plain text