summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/segmentio/backo-go/backo.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/segmentio/backo-go/backo.go')
-rw-r--r--vendor/github.com/segmentio/backo-go/backo.go83
1 files changed, 83 insertions, 0 deletions
diff --git a/vendor/github.com/segmentio/backo-go/backo.go b/vendor/github.com/segmentio/backo-go/backo.go
new file mode 100644
index 000000000..6f7b6d5e2
--- /dev/null
+++ b/vendor/github.com/segmentio/backo-go/backo.go
@@ -0,0 +1,83 @@
+package backo
+
+import (
+ "math"
+ "math/rand"
+ "time"
+)
+
+type Backo struct {
+ base time.Duration
+ factor uint8
+ jitter float64
+ cap time.Duration
+}
+
+// Creates a backo instance with the given parameters
+func NewBacko(base time.Duration, factor uint8, jitter float64, cap time.Duration) *Backo {
+ return &Backo{base, factor, jitter, cap}
+}
+
+// Creates a backo instance with the following defaults:
+// base: 100 milliseconds
+// factor: 2
+// jitter: 0
+// cap: 10 seconds
+func DefaultBacko() *Backo {
+ return NewBacko(time.Millisecond*100, 2, 0, time.Second*10)
+}
+
+// Duration returns the backoff interval for the given attempt.
+func (backo *Backo) Duration(attempt int) time.Duration {
+ duration := float64(backo.base) * math.Pow(float64(backo.factor), float64(attempt))
+
+ if backo.jitter != 0 {
+ random := rand.Float64()
+ deviation := math.Floor(random * backo.jitter * duration)
+ if (int(math.Floor(random*10)) & 1) == 0 {
+ duration = duration - deviation
+ } else {
+ duration = duration + deviation
+ }
+ }
+
+ duration = math.Min(float64(duration), float64(backo.cap))
+ return time.Duration(duration)
+}
+
+// Sleep pauses the current goroutine for the backoff interval for the given attempt.
+func (backo *Backo) Sleep(attempt int) {
+ duration := backo.Duration(attempt)
+ time.Sleep(duration)
+}
+
+type Ticker struct {
+ done chan struct{}
+ C <-chan time.Time
+}
+
+func (b *Backo) NewTicker() *Ticker {
+ c := make(chan time.Time, 1)
+ ticker := &Ticker{
+ done: make(chan struct{}, 1),
+ C: c,
+ }
+
+ go func() {
+ for i := 0; ; i++ {
+ select {
+ case t := <-time.After(b.Duration(i)):
+ c <- t
+ case <-ticker.done:
+ close(c)
+ return
+ }
+ }
+ }()
+
+ return ticker
+}
+
+func (t *Ticker) Stop() {
+ t.done <- struct{}{}
+}