Pārlūkot izejas kodu

Revert "Fix build flag"

This reverts commit a294bd8118737d8db9fbbe2e2c046d7bad5ef3fa.
tukeJonny 6 gadi atpakaļ
vecāks
revīzija
5a6c539a71
3 mainītis faili ar 70 papildinājumiem un 28 dzēšanām
  1. 25 0
      retrier/retrier.go
  2. 45 0
      retrier/retrier_go17.go
  3. 0 28
      retrier/retrier_legacy.go

+ 25 - 0
retrier/retrier.go

@@ -1,3 +1,5 @@
+// +build !go1.7
+
 // Package retrier implements the "retriable" resiliency pattern for Go.
 package retrier
 
@@ -33,6 +35,29 @@ func New(backoff []time.Duration, class Classifier) *Retrier {
 	}
 }
 
+// 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 {
 	// lock unsafe rand prng
 	r.randMu.Lock()

+ 45 - 0
retrier/retrier_go17.go

@@ -5,9 +5,37 @@ package retrier
 
 import (
 	"context"
+	"math/rand"
+	"sync"
 	"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
+	randMu  sync.Mutex
+}
+
+// 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 by executing RunCtx without context.Context.
 func (r *Retrier) Run(work func() error) error {
 	return r.RunCtx(context.Background(), func(ctx context.Context) error {
@@ -52,3 +80,20 @@ func (r *Retrier) sleep(ctx context.Context, t <-chan time.Time) error {
 		return ctx.Err()
 	}
 }
+
+func (r *Retrier) calcSleep(i int) time.Duration {
+	// lock unsafe rand prng
+	r.randMu.Lock()
+	defer r.randMu.Unlock()
+	// 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
+}

+ 0 - 28
retrier/retrier_legacy.go

@@ -1,28 +0,0 @@
-// +build !go1.7
-
-package retrier
-
-import "time"
-
-// 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++
-		}
-	}
-}