Do not wrap original err on fallback
f you want to implement a conditional fallback, it's important that the original error is not wrapped when returned from the fallback. Otherwise it becomes impossible for the caller to distinguish e.g. ErrCircuitOpen from ErrTimeout.
please provide an example of a conditional fallback and caller which you are having trouble implementing without this patch
The following code works:
func ExampleError() {
err := hystrix.Go("my_command", func() error {
time.Sleep(2 * time.Minute)
return nil
}, nil)
switch <-err {
case hystrix.ErrTimeout:
fmt.Println("Timeout")
default:
fmt.Println("Unknown error")
}
// Output: Timeout
}
However, adding a very simple fallback makes it fail:
func ExampleError() {
err := hystrix.Go("my_command", func() error {
time.Sleep(2 * time.Minute)
return nil
}, func(err error) {
return err
})
switch <-err {
case hystrix.ErrTimeout:
fmt.Println("Timeout")
default:
fmt.Println("Unknown error")
}
// Output: Timeout
}
This seems to be wrong and I'd probably go even further, suggesting to get rid of all the fallback error wrapping, now that I've written this example.
Now where do I want to use this? In case of an error, I want to potentially return a previously cached result. If it's not available, I'd like to propagate the error to the outside of the operation. Depending on the particular result, I would like to retry the operation. For example, I'd want to retry on a max concurrency error after waiting a little. I do not want to apply the same logic on e.g. Circuit Closed. With the current error wrapping, there is no good way to tell those two cases apart - at least not when using a fallback function.