mirror of https://github.com/jpillora/backoff.git
initial, tests passing
This commit is contained in:
commit
34204cc40b
|
@ -0,0 +1,63 @@
|
||||||
|
# Backoff
|
||||||
|
|
||||||
|
A simple backoff algorithm in Go (Golang)
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
Starts at `Min`, multiplied by `Factor` every call to
|
||||||
|
`Duration()` where it is capped at `Max`. Commonly used
|
||||||
|
in conjunction with `time.Sleep(duration)`.
|
||||||
|
|
||||||
|
``` go
|
||||||
|
|
||||||
|
b := &backoff.Backoff{
|
||||||
|
//These are the defaults
|
||||||
|
Min: 100 * time.Millisecond,
|
||||||
|
Max: 10 * time.Second,
|
||||||
|
Factor: 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%s\n", b.Duration())
|
||||||
|
fmt.Printf("%s\n", b.Duration())
|
||||||
|
fmt.Printf("%s\n", b.Duration())
|
||||||
|
|
||||||
|
fmt.Printf("Reset!\n")
|
||||||
|
b.Reset()
|
||||||
|
|
||||||
|
fmt.Printf("%s\n", b.Duration())
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
100ms
|
||||||
|
200ms
|
||||||
|
400ms
|
||||||
|
Reset!
|
||||||
|
100ms
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Credits
|
||||||
|
|
||||||
|
Ported from some JavaScript written by [@tj](https://github.com/tj)
|
||||||
|
|
||||||
|
#### MIT License
|
||||||
|
|
||||||
|
Copyright © 2015 Jaime Pillora <dev@jpillora.com>
|
||||||
|
|
||||||
|
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.
|
|
@ -0,0 +1,38 @@
|
||||||
|
package backoff
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Backoff struct {
|
||||||
|
attempts, Factor int
|
||||||
|
curr, Min, Max time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Backoff) Duration() time.Duration {
|
||||||
|
//abit hacky though, if zero-value, apply defaults
|
||||||
|
if b.Min == 0 {
|
||||||
|
b.Min = 100 * time.Millisecond
|
||||||
|
}
|
||||||
|
if b.Max == 0 {
|
||||||
|
b.Max = 10 * time.Second
|
||||||
|
}
|
||||||
|
if b.Factor == 0 {
|
||||||
|
b.Factor = 2
|
||||||
|
}
|
||||||
|
if b.curr == 0 {
|
||||||
|
b.curr = b.Min
|
||||||
|
}
|
||||||
|
|
||||||
|
//calculate next duration in ms
|
||||||
|
ms := float64(b.curr) * math.Pow(float64(b.Factor), float64(b.attempts))
|
||||||
|
//bump attempts count
|
||||||
|
b.attempts++
|
||||||
|
//return as a time.Duration
|
||||||
|
return time.Duration(math.Min(ms, float64(b.Max)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Backoff) Reset() {
|
||||||
|
b.attempts = 0
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package backoff
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test1(t *testing.T) {
|
||||||
|
|
||||||
|
b := &Backoff{
|
||||||
|
Min: 100 * time.Millisecond,
|
||||||
|
Max: 10 * time.Second,
|
||||||
|
Factor: 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.Duration() != 100*time.Millisecond {
|
||||||
|
t.Error("Should be 100ms")
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.Duration() != 200*time.Millisecond {
|
||||||
|
t.Error("Should be 200ms")
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.Duration() != 400*time.Millisecond {
|
||||||
|
t.Error("Should be 400ms")
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Reset()
|
||||||
|
|
||||||
|
if b.Duration() != 100*time.Millisecond {
|
||||||
|
t.Error("Should be 100ms again")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue