package com.sequenceiq.cloudbreak.cloud.scheduler;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.inject.Inject;
import org.springframework.stereotype.Component;
import com.google.common.util.concurrent.ListenableScheduledFuture;
import com.google.common.util.concurrent.ListeningScheduledExecutorService;
import com.sequenceiq.cloudbreak.cloud.task.FetchTask;
import com.sequenceiq.cloudbreak.cloud.task.PollTask;
@Component
public class SyncPollingScheduler<T> {
private static final int POLLING_INTERVAL = 5;
private static final int MAX_POLLING_ATTEMPT = 1000;
private static final int FAILURE_TOLERANT_ATTEMPT = 3;
@Inject
private ListeningScheduledExecutorService scheduler;
public T schedule(PollTask<T> task) throws ExecutionException, InterruptedException, TimeoutException {
return schedule(task, POLLING_INTERVAL, MAX_POLLING_ATTEMPT, FAILURE_TOLERANT_ATTEMPT);
}
public T schedule(PollTask<T> task, int interval, int maxAttempt, int maxFailureTolerant) throws ExecutionException, InterruptedException, TimeoutException {
T result;
int actualFailureTolerant = 0;
for (int i = 0; i < maxAttempt; i++) {
if (task.cancelled()) {
throw new CancellationException("Task was cancelled.");
}
try {
ListenableScheduledFuture<T> ft = schedule(task, interval);
result = ft.get();
if (task.completed(result)) {
return result;
}
} catch (Exception ex) {
actualFailureTolerant++;
if (actualFailureTolerant >= maxFailureTolerant) {
throw ex;
}
}
}
throw new TimeoutException(String.format("Task did not finished within %d seconds", interval * maxAttempt));
}
public ListenableScheduledFuture<T> schedule(FetchTask<T> task, int interval) {
return scheduler.schedule(task, interval, TimeUnit.SECONDS);
}
}