-
-
Notifications
You must be signed in to change notification settings - Fork 33
/
loop.go
126 lines (115 loc) · 2.57 KB
/
loop.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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package runn
import (
"context"
"strconv"
"strings"
"time"
"github.com/goccy/go-yaml"
"github.com/lestrrat-go/backoff/v2"
)
const (
loopSectionKey = "loop"
storeRootKeyLoopCountIndex = "i"
)
var (
defaultCount = 3
defaultMaxInterval = "0ms"
defaultMinInterval = "0ms"
defaultJitter = float64(0.0)
defaultMultiplier = float64(1.5)
)
type Loop struct {
Count string `yaml:"count,omitempty"`
Interval string `yaml:"interval,omitempty"`
MinInterval string `yaml:"minInterval,omitempty"`
MaxInterval string `yaml:"maxInterval,omitempty"`
Jitter *float64 `yaml:"jitter,omitempty"`
Multiplier *float64 `yaml:"multiplier,omitempty"`
Until string `yaml:"until"`
ctrl backoff.Controller
interval *time.Duration
minInterval *time.Duration
maxInterval *time.Duration
}
func newLoop(v any) (*Loop, error) {
b, err := yaml.Marshal(v)
if err != nil {
return nil, err
}
l := &Loop{}
err = yaml.Unmarshal(b, l)
if err != nil {
// short syntax
l.Count = strings.TrimRight(string(b), "\n\r")
}
if l.Count == "" {
l.Count = strconv.Itoa(defaultCount)
}
if l.Until == "" && l.Interval == "" && l.MinInterval == "" && l.MaxInterval == "" {
// for simple loop
l.Interval = "0"
}
if l.Until == "" && l.Jitter == nil {
// for simple loop
i := 0.0
l.Jitter = &i
}
if l.Interval == "" {
if l.MinInterval == "" {
l.MinInterval = defaultMinInterval
}
if l.MaxInterval == "" {
l.MaxInterval = defaultMaxInterval
}
if l.Multiplier == nil {
l.Multiplier = &defaultMultiplier
}
}
if l.Jitter == nil {
l.Jitter = &defaultJitter
}
if l.Interval != "" {
i, err := parseDuration(l.Interval)
if err != nil {
return nil, err
}
l.interval = &i
} else {
imin, err := parseDuration(l.MinInterval)
if err != nil {
return nil, err
}
l.minInterval = &imin
imax, err := parseDuration(l.MaxInterval)
if err != nil {
return nil, err
}
l.maxInterval = &imax
}
return l, nil
}
func (l *Loop) Loop(ctx context.Context) bool {
if l.ctrl == nil {
var p backoff.Policy
if l.interval != nil {
p = backoff.Constant(
backoff.WithMaxRetries(0),
backoff.WithInterval(*l.interval),
backoff.WithJitterFactor(*l.Jitter),
)
} else {
p = backoff.Exponential(
backoff.WithMaxRetries(0),
backoff.WithMinInterval(*l.minInterval),
backoff.WithMaxInterval(*l.maxInterval),
backoff.WithMultiplier(*l.Multiplier),
backoff.WithJitterFactor(*l.Jitter),
)
}
l.ctrl = p.Start(ctx)
}
return backoff.Continue(l.ctrl)
}
func (l *Loop) Clear() {
l.ctrl = nil
}