I am working on a library where I make Http call to my service and if my service machine doesn't respond back (there is a socket timeout or connect timeout), I add them to my local blockList
and if machine is blocked 5 times then I don't make call to them.
So let's say if machineA
is not responding (throwing RestClientException)
, I will call onFailure
method everytime and keep incrementing the counter and then while making call to machineA
again, I check isBlocked
method by passing machineA
as hostname and 5 as threshold so if machineA
has been blocked 5 times then I don't make call to them at all. My library is multithreaded so that's why I am using volatile here as I want all threads to see same value.
Below is what I have in DataMapping
class:
public static volatile ConcurrentHashMap<String, AtomicInteger> blockedHosts =
new ConcurrentHashMap<String, AtomicInteger>();
boolean isBlocked(String hostname, int threshold) {
AtomicInteger count = blockedHosts.get(hostname);
return count != null && count.get() >= threshold;
}
void onFailure(String hostname) {
AtomicInteger newValue = new AtomicInteger();
AtomicInteger val = blockedHosts.putIfAbsent(hostname, newValue);
// no need to care about over-reaching 5 here
(val == null ? newValue : val).incrementAndGet();
}
void onSuccess(String hostname) {
blockedHosts.remove(hostname);
}
Problem Statement:-
Now I want to add one more feature which is - If machineA
is blocked (since its blocking count is >= 5) then I want to keep it block for x interval. I will be having another parameter (key.getInterval())
which will tell us for how long I want to keep this machine blocked and after that interval is elapsed, then only I will start making call to them. I am not able to understand how to add this feature?
Below is my main thread code where I am using DataMapping
methods to check whether hostname is blocked or not and also to block hostnames.
@Override
public DataResponse call() {
ResponseEntity<String> response = null;
List<String> hostnames = some_code_here;
for (String hostname : hostnames) {
// If hostname is in block list, skip sending request to this host
if (DataMapping.isBlocked(hostname)) {
continue;
}
try {
String url = createURL(hostname);
response = restTemplate.exchange(url, HttpMethod.GET, key.getEntity(), String.class);
DataMapping.onSuccess(hostname);
// some code here to return the response if successful
} catch (RestClientException ex) {
// adding to block list
DataMapping.onFailure(hostname);
}
}
return new DataResponse(DataErrorEnum.SERVER_UNAVAILABLE, DataStatusEnum.ERROR);
}
How can I block a particular machine for a particular period of time and as soon as that interval is elapsed then only start making calls to them?