Prune dependencies (#1917)

When running `dep prune` explicitly, the following message show up:
```
dep prune
Pruning is now performed automatically by dep ensure.
```

However, after the explicit `dep prune`, there are still many files deleted. (Guess `dep ensure` is not complete yet).

This fix did a `dep prune` to clean up unneeded files.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
This commit is contained in:
Yong Tang 2018-06-30 14:47:19 -07:00 committed by Miek Gieben
parent fcc32a79d4
commit c7321fabc2
10332 changed files with 0 additions and 4102992 deletions

View file

@ -1,31 +0,0 @@
batcher
=======
[![Build Status](https://travis-ci.org/eapache/go-resiliency.svg?branch=master)](https://travis-ci.org/eapache/go-resiliency)
[![GoDoc](https://godoc.org/github.com/eapache/go-resiliency/batcher?status.svg)](https://godoc.org/github.com/eapache/go-resiliency/batcher)
[![Code of Conduct](https://img.shields.io/badge/code%20of%20conduct-active-blue.svg)](https://eapache.github.io/conduct.html)
The batching resiliency pattern for golang.
Creating a batcher takes two parameters:
- the timeout to wait while collecting a batch
- the function to run once a batch has been collected
You can also optionally set a prefilter to fail queries before they enter the
batch.
```go
b := batcher.New(10*time.Millisecond, func(params []interface{}) error {
// do something with the batch of parameters
return nil
})
b.Prefilter(func(param interface{}) error {
// do some sort of sanity check on the parameter, and return an error if it fails
return nil
})
for i := 0; i < 10; i++ {
go b.Run(i)
}
```

View file

@ -1,108 +0,0 @@
// Package batcher implements the batching resiliency pattern for Go.
package batcher
import (
"sync"
"time"
)
type work struct {
param interface{}
future chan error
}
// Batcher implements the batching resiliency pattern
type Batcher struct {
timeout time.Duration
prefilter func(interface{}) error
lock sync.Mutex
submit chan *work
doWork func([]interface{}) error
}
// New constructs a new batcher that will batch all calls to Run that occur within
// `timeout` time before calling doWork just once for the entire batch. The doWork
// function must be safe to run concurrently with itself as this may occur, especially
// when the timeout is small.
func New(timeout time.Duration, doWork func([]interface{}) error) *Batcher {
return &Batcher{
timeout: timeout,
doWork: doWork,
}
}
// Run runs the work function with the given parameter, possibly
// including it in a batch with other calls to Run that occur within the
// specified timeout. It is safe to call Run concurrently on the same batcher.
func (b *Batcher) Run(param interface{}) error {
if b.prefilter != nil {
if err := b.prefilter(param); err != nil {
return err
}
}
if b.timeout == 0 {
return b.doWork([]interface{}{param})
}
w := &work{
param: param,
future: make(chan error, 1),
}
b.submitWork(w)
return <-w.future
}
// Prefilter specifies an optional function that can be used to run initial checks on parameters
// passed to Run before being added to the batch. If the prefilter returns a non-nil error,
// that error is returned immediately from Run and the batcher is not invoked. A prefilter
// cannot safely be specified for a batcher if Run has already been invoked. The filter function
// specified must be concurrency-safe.
func (b *Batcher) Prefilter(filter func(interface{}) error) {
b.prefilter = filter
}
func (b *Batcher) submitWork(w *work) {
b.lock.Lock()
defer b.lock.Unlock()
if b.submit == nil {
b.submit = make(chan *work, 4)
go b.batch()
}
b.submit <- w
}
func (b *Batcher) batch() {
var params []interface{}
var futures []chan error
input := b.submit
go b.timer()
for work := range input {
params = append(params, work.param)
futures = append(futures, work.future)
}
ret := b.doWork(params)
for _, future := range futures {
future <- ret
close(future)
}
}
func (b *Batcher) timer() {
time.Sleep(b.timeout)
b.lock.Lock()
defer b.lock.Unlock()
close(b.submit)
b.submit = nil
}

View file

@ -1,123 +0,0 @@
package batcher
import (
"errors"
"sync"
"sync/atomic"
"testing"
"time"
)
var errSomeError = errors.New("errSomeError")
func returnsError(params []interface{}) error {
return errSomeError
}
func returnsSuccess(params []interface{}) error {
return nil
}
func TestBatcherSuccess(t *testing.T) {
b := New(10*time.Millisecond, returnsSuccess)
wg := &sync.WaitGroup{}
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
if err := b.Run(nil); err != nil {
t.Error(err)
}
wg.Done()
}()
}
wg.Wait()
b = New(0, returnsSuccess)
for i := 0; i < 10; i++ {
if err := b.Run(nil); err != nil {
t.Error(err)
}
}
}
func TestBatcherError(t *testing.T) {
b := New(10*time.Millisecond, returnsError)
wg := &sync.WaitGroup{}
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
if err := b.Run(nil); err != errSomeError {
t.Error(err)
}
wg.Done()
}()
}
wg.Wait()
}
func TestBatcherPrefilter(t *testing.T) {
b := New(1*time.Millisecond, returnsSuccess)
b.Prefilter(func(param interface{}) error {
if param == nil {
return errSomeError
}
return nil
})
if err := b.Run(nil); err != errSomeError {
t.Error(err)
}
if err := b.Run(1); err != nil {
t.Error(err)
}
}
func TestBatcherMultipleBatches(t *testing.T) {
var iters uint32
b := New(10*time.Millisecond, func(params []interface{}) error {
atomic.AddUint32(&iters, 1)
return nil
})
wg := &sync.WaitGroup{}
for group := 0; group < 5; group++ {
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
if err := b.Run(nil); err != nil {
t.Error(err)
}
wg.Done()
}()
}
time.Sleep(15 * time.Millisecond)
}
wg.Wait()
if iters != 5 {
t.Error("Wrong number of iters:", iters)
}
}
func ExampleBatcher() {
b := New(10*time.Millisecond, func(params []interface{}) error {
// do something with the batch of parameters
return nil
})
b.Prefilter(func(param interface{}) error {
// do some sort of sanity check on the parameter, and return an error if it fails
return nil
})
for i := 0; i < 10; i++ {
go b.Run(i)
}
}

View file

@ -1,27 +0,0 @@
deadline
========
[![Build Status](https://travis-ci.org/eapache/go-resiliency.svg?branch=master)](https://travis-ci.org/eapache/go-resiliency)
[![GoDoc](https://godoc.org/github.com/eapache/go-resiliency/deadline?status.svg)](https://godoc.org/github.com/eapache/go-resiliency/deadline)
[![Code of Conduct](https://img.shields.io/badge/code%20of%20conduct-active-blue.svg)](https://eapache.github.io/conduct.html)
The deadline/timeout resiliency pattern for golang.
Creating a deadline takes one parameter: how long to wait.
```go
dl := deadline.New(1 * time.Second)
err := dl.Run(func(stopper <-chan struct{}) error {
// do something potentially slow
// give up when the `stopper` channel is closed (indicating a time-out)
return nil
})
switch err {
case deadline.ErrTimedOut:
// execution took too long, oops
default:
// some other error
}
```

View file

@ -1,45 +0,0 @@
// Package deadline implements the deadline (also known as "timeout") resiliency pattern for Go.
package deadline
import (
"errors"
"time"
)
// ErrTimedOut is the error returned from Run when the deadline expires.
var ErrTimedOut = errors.New("timed out waiting for function to finish")
// Deadline implements the deadline/timeout resiliency pattern.
type Deadline struct {
timeout time.Duration
}
// New constructs a new Deadline with the given timeout.
func New(timeout time.Duration) *Deadline {
return &Deadline{
timeout: timeout,
}
}
// Run runs the given function, passing it a stopper channel. If the deadline passes before
// the function finishes executing, Run returns ErrTimeOut to the caller and closes the stopper
// channel so that the work function can attempt to exit gracefully. It does not (and cannot)
// simply kill the running function, so if it doesn't respect the stopper channel then it may
// keep running after the deadline passes. If the function finishes before the deadline, then
// the return value of the function is returned from Run.
func (d *Deadline) Run(work func(<-chan struct{}) error) error {
result := make(chan error)
stopper := make(chan struct{})
go func() {
result <- work(stopper)
}()
select {
case ret := <-result:
return ret
case <-time.After(d.timeout):
close(stopper)
return ErrTimedOut
}
}

View file

@ -1,65 +0,0 @@
package deadline
import (
"errors"
"testing"
"time"
)
func takesFiveMillis(stopper <-chan struct{}) error {
time.Sleep(5 * time.Millisecond)
return nil
}
func takesTwentyMillis(stopper <-chan struct{}) error {
time.Sleep(20 * time.Millisecond)
return nil
}
func returnsError(stopper <-chan struct{}) error {
return errors.New("foo")
}
func TestDeadline(t *testing.T) {
dl := New(10 * time.Millisecond)
if err := dl.Run(takesFiveMillis); err != nil {
t.Error(err)
}
if err := dl.Run(takesTwentyMillis); err != ErrTimedOut {
t.Error(err)
}
if err := dl.Run(returnsError); err.Error() != "foo" {
t.Error(err)
}
done := make(chan struct{})
err := dl.Run(func(stopper <-chan struct{}) error {
<-stopper
close(done)
return nil
})
if err != ErrTimedOut {
t.Error(err)
}
<-done
}
func ExampleDeadline() {
dl := New(1 * time.Second)
err := dl.Run(func(stopper <-chan struct{}) error {
// do something possibly slow
// check stopper function and give up if timed out
return nil
})
switch err {
case ErrTimedOut:
// execution took too long, oops
default:
// some other error
}
}

View file

@ -1,26 +0,0 @@
retrier
=======
[![Build Status](https://travis-ci.org/eapache/go-resiliency.svg?branch=master)](https://travis-ci.org/eapache/go-resiliency)
[![GoDoc](https://godoc.org/github.com/eapache/go-resiliency/retrier?status.svg)](https://godoc.org/github.com/eapache/go-resiliency/retrier)
[![Code of Conduct](https://img.shields.io/badge/code%20of%20conduct-active-blue.svg)](https://eapache.github.io/conduct.html)
The retriable resiliency pattern for golang.
Creating a retrier takes two parameters:
- the times to back-off between retries (and implicitly the number of times to
retry)
- the classifier that determines which errors to retry
```go
r := retrier.New(retrier.ConstantBackoff(3, 100*time.Millisecond), nil)
err := r.Run(func() error {
// do some work
return nil
})
if err != nil {
// handle the case where the work failed three times
}
```

View file

@ -1,24 +0,0 @@
package retrier
import "time"
// ConstantBackoff generates a simple back-off strategy of retrying 'n' times, and waiting 'amount' time after each one.
func ConstantBackoff(n int, amount time.Duration) []time.Duration {
ret := make([]time.Duration, n)
for i := range ret {
ret[i] = amount
}
return ret
}
// ExponentialBackoff generates a simple back-off strategy of retrying 'n' times, and doubling the amount of
// time waited after each one.
func ExponentialBackoff(n int, initialAmount time.Duration) []time.Duration {
ret := make([]time.Duration, n)
next := initialAmount
for i := range ret {
ret[i] = next
next *= 2
}
return ret
}

View file

@ -1,55 +0,0 @@
package retrier
import (
"testing"
"time"
)
func TestConstantBackoff(t *testing.T) {
b := ConstantBackoff(1, 10*time.Millisecond)
if len(b) != 1 {
t.Error("incorrect length")
}
for i := range b {
if b[i] != 10*time.Millisecond {
t.Error("incorrect value at", i)
}
}
b = ConstantBackoff(10, 250*time.Hour)
if len(b) != 10 {
t.Error("incorrect length")
}
for i := range b {
if b[i] != 250*time.Hour {
t.Error("incorrect value at", i)
}
}
}
func TestExponentialBackoff(t *testing.T) {
b := ExponentialBackoff(1, 10*time.Millisecond)
if len(b) != 1 {
t.Error("incorrect length")
}
if b[0] != 10*time.Millisecond {
t.Error("incorrect value")
}
b = ExponentialBackoff(4, 1*time.Minute)
if len(b) != 4 {
t.Error("incorrect length")
}
if b[0] != 1*time.Minute {
t.Error("incorrect value")
}
if b[1] != 2*time.Minute {
t.Error("incorrect value")
}
if b[2] != 4*time.Minute {
t.Error("incorrect value")
}
if b[3] != 8*time.Minute {
t.Error("incorrect value")
}
}

View file

@ -1,66 +0,0 @@
package retrier
// Action is the type returned by a Classifier to indicate how the Retrier should proceed.
type Action int
const (
Succeed Action = iota // Succeed indicates the Retrier should treat this value as a success.
Fail // Fail indicates the Retrier should treat this value as a hard failure and not retry.
Retry // Retry indicates the Retrier should treat this value as a soft failure and retry.
)
// Classifier is the interface implemented by anything that can classify Errors for a Retrier.
type Classifier interface {
Classify(error) Action
}
// DefaultClassifier classifies errors in the simplest way possible. If
// the error is nil, it returns Succeed, otherwise it returns Retry.
type DefaultClassifier struct{}
// Classify implements the Classifier interface.
func (c DefaultClassifier) Classify(err error) Action {
if err == nil {
return Succeed
}
return Retry
}
// WhitelistClassifier classifies errors based on a whitelist. If the error is nil, it
// returns Succeed; if the error is in the whitelist, it returns Retry; otherwise, it returns Fail.
type WhitelistClassifier []error
// Classify implements the Classifier interface.
func (list WhitelistClassifier) Classify(err error) Action {
if err == nil {
return Succeed
}
for _, pass := range list {
if err == pass {
return Retry
}
}
return Fail
}
// BlacklistClassifier classifies errors based on a blacklist. If the error is nil, it
// returns Succeed; if the error is in the blacklist, it returns Fail; otherwise, it returns Retry.
type BlacklistClassifier []error
// Classify implements the Classifier interface.
func (list BlacklistClassifier) Classify(err error) Action {
if err == nil {
return Succeed
}
for _, pass := range list {
if err == pass {
return Fail
}
}
return Retry
}

View file

@ -1,66 +0,0 @@
package retrier
import (
"errors"
"testing"
)
var (
errFoo = errors.New("FOO")
errBar = errors.New("BAR")
errBaz = errors.New("BAZ")
)
func TestDefaultClassifier(t *testing.T) {
c := DefaultClassifier{}
if c.Classify(nil) != Succeed {
t.Error("default misclassified nil")
}
if c.Classify(errFoo) != Retry {
t.Error("default misclassified foo")
}
if c.Classify(errBar) != Retry {
t.Error("default misclassified bar")
}
if c.Classify(errBaz) != Retry {
t.Error("default misclassified baz")
}
}
func TestWhitelistClassifier(t *testing.T) {
c := WhitelistClassifier{errFoo, errBar}
if c.Classify(nil) != Succeed {
t.Error("whitelist misclassified nil")
}
if c.Classify(errFoo) != Retry {
t.Error("whitelist misclassified foo")
}
if c.Classify(errBar) != Retry {
t.Error("whitelist misclassified bar")
}
if c.Classify(errBaz) != Fail {
t.Error("whitelist misclassified baz")
}
}
func TestBlacklistClassifier(t *testing.T) {
c := BlacklistClassifier{errBar}
if c.Classify(nil) != Succeed {
t.Error("blacklist misclassified nil")
}
if c.Classify(errFoo) != Retry {
t.Error("blacklist misclassified foo")
}
if c.Classify(errBar) != Fail {
t.Error("blacklist misclassified bar")
}
if c.Classify(errBaz) != Retry {
t.Error("blacklist misclassified baz")
}
}

View file

@ -1,69 +0,0 @@
// Package retrier implements the "retriable" resiliency pattern for Go.
package retrier
import (
"math/rand"
"time"
)
// Retrier implements the "retriable" resiliency pattern, abstracting out the process of retrying a failed action
// a certain number of times with an optional back-off between each retry.
type Retrier struct {
backoff []time.Duration
class Classifier
jitter float64
rand *rand.Rand
}
// New constructs a Retrier with the given backoff pattern and classifier. The length of the backoff pattern
// indicates how many times an action will be retried, and the value at each index indicates the amount of time
// waited before each subsequent retry. The classifier is used to determine which errors should be retried and
// which should cause the retrier to fail fast. The DefaultClassifier is used if nil is passed.
func New(backoff []time.Duration, class Classifier) *Retrier {
if class == nil {
class = DefaultClassifier{}
}
return &Retrier{
backoff: backoff,
class: class,
rand: rand.New(rand.NewSource(time.Now().UnixNano())),
}
}
// Run executes the given work function, then classifies its return value based on the classifier used
// to construct the Retrier. If the result is Succeed or Fail, the return value of the work function is
// returned to the caller. If the result is Retry, then Run sleeps according to the its backoff policy
// before retrying. If the total number of retries is exceeded then the return value of the work function
// is returned to the caller regardless.
func (r *Retrier) Run(work func() error) error {
retries := 0
for {
ret := work()
switch r.class.Classify(ret) {
case Succeed, Fail:
return ret
case Retry:
if retries >= len(r.backoff) {
return ret
}
time.Sleep(r.calcSleep(retries))
retries++
}
}
}
func (r *Retrier) calcSleep(i int) time.Duration {
// take a random float in the range (-r.jitter, +r.jitter) and multiply it by the base amount
return r.backoff[i] + time.Duration(((r.rand.Float64()*2)-1)*r.jitter*float64(r.backoff[i]))
}
// SetJitter sets the amount of jitter on each back-off to a factor between 0.0 and 1.0 (values outside this range
// are silently ignored). When a retry occurs, the back-off is adjusted by a random amount up to this value.
func (r *Retrier) SetJitter(jit float64) {
if jit < 0 || jit > 1 {
return
}
r.jitter = jit
}

View file

@ -1,129 +0,0 @@
package retrier
import (
"testing"
"time"
)
var i int
func genWork(returns []error) func() error {
i = 0
return func() error {
i++
if i > len(returns) {
return nil
}
return returns[i-1]
}
}
func TestRetrier(t *testing.T) {
r := New([]time.Duration{0, 10 * time.Millisecond}, WhitelistClassifier{errFoo})
err := r.Run(genWork([]error{errFoo, errFoo}))
if err != nil {
t.Error(err)
}
if i != 3 {
t.Error("run wrong number of times")
}
err = r.Run(genWork([]error{errFoo, errBar}))
if err != errBar {
t.Error(err)
}
if i != 2 {
t.Error("run wrong number of times")
}
err = r.Run(genWork([]error{errBar, errBaz}))
if err != errBar {
t.Error(err)
}
if i != 1 {
t.Error("run wrong number of times")
}
}
func TestRetrierNone(t *testing.T) {
r := New(nil, nil)
i = 0
err := r.Run(func() error {
i++
return errFoo
})
if err != errFoo {
t.Error(err)
}
if i != 1 {
t.Error("run wrong number of times")
}
i = 0
err = r.Run(func() error {
i++
return nil
})
if err != nil {
t.Error(err)
}
if i != 1 {
t.Error("run wrong number of times")
}
}
func TestRetrierJitter(t *testing.T) {
r := New([]time.Duration{0, 10 * time.Millisecond, 4 * time.Hour}, nil)
if r.calcSleep(0) != 0 {
t.Error("Incorrect sleep calculated")
}
if r.calcSleep(1) != 10*time.Millisecond {
t.Error("Incorrect sleep calculated")
}
if r.calcSleep(2) != 4*time.Hour {
t.Error("Incorrect sleep calculated")
}
r.SetJitter(0.25)
for i := 0; i < 20; i++ {
if r.calcSleep(0) != 0 {
t.Error("Incorrect sleep calculated")
}
slp := r.calcSleep(1)
if slp < 7500*time.Microsecond || slp > 12500*time.Microsecond {
t.Error("Incorrect sleep calculated")
}
slp = r.calcSleep(2)
if slp < 3*time.Hour || slp > 5*time.Hour {
t.Error("Incorrect sleep calculated")
}
}
r.SetJitter(-1)
if r.jitter != 0.25 {
t.Error("Invalid jitter value accepted")
}
r.SetJitter(2)
if r.jitter != 0.25 {
t.Error("Invalid jitter value accepted")
}
}
func ExampleRetrier() {
r := New(ConstantBackoff(3, 100*time.Millisecond), nil)
err := r.Run(func() error {
// do some work
return nil
})
if err != nil {
// handle the case where the work failed three times
}
}

View file

@ -1,22 +0,0 @@
semaphore
=========
[![Build Status](https://travis-ci.org/eapache/go-resiliency.svg?branch=master)](https://travis-ci.org/eapache/go-resiliency)
[![GoDoc](https://godoc.org/github.com/eapache/go-resiliency/semaphore?status.svg)](https://godoc.org/github.com/eapache/go-resiliency/semaphore)
[![Code of Conduct](https://img.shields.io/badge/code%20of%20conduct-active-blue.svg)](https://eapache.github.io/conduct.html)
The semaphore resiliency pattern for golang.
Creating a semaphore takes two parameters:
- ticket count (how many tickets to give out at once)
- timeout (how long to wait for a ticket if none are currently available)
```go
sem := semaphore.New(3, 1*time.Second)
if err := sem.Acquire(); err != nil {
// could not acquire semaphore
return err
}
defer sem.Release()
```

View file

@ -1,52 +0,0 @@
// Package semaphore implements the semaphore resiliency pattern for Go.
package semaphore
import (
"errors"
"time"
)
// ErrNoTickets is the error returned by Acquire when it could not acquire
// a ticket from the semaphore within the configured timeout.
var ErrNoTickets = errors.New("could not acquire semaphore ticket")
// Semaphore implements the semaphore resiliency pattern
type Semaphore struct {
sem chan struct{}
timeout time.Duration
}
// New constructs a new Semaphore with the given ticket-count
// and timeout.
func New(tickets int, timeout time.Duration) *Semaphore {
return &Semaphore{
sem: make(chan struct{}, tickets),
timeout: timeout,
}
}
// Acquire tries to acquire a ticket from the semaphore. If it can, it returns nil.
// If it cannot after "timeout" amount of time, it returns ErrNoTickets. It is
// safe to call Acquire concurrently on a single Semaphore.
func (s *Semaphore) Acquire() error {
select {
case s.sem <- struct{}{}:
return nil
case <-time.After(s.timeout):
return ErrNoTickets
}
}
// Release releases an acquired ticket back to the semaphore. It is safe to call
// Release concurrently on a single Semaphore. It is an error to call Release on
// a Semaphore from which you have not first acquired a ticket.
func (s *Semaphore) Release() {
<-s.sem
}
// IsEmpty will return true if no tickets are being held at that instant.
// It is safe to call concurrently with Acquire and Release, though do note
// that the result may then be unpredictable.
func (s *Semaphore) IsEmpty() bool {
return len(s.sem) == 0
}

View file

@ -1,81 +0,0 @@
package semaphore
import (
"testing"
"time"
)
func TestSemaphoreAcquireRelease(t *testing.T) {
sem := New(3, 1*time.Second)
for i := 0; i < 10; i++ {
if err := sem.Acquire(); err != nil {
t.Error(err)
}
if err := sem.Acquire(); err != nil {
t.Error(err)
}
if err := sem.Acquire(); err != nil {
t.Error(err)
}
sem.Release()
sem.Release()
sem.Release()
}
}
func TestSemaphoreBlockTimeout(t *testing.T) {
sem := New(1, 200*time.Millisecond)
if err := sem.Acquire(); err != nil {
t.Error(err)
}
start := time.Now()
if err := sem.Acquire(); err != ErrNoTickets {
t.Error(err)
}
if start.Add(200 * time.Millisecond).After(time.Now()) {
t.Error("semaphore did not wait long enough")
}
sem.Release()
if err := sem.Acquire(); err != nil {
t.Error(err)
}
}
func TestSemaphoreEmpty(t *testing.T) {
sem := New(2, 200*time.Millisecond)
if !sem.IsEmpty() {
t.Error("semaphore should be empty")
}
sem.Acquire()
if sem.IsEmpty() {
t.Error("semaphore should not be empty")
}
sem.Release()
if !sem.IsEmpty() {
t.Error("semaphore should be empty")
}
}
func ExampleSemaphore() {
sem := New(3, 1*time.Second)
for i := 0; i < 10; i++ {
go func() {
if err := sem.Acquire(); err != nil {
return //could not acquire semaphore
}
defer sem.Release()
// do something semaphore-guarded
}()
}
}