Skip to content

Commit

Permalink
registry: Add retryable executor and use it in parser
Browse files Browse the repository at this point in the history
  • Loading branch information
cdamian committed Mar 22, 2023
1 parent 0efc31b commit 62d3d77
Show file tree
Hide file tree
Showing 6 changed files with 386 additions and 149 deletions.
118 changes: 118 additions & 0 deletions registry/exec/exec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package exec

import (
"errors"
"fmt"
"strings"
"time"
)

type RetryableExecutor[T any] interface {
ExecWithFallback(execFn func() (T, error), fallbackFn func() error) (T, error)
}

type retryableExecutor[T any] struct {
opts *Opts
}

func NewRetryableExecutor[T any](opts ...OptsFn) RetryableExecutor[T] {
execOpts := NewDefaultExecOpts()

for _, opt := range opts {
opt(execOpts)
}

return &retryableExecutor[T]{
execOpts,
}
}

func (r *retryableExecutor[T]) ExecWithFallback(execFn func() (T, error), fallbackFn func() error) (res T, err error) {
if execFn == nil {
return res, errors.New("no exec function provided")
}

if fallbackFn == nil {
return res, errors.New("no fallback function provided")
}

execErr := &Error{}

for i := uint(0); i < r.opts.maxCount; i++ {
res, err = execFn()

if err == nil {
return res, nil
}

execErr.AddErr(fmt.Errorf("exec function error: %w", err))

if err = fallbackFn(); err != nil && !r.opts.retryOnFallbackError {
execErr.AddErr(fmt.Errorf("fallback function error: %w", err))

return res, execErr
}

time.Sleep(r.opts.errTimeout)
}

return res, execErr
}

const (
defaultExecMaxCount = 3
defaultErrTimeout = 0 * time.Second
defaultRetryOnFallbackError = true
)

type Opts struct {
maxCount uint
errTimeout time.Duration
retryOnFallbackError bool
}

func NewDefaultExecOpts() *Opts {
return &Opts{
maxCount: defaultExecMaxCount,
errTimeout: defaultErrTimeout,
retryOnFallbackError: defaultRetryOnFallbackError,
}
}

type OptsFn func(opts *Opts)

func WithMaxCount(maxCount uint) OptsFn {
return func(opts *Opts) {
opts.maxCount = maxCount
}
}

func WithErrTimeout(errTimeout time.Duration) OptsFn {
return func(opts *Opts) {
opts.errTimeout = errTimeout
}
}

func WithRetryOnFallBackError(retryOnFallbackError bool) OptsFn {
return func(opts *Opts) {
opts.retryOnFallbackError = retryOnFallbackError
}
}

type Error struct {
errs []error
}

func (e *Error) AddErr(err error) {
e.errs = append(e.errs, err)
}

func (e *Error) Error() string {
sb := strings.Builder{}

for i, err := range e.errs {
sb.WriteString(fmt.Sprintf("error %d: %s\n", i, err))
}

return sb.String()
}
147 changes: 0 additions & 147 deletions registry/parser.go

This file was deleted.

Loading

0 comments on commit 62d3d77

Please sign in to comment.