-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbackoff.go
52 lines (43 loc) · 1.55 KB
/
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
package chadango
import (
"context"
"math/rand"
"time"
)
// Backoff represents a backoff mechanism with configurable duration and maximum duration.
type Backoff struct {
Duration time.Duration // Duration represents the current backoff duration.
MaxDuration time.Duration // MaxDuration is the maximum allowed backoff duration.
context context.Context // context is the context used for cancellation.
cancelCtx context.CancelFunc // cancel is the function to cancel the [Backoff.Sleep] operation.
}
// increment increases the backoff duration using an exponential strategy
func (b *Backoff) increment() {
if b.Duration < b.MaxDuration {
// Use an exponential backoff strategy to increase the wait duration between reconnection attempts.
b.Duration *= 2
}
if b.Duration > b.MaxDuration {
b.Duration = b.MaxDuration
}
}
// Sleep is a mock of [time.Sleep], that is also responsive to the cancel signal.
// It adds some jitter to the context and waits until the context is done.
//
// Args:
// - ctx: The context used for cancellation.
//
// Returns:
// - bool: True if the sleep was cancelled before the deadline, false otherwise.
func (b *Backoff) Sleep(ctx context.Context) bool {
defer b.increment()
// Add some jitter to the context.
b.context, b.cancelCtx = context.WithTimeout(ctx, b.Duration+time.Duration(rand.Int63n(int64(b.Duration)/4)))
defer b.cancelCtx()
<-b.context.Done()
return b.context.Err() != context.DeadlineExceeded
}
// Cancel cancels the ongoing backoff sleep.
func (b *Backoff) Cancel() {
b.cancelCtx()
}