/** * Private method that determines whether a given task should be re-tried based on the given * {@code Throwable} that caused failure. If this returns {@code true} then the task should be * re-tried. Otherwise, the task should be dropped. */ private boolean shouldRetry(ScheduledTaskImpl task, Throwable t) { // NOTE: as a first-pass implementation this simply instructs the // caller to try again if retry is requested, but other strategies // (like the number of times re-tried) might be considered later if ((t instanceof ExceptionRetryStatus) && (((ExceptionRetryStatus) t).shouldRetry())) { return true; } // we're not re-trying the task, so log that it's being dropped if (logger.isLoggable(Level.WARNING)) { if (task.isRecurring()) { logger.logThrow( Level.WARNING, t, "skipping a recurrence of " + "a task that failed with a non-retryable " + "exception: {0}", task); } else { logger.logThrow( Level.WARNING, t, "dropping a task that " + "failed with a non-retryable exception: {0}", task); } } return false; }
/** {@inheritDoc} */ public void run() { logger.log(Level.FINE, "Starting a consumer for transactions"); notifyThreadJoining(); try { while (true) { // wait for the next task, at which point we may get // interrupted and should therefore return ScheduledTaskImpl task = (ScheduledTaskImpl) (backingQueue.getNextTask(true)); // run the task, checking if it completed if (executeTask(task, false, true)) { // if it's a recurring task, schedule the next run if (task.isRecurring()) { long nextStart = task.getStartTime() + task.getPeriod(); task = new ScheduledTaskImpl(task, nextStart); backingQueue.addTask(task); } // if it has dependent tasks, schedule the next one TaskQueueImpl queue = (TaskQueueImpl) (task.getTaskQueue()); if (queue != null) { queue.scheduleNextTask(); } } } } catch (InterruptedException ie) { if (logger.isLoggable(Level.FINE)) { logger.logThrow(Level.FINE, ie, "Consumer is finishing"); } } catch (Exception e) { // this should never happen, since running the task should // never throw an exception that isn't handled logger.logThrow(Level.SEVERE, e, "Fatal error for consumer"); } finally { notifyThreadLeaving(); } }