Fluent retries
Not long ago, I was working with an unreliable external service which our application was depending upon. By unreliable, I mean that the service wouldn’t necessarily return a successful response in the first try. After discussions with the service provider, we felt that this necessitated a retry mechanism: call the service until it returns a successful response, or error out after N - say three - retries. Also, a particular response code indicated that retries may not have any effect.
A knee-jerk reaction to write the code was to use a while
loop:
What if you wanted to decouple the act of retrying from what gets tried?
What if you wanted to test the retry logic?
What if another place in the code warranted a retry mechanism?
Doesn’t the while
and the counter increment hurt your eyes?
Wouldn’t it be dreamy if a more readable Fluent API were available - such as this one?
See how well this reads. Poetic (almost)!
Fortunately, it is not too difficult to cook up an implementation for the Retry
fluent interface. The idea is to accumulate all building blocks - such as what defines the service call, what it means to short-circuit the retry mechanism, how many times should retry be performed at max, etc. - into a context object. In this case, an object of the Retry
class serves as the context.
Method chaining can be used to enrich the context with various building blocks. Keep returning this
from each building block, so that the next building block can be executed.
It’s a matter of personal choice to give or not to give sensible defaults to the building blocks.
One may also add validations within the Execute
method to check if all the necessary building blocks are in place.
Let’s write a quick and sweet test to assert that atmost N retries are carried out:
Ofcourse, fluent API is not a silver bullet to the world’s problems. You silently inherit the problem of temporal coupling: instead of passing in the must-have building blocks (like task to perform, maximum number of tries) in a constructor, you introduce methods like Do
and Atmost
which must be called before Execute
. Fluent APIs are also not very debug-friendly.
In the end, it is about how the artist in you wants to express herself/himself.