Skip to content

Commit

Permalink
Refactor code
Browse files Browse the repository at this point in the history
  • Loading branch information
thedevsaddam committed Feb 26, 2018
1 parent 9cbffc5 commit 95c28fa
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 23 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func main() {
if err != nil {
panic(err)
}
log.Println(res[0].Interface(), res[1].Interface())
log.Println(res)
}

```
Expand Down
39 changes: 22 additions & 17 deletions retry.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,18 @@ func DoFunc(attempt int, sleep time.Duration, fn func() error) error {

// Do try to execute the function by its value, function can take variadic arguments and return multiple return.
// You must put error as the last return value so that DoFunc can take decision that the call failed or not
func Do(attempt int, sleep time.Duration, fn interface{}, args ...interface{}) ([]reflect.Value, error) {
func Do(attempt int, sleep time.Duration, fn interface{}, args ...interface{}) ([]interface{}, error) {

// if the fn is not a function then return error
vfn := reflect.ValueOf(fn)

// if the fn is not a function then return error
if vfn.Type().Kind() != reflect.Func {
return nil, errors.New("retry: fn is not a function")
}

// if the functions in not variadic then return the argument missmatch error
if !vfn.Type().IsVariadic() {
if vfn.Type().NumIn() != len(args) {
return nil, errors.New("retry: fn argument mismatch")
}
if !vfn.Type().IsVariadic() && (vfn.Type().NumIn() != len(args)) {
return nil, errors.New("retry: fn argument mismatch")
}

// if the function does not return anything, we can't catch if an error occur or not
Expand All @@ -55,19 +54,25 @@ func Do(attempt int, sleep time.Duration, fn interface{}, args ...interface{}) (
}

// call the fn with arguments
out := vfn.Call(in)
out := []interface{}{}
for _, o := range vfn.Call(in) {
out = append(out, o.Interface())
}

// if the last return value is type of error and it is not nil then attempt to retry
if err, ok := out[len(out)-1:][0].Interface().(error); ok {
if err != nil {
attempt--
if attempt > 0 {
time.Sleep(sleep)
return Do(attempt, sleep, fn, args...)
}
return out, err
// if the last value is not error then return an error
err, ok := out[len(out)-1].(error)
if !ok && out[len(out)-1] != nil {
return nil, errors.New("retry: fn return's right most value must be an error")
}

if err != nil {
attempt--
if attempt > 0 {
time.Sleep(sleep)
return Do(attempt, sleep, fn, args...)
}
return out, err
}

return out, nil
return out[:len(out)-1], nil
}
11 changes: 6 additions & 5 deletions retry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,10 @@ func TestDo(t *testing.T) {
ExpectedError: true,
},
{
Tag: "As 'noErrorFunc' is does not return error we silently try to execute the func only once",
Func: noErrorFunc,
Result: false,
Tag: "As 'noErrorFunc' is does not return error we silently try to execute the func only once",
Func: noErrorFunc,
Result: false,
ExpectedError: true,
},
}

Expand All @@ -124,8 +125,8 @@ func TestDo(t *testing.T) {
}

if !tc.ExpectedError && out != nil {
if out[0].Interface() != tc.Result {
t.Errorf("Failed: %s \nExpected: %v \nGot: %v", tc.Tag, tc.Result, out[0].Interface())
if out[0] != tc.Result {
t.Errorf("Failed: %s \nExpected: %v \nGot: %v", tc.Tag, tc.Result, out[0])
}
}
}
Expand Down

0 comments on commit 95c28fa

Please sign in to comment.