Skip to content
This repository has been archived by the owner on May 26, 2022. It is now read-only.

Commit

Permalink
deprecate this repo (#84)
Browse files Browse the repository at this point in the history
  • Loading branch information
marten-seemann committed Apr 21, 2022
1 parent 80f7185 commit 1112033
Show file tree
Hide file tree
Showing 14 changed files with 452 additions and 1,577 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# DEPRECATION NOTICE

This package has moved into go-libp2p, split into multiple sub-packages:
`github.com/libp2p/go-libp2p/p2p/discovery`.

# go-libp2p-discovery

[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](https://protocol.ai)
Expand Down
201 changes: 20 additions & 181 deletions backoff.go
Original file line number Diff line number Diff line change
@@ -1,228 +1,67 @@
package discovery

import (
"math"
"math/rand"
"sync"
"time"

dbackoff "github.com/libp2p/go-libp2p/p2p/discovery/backoff"
)

type BackoffFactory func() BackoffStrategy
// Deprecated: use go-libp2p/p2p/discovery/backoff.BackoffFactory instead.
type BackoffFactory = dbackoff.BackoffFactory

// BackoffStrategy describes how backoff will be implemented. BackoffStratgies are stateful.
type BackoffStrategy interface {
// Delay calculates how long the next backoff duration should be, given the prior calls to Delay
Delay() time.Duration
// Reset clears the internal state of the BackoffStrategy
Reset()
}
// Deprecated: use go-libp2p/p2p/discovery/backoff.BackoffStrategy instead.
type BackoffStrategy = dbackoff.BackoffStrategy

// Jitter implementations taken roughly from https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/

// Jitter must return a duration between min and max. Min must be lower than, or equal to, max.
type Jitter func(duration, min, max time.Duration, rng *rand.Rand) time.Duration
// Deprecated: use go-libp2p/p2p/discovery/backoff.Jitter instead.
type Jitter = dbackoff.Jitter

// FullJitter returns a random number uniformly chose from the range [min, boundedDur].
// boundedDur is the duration bounded between min and max.
// Deprecated: use go-libp2p/p2p/discovery/backoff.FullJitter instead.
func FullJitter(duration, min, max time.Duration, rng *rand.Rand) time.Duration {
if duration <= min {
return min
}

normalizedDur := boundedDuration(duration, min, max) - min

return boundedDuration(time.Duration(rng.Int63n(int64(normalizedDur)))+min, min, max)
return dbackoff.FullJitter(duration, min, max, rng)
}

// NoJitter returns the duration bounded between min and max
// Deprecated: use go-libp2p/p2p/discovery/backoff.NoJitter instead.
func NoJitter(duration, min, max time.Duration, rng *rand.Rand) time.Duration {
return boundedDuration(duration, min, max)
}

type randomizedBackoff struct {
min time.Duration
max time.Duration
rng *rand.Rand
}

func (b *randomizedBackoff) BoundedDelay(duration time.Duration) time.Duration {
return boundedDuration(duration, b.min, b.max)
}

func boundedDuration(d, min, max time.Duration) time.Duration {
if d < min {
return min
}
if d > max {
return max
}
return d
}

type attemptBackoff struct {
attempt int
jitter Jitter
randomizedBackoff
}

func (b *attemptBackoff) Reset() {
b.attempt = 0
return dbackoff.NoJitter(duration, min, max, rng)
}

// NewFixedBackoff creates a BackoffFactory with a constant backoff duration
// Deprecated: use go-libp2p/p2p/discovery/backoff.NewFixedBackoff instead.
func NewFixedBackoff(delay time.Duration) BackoffFactory {
return func() BackoffStrategy {
return &fixedBackoff{delay: delay}
}
}

type fixedBackoff struct {
delay time.Duration
}

func (b *fixedBackoff) Delay() time.Duration {
return b.delay
return dbackoff.NewFixedBackoff(delay)
}

func (b *fixedBackoff) Reset() {}

// NewPolynomialBackoff creates a BackoffFactory with backoff of the form c0*x^0, c1*x^1, ...cn*x^n where x is the attempt number
// jitter is the function for adding randomness around the backoff
// timeUnits are the units of time the polynomial is evaluated in
// polyCoefs is the array of polynomial coefficients from [c0, c1, ... cn]
// Deprecated: use go-libp2p/p2p/discovery/backoff.NewPolynomialBackoff instead.
func NewPolynomialBackoff(min, max time.Duration, jitter Jitter,
timeUnits time.Duration, polyCoefs []float64, rngSrc rand.Source) BackoffFactory {
rng := rand.New(&lockedSource{src: rngSrc})
return func() BackoffStrategy {
return &polynomialBackoff{
attemptBackoff: attemptBackoff{
randomizedBackoff: randomizedBackoff{
min: min,
max: max,
rng: rng,
},
jitter: jitter,
},
timeUnits: timeUnits,
poly: polyCoefs,
}
}
}

type polynomialBackoff struct {
attemptBackoff
timeUnits time.Duration
poly []float64
}

func (b *polynomialBackoff) Delay() time.Duration {
var polySum float64
switch len(b.poly) {
case 0:
return 0
case 1:
polySum = b.poly[0]
default:
polySum = b.poly[0]
exp := 1
attempt := b.attempt
b.attempt++

for _, c := range b.poly[1:] {
exp *= attempt
polySum += float64(exp) * c
}
}
return b.jitter(time.Duration(float64(b.timeUnits)*polySum), b.min, b.max, b.rng)
return dbackoff.NewPolynomialBackoff(min, max, jitter, timeUnits, polyCoefs, rngSrc)
}

// NewExponentialBackoff creates a BackoffFactory with backoff of the form base^x + offset where x is the attempt number
// jitter is the function for adding randomness around the backoff
// timeUnits are the units of time the base^x is evaluated in
// Deprecated: use go-libp2p/p2p/discovery/backoff.NewExponentialBackoff instead.
func NewExponentialBackoff(min, max time.Duration, jitter Jitter,
timeUnits time.Duration, base float64, offset time.Duration, rngSrc rand.Source) BackoffFactory {
rng := rand.New(&lockedSource{src: rngSrc})
return func() BackoffStrategy {
return &exponentialBackoff{
attemptBackoff: attemptBackoff{
randomizedBackoff: randomizedBackoff{
min: min,
max: max,
rng: rng,
},
jitter: jitter,
},
timeUnits: timeUnits,
base: base,
offset: offset,
}
}
}

type exponentialBackoff struct {
attemptBackoff
timeUnits time.Duration
base float64
offset time.Duration
}

func (b *exponentialBackoff) Delay() time.Duration {
attempt := b.attempt
b.attempt++
return b.jitter(
time.Duration(math.Pow(b.base, float64(attempt))*float64(b.timeUnits))+b.offset, b.min, b.max, b.rng)
return dbackoff.NewExponentialBackoff(min, max, jitter, timeUnits, base, offset, rngSrc)
}

// NewExponentialDecorrelatedJitter creates a BackoffFactory with backoff of the roughly of the form base^x where x is the attempt number.
// Delays start at the minimum duration and after each attempt delay = rand(min, delay * base), bounded by the max
// See https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/ for more information
// Deprecated: use go-libp2p/p2p/discovery/backoff.NewExponentialDecorrelatedJitter instead.
func NewExponentialDecorrelatedJitter(min, max time.Duration, base float64, rngSrc rand.Source) BackoffFactory {
rng := rand.New(&lockedSource{src: rngSrc})
return func() BackoffStrategy {
return &exponentialDecorrelatedJitter{
randomizedBackoff: randomizedBackoff{
min: min,
max: max,
rng: rng,
},
base: base,
}
}
}

type exponentialDecorrelatedJitter struct {
randomizedBackoff
base float64
lastDelay time.Duration
}

func (b *exponentialDecorrelatedJitter) Delay() time.Duration {
if b.lastDelay < b.min {
b.lastDelay = b.min
return b.lastDelay
}

nextMax := int64(float64(b.lastDelay) * b.base)
b.lastDelay = boundedDuration(time.Duration(b.rng.Int63n(nextMax-int64(b.min)))+b.min, b.min, b.max)
return b.lastDelay
}

func (b *exponentialDecorrelatedJitter) Reset() { b.lastDelay = 0 }

type lockedSource struct {
lk sync.Mutex
src rand.Source
}

func (r *lockedSource) Int63() (n int64) {
r.lk.Lock()
n = r.src.Int63()
r.lk.Unlock()
return
}

func (r *lockedSource) Seed(seed int64) {
r.lk.Lock()
r.src.Seed(seed)
r.lk.Unlock()
return dbackoff.NewExponentialDecorrelatedJitter(min, max, base, rngSrc)
}
Loading

0 comments on commit 1112033

Please sign in to comment.