Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Open sidebar
Ijaz Ahmad
ksonnet
Commits
755b7de0
Unverified
Commit
755b7de0
authored
Apr 03, 2018
by
bryanl
Browse files
adding backoff util
Signed-off-by:
bryanl
<
bryanliles@gmail.com
>
parent
78117253
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
570 additions
and
1 deletion
+570
-1
Gopkg.lock
Gopkg.lock
+7
-1
vendor/github.com/cenkalti/backoff/.gitignore
vendor/github.com/cenkalti/backoff/.gitignore
+22
-0
vendor/github.com/cenkalti/backoff/.travis.yml
vendor/github.com/cenkalti/backoff/.travis.yml
+10
-0
vendor/github.com/cenkalti/backoff/LICENSE
vendor/github.com/cenkalti/backoff/LICENSE
+20
-0
vendor/github.com/cenkalti/backoff/README.md
vendor/github.com/cenkalti/backoff/README.md
+30
-0
vendor/github.com/cenkalti/backoff/backoff.go
vendor/github.com/cenkalti/backoff/backoff.go
+66
-0
vendor/github.com/cenkalti/backoff/context.go
vendor/github.com/cenkalti/backoff/context.go
+60
-0
vendor/github.com/cenkalti/backoff/exponential.go
vendor/github.com/cenkalti/backoff/exponential.go
+158
-0
vendor/github.com/cenkalti/backoff/retry.go
vendor/github.com/cenkalti/backoff/retry.go
+78
-0
vendor/github.com/cenkalti/backoff/ticker.go
vendor/github.com/cenkalti/backoff/ticker.go
+84
-0
vendor/github.com/cenkalti/backoff/tries.go
vendor/github.com/cenkalti/backoff/tries.go
+35
-0
No files found.
Gopkg.lock
View file @
755b7de0
...
...
@@ -35,6 +35,12 @@
revision = "2ee87856327ba09384cabd113bc6b5d174e9ec0f"
version = "v3.5.1"
[[projects]]
name = "github.com/cenkalti/backoff"
packages = ["."]
revision = "2ea60e5f094469f9e65adb9cd103795b73ae743e"
version = "v2.0.0"
[[projects]]
name = "github.com/cpuguy83/go-md2man"
packages = ["md2man"]
...
...
@@ -669,6 +675,6 @@
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "
b1ae87ac0ef11d1061f455055e4c56dc7e39a753d77347d2e02af4d44e6a7633
"
inputs-digest = "
12c28be36adc447c9dfceffe28256a3ec5c0709379755082872b981f309857ee
"
solver-name = "gps-cdcl"
solver-version = 1
vendor/github.com/cenkalti/backoff/.gitignore
0 → 100644
View file @
755b7de0
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
vendor/github.com/cenkalti/backoff/.travis.yml
0 → 100644
View file @
755b7de0
language
:
go
go
:
-
1.3.3
-
1.x
-
tip
before_install
:
-
go get github.com/mattn/goveralls
-
go get golang.org/x/tools/cmd/cover
script
:
-
$HOME/gopath/bin/goveralls -service=travis-ci
vendor/github.com/cenkalti/backoff/LICENSE
0 → 100644
View file @
755b7de0
The MIT License (MIT)
Copyright (c) 2014 Cenk Altı
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
vendor/github.com/cenkalti/backoff/README.md
0 → 100644
View file @
755b7de0
# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Build Status][travis image]][travis] [![Coverage Status][coveralls image]][coveralls]
This is a Go port of the exponential backoff algorithm from
[
Google's HTTP Client Library for Java
][
google-http-java-client
]
.
[
Exponential backoff
][
exponential backoff wiki
]
is an algorithm that uses feedback to multiplicatively decrease the rate of some process,
in order to gradually find an acceptable rate.
The retries exponentially increase and stop increasing when a certain threshold is met.
## Usage
See https://godoc.org/github.com/cenkalti/backoff#pkg-examples
## Contributing
*
I would like to keep this library as small as possible.
*
Please don't send a PR without opening an issue and discussing it first.
*
If proposed change is not a common use case, I will probably not accept it.
[
godoc
]:
https://godoc.org/github.com/cenkalti/backoff
[
godoc image
]:
https://godoc.org/github.com/cenkalti/backoff?status.png
[
travis
]:
https://travis-ci.org/cenkalti/backoff
[
travis image
]:
https://travis-ci.org/cenkalti/backoff.png?branch=master
[
coveralls
]:
https://coveralls.io/github/cenkalti/backoff?branch=master
[
coveralls image
]:
https://coveralls.io/repos/github/cenkalti/backoff/badge.svg?branch=master
[
google-http-java-client
]:
https://github.com/google/google-http-java-client
[
exponential backoff wiki
]:
http://en.wikipedia.org/wiki/Exponential_backoff
[
advanced example
]:
https://godoc.org/github.com/cenkalti/backoff#example_
vendor/github.com/cenkalti/backoff/backoff.go
0 → 100644
View file @
755b7de0
// Package backoff implements backoff algorithms for retrying operations.
//
// Use Retry function for retrying operations that may fail.
// If Retry does not meet your needs,
// copy/paste the function into your project and modify as you wish.
//
// There is also Ticker type similar to time.Ticker.
// You can use it if you need to work with channels.
//
// See Examples section below for usage examples.
package
backoff
import
"time"
// BackOff is a backoff policy for retrying an operation.
type
BackOff
interface
{
// NextBackOff returns the duration to wait before retrying the operation,
// or backoff. Stop to indicate that no more retries should be made.
//
// Example usage:
//
// duration := backoff.NextBackOff();
// if (duration == backoff.Stop) {
// // Do not retry operation.
// } else {
// // Sleep for duration and retry operation.
// }
//
NextBackOff
()
time
.
Duration
// Reset to initial state.
Reset
()
}
// Stop indicates that no more retries should be made for use in NextBackOff().
const
Stop
time
.
Duration
=
-
1
// ZeroBackOff is a fixed backoff policy whose backoff time is always zero,
// meaning that the operation is retried immediately without waiting, indefinitely.
type
ZeroBackOff
struct
{}
func
(
b
*
ZeroBackOff
)
Reset
()
{}
func
(
b
*
ZeroBackOff
)
NextBackOff
()
time
.
Duration
{
return
0
}
// StopBackOff is a fixed backoff policy that always returns backoff.Stop for
// NextBackOff(), meaning that the operation should never be retried.
type
StopBackOff
struct
{}
func
(
b
*
StopBackOff
)
Reset
()
{}
func
(
b
*
StopBackOff
)
NextBackOff
()
time
.
Duration
{
return
Stop
}
// ConstantBackOff is a backoff policy that always returns the same backoff delay.
// This is in contrast to an exponential backoff policy,
// which returns a delay that grows longer as you call NextBackOff() over and over again.
type
ConstantBackOff
struct
{
Interval
time
.
Duration
}
func
(
b
*
ConstantBackOff
)
Reset
()
{}
func
(
b
*
ConstantBackOff
)
NextBackOff
()
time
.
Duration
{
return
b
.
Interval
}
func
NewConstantBackOff
(
d
time
.
Duration
)
*
ConstantBackOff
{
return
&
ConstantBackOff
{
Interval
:
d
}
}
vendor/github.com/cenkalti/backoff/context.go
0 → 100644
View file @
755b7de0
package
backoff
import
(
"time"
"golang.org/x/net/context"
)
// BackOffContext is a backoff policy that stops retrying after the context
// is canceled.
type
BackOffContext
interface
{
BackOff
Context
()
context
.
Context
}
type
backOffContext
struct
{
BackOff
ctx
context
.
Context
}
// WithContext returns a BackOffContext with context ctx
//
// ctx must not be nil
func
WithContext
(
b
BackOff
,
ctx
context
.
Context
)
BackOffContext
{
if
ctx
==
nil
{
panic
(
"nil context"
)
}
if
b
,
ok
:=
b
.
(
*
backOffContext
);
ok
{
return
&
backOffContext
{
BackOff
:
b
.
BackOff
,
ctx
:
ctx
,
}
}
return
&
backOffContext
{
BackOff
:
b
,
ctx
:
ctx
,
}
}
func
ensureContext
(
b
BackOff
)
BackOffContext
{
if
cb
,
ok
:=
b
.
(
BackOffContext
);
ok
{
return
cb
}
return
WithContext
(
b
,
context
.
Background
())
}
func
(
b
*
backOffContext
)
Context
()
context
.
Context
{
return
b
.
ctx
}
func
(
b
*
backOffContext
)
NextBackOff
()
time
.
Duration
{
select
{
case
<-
b
.
Context
()
.
Done
()
:
return
Stop
default
:
return
b
.
BackOff
.
NextBackOff
()
}
}
vendor/github.com/cenkalti/backoff/exponential.go
0 → 100644
View file @
755b7de0
package
backoff
import
(
"math/rand"
"time"
)
/*
ExponentialBackOff is a backoff implementation that increases the backoff
period for each retry attempt using a randomization function that grows exponentially.
NextBackOff() is calculated using the following formula:
randomized interval =
RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor])
In other words NextBackOff() will range between the randomization factor
percentage below and above the retry interval.
For example, given the following parameters:
RetryInterval = 2
RandomizationFactor = 0.5
Multiplier = 2
the actual backoff period used in the next retry attempt will range between 1 and 3 seconds,
multiplied by the exponential, that is, between 2 and 6 seconds.
Note: MaxInterval caps the RetryInterval and not the randomized interval.
If the time elapsed since an ExponentialBackOff instance is created goes past the
MaxElapsedTime, then the method NextBackOff() starts returning backoff.Stop.
The elapsed time can be reset by calling Reset().
Example: Given the following default arguments, for 10 tries the sequence will be,
and assuming we go over the MaxElapsedTime on the 10th try:
Request # RetryInterval (seconds) Randomized Interval (seconds)
1 0.5 [0.25, 0.75]
2 0.75 [0.375, 1.125]
3 1.125 [0.562, 1.687]
4 1.687 [0.8435, 2.53]
5 2.53 [1.265, 3.795]
6 3.795 [1.897, 5.692]
7 5.692 [2.846, 8.538]
8 8.538 [4.269, 12.807]
9 12.807 [6.403, 19.210]
10 19.210 backoff.Stop
Note: Implementation is not thread-safe.
*/
type
ExponentialBackOff
struct
{
InitialInterval
time
.
Duration
RandomizationFactor
float64
Multiplier
float64
MaxInterval
time
.
Duration
// After MaxElapsedTime the ExponentialBackOff stops.
// It never stops if MaxElapsedTime == 0.
MaxElapsedTime
time
.
Duration
Clock
Clock
currentInterval
time
.
Duration
startTime
time
.
Time
random
*
rand
.
Rand
}
// Clock is an interface that returns current time for BackOff.
type
Clock
interface
{
Now
()
time
.
Time
}
// Default values for ExponentialBackOff.
const
(
DefaultInitialInterval
=
500
*
time
.
Millisecond
DefaultRandomizationFactor
=
0.5
DefaultMultiplier
=
1.5
DefaultMaxInterval
=
60
*
time
.
Second
DefaultMaxElapsedTime
=
15
*
time
.
Minute
)
// NewExponentialBackOff creates an instance of ExponentialBackOff using default values.
func
NewExponentialBackOff
()
*
ExponentialBackOff
{
b
:=
&
ExponentialBackOff
{
InitialInterval
:
DefaultInitialInterval
,
RandomizationFactor
:
DefaultRandomizationFactor
,
Multiplier
:
DefaultMultiplier
,
MaxInterval
:
DefaultMaxInterval
,
MaxElapsedTime
:
DefaultMaxElapsedTime
,
Clock
:
SystemClock
,
random
:
rand
.
New
(
rand
.
NewSource
(
time
.
Now
()
.
UnixNano
())),
}
b
.
Reset
()
return
b
}
type
systemClock
struct
{}
func
(
t
systemClock
)
Now
()
time
.
Time
{
return
time
.
Now
()
}
// SystemClock implements Clock interface that uses time.Now().
var
SystemClock
=
systemClock
{}
// Reset the interval back to the initial retry interval and restarts the timer.
func
(
b
*
ExponentialBackOff
)
Reset
()
{
b
.
currentInterval
=
b
.
InitialInterval
b
.
startTime
=
b
.
Clock
.
Now
()
}
// NextBackOff calculates the next backoff interval using the formula:
// Randomized interval = RetryInterval +/- (RandomizationFactor * RetryInterval)
func
(
b
*
ExponentialBackOff
)
NextBackOff
()
time
.
Duration
{
// Make sure we have not gone over the maximum elapsed time.
if
b
.
MaxElapsedTime
!=
0
&&
b
.
GetElapsedTime
()
>
b
.
MaxElapsedTime
{
return
Stop
}
defer
b
.
incrementCurrentInterval
()
if
b
.
random
==
nil
{
b
.
random
=
rand
.
New
(
rand
.
NewSource
(
time
.
Now
()
.
UnixNano
()))
}
return
getRandomValueFromInterval
(
b
.
RandomizationFactor
,
b
.
random
.
Float64
(),
b
.
currentInterval
)
}
// GetElapsedTime returns the elapsed time since an ExponentialBackOff instance
// is created and is reset when Reset() is called.
//
// The elapsed time is computed using time.Now().UnixNano(). It is
// safe to call even while the backoff policy is used by a running
// ticker.
func
(
b
*
ExponentialBackOff
)
GetElapsedTime
()
time
.
Duration
{
return
b
.
Clock
.
Now
()
.
Sub
(
b
.
startTime
)
}
// Increments the current interval by multiplying it with the multiplier.
func
(
b
*
ExponentialBackOff
)
incrementCurrentInterval
()
{
// Check for overflow, if overflow is detected set the current interval to the max interval.
if
float64
(
b
.
currentInterval
)
>=
float64
(
b
.
MaxInterval
)
/
b
.
Multiplier
{
b
.
currentInterval
=
b
.
MaxInterval
}
else
{
b
.
currentInterval
=
time
.
Duration
(
float64
(
b
.
currentInterval
)
*
b
.
Multiplier
)
}
}
// Returns a random value from the following interval:
// [randomizationFactor * currentInterval, randomizationFactor * currentInterval].
func
getRandomValueFromInterval
(
randomizationFactor
,
random
float64
,
currentInterval
time
.
Duration
)
time
.
Duration
{
var
delta
=
randomizationFactor
*
float64
(
currentInterval
)
var
minInterval
=
float64
(
currentInterval
)
-
delta
var
maxInterval
=
float64
(
currentInterval
)
+
delta
// Get a random value from the range [minInterval, maxInterval].
// The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then
// we want a 33% chance for selecting either 1, 2 or 3.
return
time
.
Duration
(
minInterval
+
(
random
*
(
maxInterval
-
minInterval
+
1
)))
}
vendor/github.com/cenkalti/backoff/retry.go
0 → 100644
View file @
755b7de0
package
backoff
import
"time"
// An Operation is executing by Retry() or RetryNotify().
// The operation will be retried using a backoff policy if it returns an error.
type
Operation
func
()
error
// Notify is a notify-on-error function. It receives an operation error and
// backoff delay if the operation failed (with an error).
//
// NOTE that if the backoff policy stated to stop retrying,
// the notify function isn't called.
type
Notify
func
(
error
,
time
.
Duration
)
// Retry the operation o until it does not return error or BackOff stops.
// o is guaranteed to be run at least once.
// It is the caller's responsibility to reset b after Retry returns.
//
// If o returns a *PermanentError, the operation is not retried, and the
// wrapped error is returned.
//
// Retry sleeps the goroutine for the duration returned by BackOff after a
// failed operation returns.
func
Retry
(
o
Operation
,
b
BackOff
)
error
{
return
RetryNotify
(
o
,
b
,
nil
)
}
// RetryNotify calls notify function with the error and wait duration
// for each failed attempt before sleep.
func
RetryNotify
(
operation
Operation
,
b
BackOff
,
notify
Notify
)
error
{
var
err
error
var
next
time
.
Duration
cb
:=
ensureContext
(
b
)
b
.
Reset
()
for
{
if
err
=
operation
();
err
==
nil
{
return
nil
}
if
permanent
,
ok
:=
err
.
(
*
PermanentError
);
ok
{
return
permanent
.
Err
}
if
next
=
b
.
NextBackOff
();
next
==
Stop
{
return
err
}
if
notify
!=
nil
{
notify
(
err
,
next
)
}
t
:=
time
.
NewTimer
(
next
)
select
{
case
<-
cb
.
Context
()
.
Done
()
:
t
.
Stop
()
return
err
case
<-
t
.
C
:
}
}
}
// PermanentError signals that the operation should not be retried.
type
PermanentError
struct
{
Err
error
}
func
(
e
*
PermanentError
)
Error
()
string
{
return
e
.
Err
.
Error
()
}
// Permanent wraps the given err in a *PermanentError.
func
Permanent
(
err
error
)
*
PermanentError
{
return
&
PermanentError
{
Err
:
err
,
}
}
vendor/github.com/cenkalti/backoff/ticker.go
0 → 100644
View file @
755b7de0
package
backoff
import
(
"runtime"
"sync"
"time"
)
// Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff.
//
// Ticks will continue to arrive when the previous operation is still running,
// so operations that take a while to fail could run in quick succession.
type
Ticker
struct
{
C
<-
chan
time
.
Time
c
chan
time
.
Time
b
BackOffContext
stop
chan
struct
{}
stopOnce
sync
.
Once
}
// NewTicker returns a new Ticker containing a channel that will send
// the time at times specified by the BackOff argument. Ticker is
// guaranteed to tick at least once. The channel is closed when Stop
// method is called or BackOff stops. It is not safe to manipulate the
// provided backoff policy (notably calling NextBackOff or Reset)
// while the ticker is running.
func
NewTicker
(
b
BackOff
)
*
Ticker
{
c
:=
make
(
chan
time
.
Time
)
t
:=
&
Ticker
{
C
:
c
,
c
:
c
,
b
:
ensureContext
(
b
),
stop
:
make
(
chan
struct
{}),
}
t
.
b
.
Reset
()
go
t
.
run
()
runtime
.
SetFinalizer
(
t
,
(
*
Ticker
)
.
Stop
)
return
t
}
// Stop turns off a ticker. After Stop, no more ticks will be sent.
func
(
t
*
Ticker
)
Stop
()
{
t
.
stopOnce
.
Do
(
func
()
{
close
(
t
.
stop
)
})
}
func
(
t
*
Ticker
)
run
()
{
c
:=
t
.
c
defer
close
(
c
)
// Ticker is guaranteed to tick at least once.
afterC
:=
t
.
send
(
time
.
Now
())
for
{
if
afterC
==
nil
{
return
}
select
{
case
tick
:=
<-
afterC
:
afterC
=
t
.
send
(
tick
)
case
<-
t
.
stop
:
t
.
c
=
nil
// Prevent future ticks from being sent to the channel.
return
case
<-
t
.
b
.
Context
()
.
Done
()
:
return
}
}
}
func
(
t
*
Ticker
)
send
(
tick
time
.
Time
)
<-
chan
time
.
Time
{
select
{
case
t
.
c
<-
tick
:
case
<-
t
.
stop
:
return
nil
}
next
:=
t
.
b
.
NextBackOff
()
if
next
==
Stop
{
t
.
Stop
()
return
nil
}
return
time
.
After
(
next
)
}
vendor/github.com/cenkalti/backoff/tries.go
0 → 100644
View file @
755b7de0
package
backoff
import
"time"
/*
WithMaxRetries creates a wrapper around another BackOff, which will
return Stop if NextBackOff() has been called too many times since
the last time Reset() was called
Note: Implementation is not thread-safe.
*/
func
WithMaxRetries
(
b
BackOff
,
max
uint64
)
BackOff
{
return
&
backOffTries
{
delegate
:
b
,
maxTries
:
max
}
}
type
backOffTries
struct
{
delegate
BackOff
maxTries
uint64
numTries
uint64
}
func
(
b
*
backOffTries
)
NextBackOff
()
time
.
Duration
{
if
b
.
maxTries
>
0
{
if
b
.
maxTries
<=
b
.
numTries
{
return
Stop
}
b
.
numTries
++
}
return
b
.
delegate
.
NextBackOff
()
}
func
(
b
*
backOffTries
)
Reset
()
{
b
.
numTries
=
0
b
.
delegate
.
Reset
()
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment