failsafe-lib / failsafe

Fault tolerance and resilience patterns for the JVM
https://failsafe.dev
Apache License 2.0
4.16k stars 295 forks source link

[Question] Is it possible to have multiple Fallback policies in one Failsafe executor? #374

Closed mjalvarez closed 8 months ago

mjalvarez commented 8 months ago

I want to use multiple endpoints as backups whenever the primary endpoint fails. I tried the setup below, but it only executes the final fallback policy.

List<Policy> policies = []

policies.add(Fallback.builder({ -> sendToBackup("endpoint1") }).build())    // <--- this fallback will fail
policies.add(Fallback.builder({ -> sendToBackup("endpoint2")  }).build())   // <--- this fallback will fail
policies.add(Fallback.builder({ -> sendToBackup("endpoint3")  }).build())   // <--- this fallback will succeed
policies.add(Fallback.builder({ -> sendToBackup("endpoint4")  }).build())   // <--- this should not be executed

FailsafeExecutor executor = Failsafe.with(policies)

executor.run({ -> sendToPrimary() }  // will fail
Tembrel commented 8 months ago

Try reversing the order of policies passed to Failsafe.with(...). The "innermost" policy is the last element of the list, and the "outermost" policy is the first element of the list.

I expanded your example into a public gist, where the key line is Collections.reverse(policies).

mjalvarez commented 8 months ago

Thanks @Tembrel ! I think that did the trick. 😄

Just out of curiosity, is it possible to add retry policy for each fallback?

Tembrel commented 8 months ago

I'm assuming based on the implied context of your example that what you want is to be able to try a series of endpoints, with some retrying for each one in turn, until one succeeds (or all fail).

If so, I think a more straightforward way to do that is to use a loop over the send action for each endpoint, each one wrapped in a RetryPolicy, as in this gist. In particular, see the runMultiple method. That implementation is obviously not production ready:

Each of these points could be addressed fairly easily.

Again, assuming that's what you are ultimately trying to do, there is no need for an elaborate composition of fallbacks and retry policies when a simple loop does the trick.

mjalvarez commented 8 months ago

Gotcha. I was thinking along the lines of composition fallback + retry policies. Glad I consulted first.

Again, thank you so much for the answers, and the efforts of illustrating in a simple gist. Have a happy new year! 🍻