Dealing with Unreliable Components
As a software consultant sometimes I have to deal with components or systems that are not very reliable. Sometimes it is because those systems were not made using the common software development practices like testing, careful design, thread safety etc. Other times it is a conscious choice made in pursuit of some other goal such as performance.
A certain class of problems can be simply dealt with trying to repeat an operation several times until it succeeds. This is the case with the optimistic class of algorithms like optimistic database locking.
For this reason, a couple of years ago I took upon myself to implement a library that helps me deal with these kind of scenarios. I called the library unreliable.
The library has evolved since then, but the basic functionality is pretty simple: it allows you to perform an operation several times until it succeeds.
Unreliable.tenaciously(() -> unreliableService.doSomething()); or through a static import:
tenaciously(() -> unreliableService.doSomething()); this will perform unreliableService.doSomething() either until it passes or when it reaches the maximum number of retries. By default the maximum number of retries is 3.
If you want to specify the number of retries, you can add a second parameter:
tenaciously(() -> unreliableService.doSomething(), 5); This will retry the operation up to 5 times.
The enclosed operation can also return a value:
Long result = tenaciously(() -> unreliableService.calculateSomething());
System.out.println("The result is: " + result); If after X times it still fails, a RuntimeException will be thrown:
try { Unreliable.tenaciously(() -> unreliableService.doSomething());} catch (RuntimeException e) { System.err.println("I got tired of trying: " + e.getCause().getMessage()); } If you want to be really stubborn you can keep trying infinitely:
keepTrying(() -> unreliableService.doSomething()); In the following posts I will talk about the more advanced features of unreliable.