generated from xmidt-org/.go-template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
config.go
98 lines (84 loc) · 3.39 KB
/
config.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
// SPDX-FileCopyrightText: 2023 Comcast Cable Communications Management, LLC
// SPDX-License-Identifier: Apache-2.0
package retry
import (
"context"
"math/rand"
"time"
)
// Config represents the possible options when creating a Policy. This type is friendly
// to being unmarshaled from external sources.
//
// Three basic kinds of retry policies are created by this type:
//
// - if Interval is nonpositive, the created policy will never retry anything
// - if Interval is positive but Jitter and Multiplier are not, the created policy will return a constant, unchanging retry interval
// - if Interval is positive and Jitter or Multiplier are as well, the created policy will return an exponentially increasing retry interval
type Config struct {
// Interval specifies the retry interval for a constant backoff and the
// initial, starting interval for an exponential backoff.
//
// If this field is unset, no retries will happen.
Interval time.Duration `json:"interval" yaml:"interval"`
// Jitter is the random jitter for an exponential backoff.
//
// If this value is nonpositive, it is ignored. If both this field and
// Multiplier are unset, the resulting policy will be a constant backoff.
Jitter float64 `json:"jitter" yaml:"jitter"`
// Multiplier is the interval multiplier for an exponential backoff.
//
// If this value is less than or equal to 1.0, it is ignored. If both this field and
// Jitter are unset, the resulting policy will be a constant backoff.
Multiplier float64 `json:"multiplier" yaml:"multiplier"`
// MaxRetries is the absolute maximum number of retries performed, regardless
// of other fields. If this field is nonpositive, operations are retried until
// they succeed.
MaxRetries int `json:"maxRetries" yaml:"maxRetries"`
// MaxElapsedTime is the absolute amount of time an operation and its retries are
// allowed to take before giving up. If this field is nonpositive, no maximum
// elapsed time is enforced.
MaxElapsedTime time.Duration `json:"maxElapsedTime" yaml:"maxElapsedTime"`
// MaxInterval is the upper limit for each retry interval for an exponential backoff.
// If Jitter and Multiplier are unset, or if this value is smaller than Interval, then
// this field is ignored.
MaxInterval time.Duration `json:"maxInterval" yaml:"maxInterval"`
}
func (c Config) newPolicyCtx(parentCtx context.Context) (context.Context, context.CancelFunc) {
if c.MaxElapsedTime > 0 {
return context.WithTimeout(parentCtx, c.MaxElapsedTime)
}
return context.WithCancel(parentCtx)
}
// NewPolicy implements PolicyFactory and uses this configuration to create the type
// of retry policy indicated by the Interval, Jitter, and Multiplier fields.
func (c Config) NewPolicy(parentCtx context.Context) Policy {
ctx, cancel := c.newPolicyCtx(parentCtx)
if c.Interval <= 0 {
return &never{
ctx: ctx,
cancel: cancel,
}
}
cp := corePolicy{
ctx: ctx,
cancel: cancel,
maxRetries: c.MaxRetries,
}
if c.Jitter <= 0.0 && c.Multiplier <= 1.0 {
// constant is a slightly more efficient policy.
// if the caller doesn't want randomness or an increasing interval,
// don't make her pay the performance costs.
return &constant{
corePolicy: cp,
interval: c.Interval,
}
}
return &exponential{
corePolicy: cp,
rand: rand.Int63n,
initial: c.Interval,
jitter: c.Jitter,
multiplier: c.Multiplier,
maxInterval: c.MaxInterval,
}
}