package com.sequenceiq.cloudbreak.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class PollingService<T> {
private static final Logger LOGGER = LoggerFactory.getLogger(PollingService.class);
/**
* Executes a {@link StatusCheckerTask} until it signals success, or the
* maximum attempts are reached. A {@link StatusCheckerTask} has no
* restrictions about what kind of tasks it should do, it just needs to
* return if the task succeeded or not. If maxAttempts is lower than 0,
* there will be no timeout.
*
* @param interval sleeps this many milliseconds between status checking attempts
* @param maxAttempts signals how many times will the status check be executed before timeout
*/
public PollingResult pollWithTimeout(StatusCheckerTask<T> statusCheckerTask, T t, int interval, int maxAttempts, int maxFailure) {
boolean success = false;
boolean timeout = false;
int attempts = 0;
int failures = 0;
Exception actual = null;
boolean exit = statusCheckerTask.exitPolling(t);
while (!success && !timeout && !exit) {
LOGGER.info("Polling attempt {}.", attempts);
try {
success = statusCheckerTask.checkStatus(t);
} catch (Exception ex) {
LOGGER.warn("Exception occurred in the polling: {}", ex.getMessage(), ex);
failures++;
actual = ex;
}
if (failures >= maxFailure) {
LOGGER.info("Polling failure reached the limit which was {}, poller will drop the last exception.", maxFailure);
statusCheckerTask.handleException(actual);
return PollingResult.FAILURE;
}
if (success) {
LOGGER.info(statusCheckerTask.successMessage(t));
return PollingResult.SUCCESS;
}
sleep(interval);
attempts++;
if (maxAttempts > 0) {
timeout = attempts >= maxAttempts;
}
exit = statusCheckerTask.exitPolling(t);
}
if (timeout) {
LOGGER.info("Poller timeout.");
statusCheckerTask.handleTimeout(t);
return PollingResult.TIMEOUT;
} else if (exit) {
LOGGER.info("Poller exiting.");
return PollingResult.EXIT;
}
return PollingResult.SUCCESS;
}
public PollingResult pollWithTimeoutSingleFailure(StatusCheckerTask<T> statusCheckerTask, T t, int interval, int maxAttempts) {
return pollWithTimeout(statusCheckerTask, t, interval, maxAttempts, 1);
}
private void sleep(int duration) {
try {
Thread.sleep(duration);
} catch (InterruptedException e) {
LOGGER.info("Interrupted exception occurred during polling.", e);
Thread.currentThread().interrupt();
}
}
}