Skip to content

Commit

Permalink
Merge pull request #16 from buildkite/do-funcs
Browse files Browse the repository at this point in the history
Add DoFunc{,2,3}
  • Loading branch information
DrJosh9000 authored Feb 28, 2024
2 parents e3d1bdb + 1289264 commit 0dfc7b1
Showing 1 changed file with 48 additions and 4 deletions.
52 changes: 48 additions & 4 deletions retrier.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,9 @@ func Exponential(base, adjustment time.Duration) (Strategy, string) {
//
// Examples of a small, medium and large initial time.Second growing over 10 attempts:
//
// 100ms → 133ms → 177ms → 237ms → 316ms → 421ms → 562ms → 749ms → 1000ms
// 1.0s → 1.5s → 2.4s → 3.7s → 5.6s → 8.7s → 13.3s → 20.6s → 31.6s
// 5s → 9s → 14s → 25s → 42s → 72s → 120s → 208s → 354s
//
// 100ms → 133ms → 177ms → 237ms → 316ms → 421ms → 562ms → 749ms → 1000ms
// 1.0s → 1.5s → 2.4s → 3.7s → 5.6s → 8.7s → 13.3s → 20.6s → 31.6s
// 5s → 9s → 14s → 25s → 42s → 72s → 120s → 208s → 354s
func ExponentialSubsecond(initial time.Duration) (Strategy, string) {
if initial < 1*time.Millisecond {
panic("ExponentialSubsecond retry strategies must have an initial delay of at least 1 millisecond")
Expand Down Expand Up @@ -284,6 +283,51 @@ func (r *Retrier) DoWithContext(ctx context.Context, callback func(*Retrier) err
}
}

// DoFunc is a helper for retrying callback functions that return a value or an
// error. It returns the last value returned by a call to callback, and reports
// an error if none of the calls succeeded.
// (Note this is not a method of Retrier, since methods can't be generic.)
func DoFunc[T any](ctx context.Context, r *Retrier, callback func(*Retrier) (T, error)) (T, error) {
var t T
err := r.DoWithContext(ctx, func(rt *Retrier) error {
var err error
t, err = callback(rt)
return err
})
return t, err
}

// DoFunc2 is a helper for retrying callback functions that return two value or
// an error. It returns the last values returned by a call to callback, and
// reports an error if none of the calls succeeded.
// (Note this is not a method of Retrier, since methods can't be generic.)
func DoFunc2[T1, T2 any](ctx context.Context, r *Retrier, callback func(*Retrier) (T1, T2, error)) (T1, T2, error) {
var t1 T1
var t2 T2
err := r.DoWithContext(ctx, func(rt *Retrier) error {
var err error
t1, t2, err = callback(rt)
return err
})
return t1, t2, err
}

// DoFunc3 is a helper for retrying callback functions that return 3 values or
// an error. It returns the last values returned by a call to callback, and
// reports an error if none of the calls succeeded.
// (Note this is not a method of Retrier, since methods can't be generic.)
func DoFunc3[T1, T2, T3 any](ctx context.Context, r *Retrier, callback func(*Retrier) (T1, T2, T3, error)) (T1, T2, T3, error) {
var t1 T1
var t2 T2
var t3 T3
err := r.DoWithContext(ctx, func(rt *Retrier) error {
var err error
t1, t2, t3, err = callback(rt)
return err
})
return t1, t2, t3, err
}

func (r *Retrier) sleepOrDone(ctx context.Context, nextInterval time.Duration) error {
if r.sleepFunc == nil {
t := time.NewTimer(nextInterval)
Expand Down

0 comments on commit 0dfc7b1

Please sign in to comment.