From 0d95101f5044746ab2411bf224f8394ca0987330 Mon Sep 17 00:00:00 2001 From: Eugene Kim Date: Fri, 14 Sep 2018 15:05:58 -0700 Subject: [PATCH] Add an exponential backoff helper --- p2p/backoff.go | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 p2p/backoff.go diff --git a/p2p/backoff.go b/p2p/backoff.go new file mode 100644 index 000000000..8de6f5a3b --- /dev/null +++ b/p2p/backoff.go @@ -0,0 +1,60 @@ +package p2p + +import "time" + +// Backoff is a backoff sleeper. +type Backoff interface { + Reset() + Sleep() + Backoff() +} + +// BackoffBase is the base implementation of backoff sleeper. It handles the +// minimum/current/maximum backoff logic. If maximum backoff is 0, there is no +// maximum. +type BackoffBase struct { + Min, Cur, Max time.Duration +} + +func NewBackoffBase(min, max time.Duration) *BackoffBase{ + return &BackoffBase{min, min, max} +} + +// Reset the current sleep duration to its minimum value. +func (b *BackoffBase) Reset() { + b.Cur = b.Min +} + +// Sleep for the current duration, then adjust the duration. +func (b *BackoffBase) Sleep() { + if b.Cur < b.Min { + b.Cur = b.Min + } + time.Sleep(b.Cur) + b.Backoff() + if b.Max != 0 && b.Cur > b.Max { + b.Cur = b.Max + } + if b.Cur < b.Min { + b.Cur = b.Min + } +} + +// Adjust the duration. Subtypes shall implement this. +func (b *BackoffBase) Backoff() { + // default implementation does not backoff +} + +// Exponential backoff. +type ExpBackoff struct { + BackoffBase + Factor float64 +} + +func NewExpBackoff(min, max time.Duration, factor float64) *ExpBackoff { + return &ExpBackoff{*NewBackoffBase(min, max), factor} +} + +func (b *ExpBackoff) Backoff() { + b.Cur = time.Duration(float64(b.Cur) * b.Factor) +}