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
package runtime
import (
"sync"
"time"
"github.com/johnandersen777/socialweb-computer-kcp/internal/kit/opt"
mcreconcile "sigs.k8s.io/multicluster-runtime/pkg/reconcile"
)
const (
DefaultBackoffBase = 500 * time.Millisecond
DefaultBackoffMax = 5 * time.Minute
ExportRetryFirst = 50 * time.Millisecond
)
type backoff struct {
base time.Duration
max time.Duration
mu sync.Mutex
failures map[mcreconcile.Request]int
}
func newBackoff(base, max time.Duration) *backoff {
base = opt.Positive(base, DefaultBackoffBase)
if max < base {
max = base
}
return &backoff{base: base, max: max, failures: map[mcreconcile.Request]int{}}
}
func (b *backoff) delay(n int) time.Duration {
d := b.base
for i := 0; i < n && d < b.max; i++ {
d *= 2
}
if d > b.max {
d = b.max
}
return d
}
func (b *backoff) When(item mcreconcile.Request) time.Duration {
b.mu.Lock()
defer b.mu.Unlock()
n := b.failures[item]
b.failures[item] = n + 1
return b.delay(n)
}
func (b *backoff) Forget(item mcreconcile.Request) {
b.mu.Lock()
defer b.mu.Unlock()
delete(b.failures, item)
}
func (b *backoff) NumRequeues(item mcreconcile.Request) int {
b.mu.Lock()
defer b.mu.Unlock()
return b.failures[item]
}
func (b *backoff) peek(item mcreconcile.Request) (int, time.Duration) {
b.mu.Lock()
defer b.mu.Unlock()
n := b.failures[item]
return n + 1, b.delay(n)
}
func BackoffDelay(base, max time.Duration, failures int) time.Duration {
return newBackoff(base, max).delay(failures)
}