Problem Statement:
- On an multi-threaded environment a record shall be created in the database by one thread and another thread may be interested to fetch the record. Due to the multi threading nature, the second thread may need to wait or retry couple of times before getting hold of the record.
- After performing an action in remoete web service, we might need to poll the service for the updated status. (though this is inefficient than using the message or event based communication).
Both of the above problem statements have a common theme of "getting the latest data by polling". A simple implementation would be put an for loop for the number of retries to fetch the data. if the data is fetched, the value is immediately returned.
@SneakyThrows
public Optional<Employee> getRecord(Long id){
for(int i=0; i< 10; i++){
Optional<Employee> emp = employeeRepository.findById(id);
if(emp.isPresent()) return emp;
Thread.sleep(200)
}
return Optional.empty();
}
Let us consider the scenario, where we would need to write the similar code block to retrieve the data from an external web serivces, a similar implementation needs to be written as well.
The above-retry logic can be implemented using Generics and functional interfaces as below.
Generic function
public class Utils{
@SneakyThrows
public static <T> Optional<T> getWithRetry( Supplier<Optional<T>> supplier, int retry){
for(int i=0; i < retry; i++){
Optional<T> data = supplier.get();
if(data.isPresent())
return data;
Thread.sleep(200);
}
return Optional.empty();
}
}
Invoking the function
public Optional<Employee> getRecord(Long id){
return Utils.getWithRetry(
() -> employeeRepository.findById(id)
, 10);
}
Other data fetching functions can be defined as Supplier interfaces or lambda expressions and invoked using the 'getWithRetry' function. By implementing the Generic function, the retry logic can be reused across as needed.
Top comments (0)