package com.bizo.asperatus.tracker.impl;
import java.util.concurrent.Callable;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Encapsulates running a task with retries.
*/
public final class RetryingScheduler {
private static final Logger logger = Logger.getLogger(RetryingScheduler.class.getName());
private final ScheduledExecutorService executor;
public RetryingScheduler(final ScheduledExecutorService executor) {
this.executor = executor;
}
public void schedule(final Callable<?> task, final int numRetries, final int retryDelaySeconds) {
schedule(task, 0, numRetries, retryDelaySeconds);
}
/**
* Schedule a task for execution. If the task throws an exception, it will be retried.
*
* @param task
* task to call
* @param initialDelaySeconds
* initial delay (seconds) before executing the task
* @param numRetries
* number of times to retry task
* @param retryDelaySeconds
* delay (seconds) before retrying a failed task
*/
public void schedule(
final Callable<?> task,
final int initialDelaySeconds,
final int numRetries,
final int retryDelaySeconds) {
executor.schedule(
new RetryWrapper(task, numRetries, retryDelaySeconds, null),
initialDelaySeconds,
TimeUnit.SECONDS);
}
private final class RetryWrapper implements Runnable {
private final Callable<?> call;
private final int retry;
private final int retryDelay;
private final Exception lastThrown;
private RetryWrapper(final Callable<?> call, final int retry, final int retryDelay, final Exception lastThrown) {
this.call = call;
this.retry = retry;
this.retryDelay = retryDelay;
this.lastThrown = lastThrown;
}
public void run() {
if (retry <= 0) {
logger.log(Level.WARNING, String.format("Failed to run task: %s", call), lastThrown);
return;
}
try {
call.call();
} catch (final Exception e) {
logger.log(Level.FINEST, String.format("Failed to run task: %s", call), e);
executor.schedule(new RetryWrapper(call, retry - 1, retryDelay, e), retryDelay, TimeUnit.SECONDS);
}
}
}
}