/*
* Copyright 2007-2010 Sun Microsystems, Inc.
*
* This file is part of Project Darkstar Server.
*
* Project Darkstar Server is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation and
* distributed hereunder to you.
*
* Project Darkstar Server is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Sun designates this particular file as subject to the "Classpath"
* exception as provided by Sun in the LICENSE file that accompanied
* this code.
*
* --
*/
package com.sun.sgs.app;
import java.io.Serializable;
/**
* Provides facilities for scheduling tasks. Each task is a serializable
* object that can be scheduled to be run now, at some time in the future, or
* periodically. For the methods that run at some delayed point in the
* future, the delay is taken from the moment when the scheduling method
* was called.
* <p>
* For all methods on <code>TaskManager</code>, if the instance of
* <code>Task</code> provided does not implement <code>ManagedObject</code>
* then the <code>TaskManager</code> will persist the <code>Task</code>
* until it finishes. This provides durability, and is particularly
* convenient for simple tasks that the developer doesn't wish to manage
* and remove manually. However, if the <code>Task</code> does implement
* <code>ManagedObject</code>, then it's assumed that the <code>Task</code>
* is already managed, and it is up to the developer to remove it from
* the <code>DataManager</code> when finished.
* <p>
* If the instance of <code>Task</code> provided to any of these methods
* is an instance of a class that has the <code>RunWithNewIdentity</code>
* annotation then that task will be run with a new owning identity. Periodic
* tasks will use this same owning identity for all recurrences. In
* practical terms, this means that the system will be able to recognize
* these tasks as distinct behavior from other tasks in the system.
* <p>
* Note that there is no assumed ordering provided by implementations of
* this interface. If two tasks are scheduled in a given transaction, it is
* undefined which task will run or complete first. Likewise, if a task
* is scheduled and then a second scheduled in a later transaction, there
* is no guarantee that the task scheduled in the previous transaction
* will complete first. If any ordering or dependency is required, this
* should be implemented within the tasks themselves.
*
* @see AppContext#getTaskManager
* @see Task
* @see RunWithNewIdentity
*/
public interface TaskManager {
/**
* Schedules a task to run now. The <code>TaskManager</code> will call the
* task's {@link Task#run run} method as soon as possible after the
* completion of the task in which this method is called, according to its
* scheduling algorithm. <p>
*
* If the call to the <code>run</code> method throws an exception, that
* exception implements {@link ExceptionRetryStatus}, and its {@link
* ExceptionRetryStatus#shouldRetry shouldRetry} method returns
* <code>true</code>, then the <code>TaskManager</code> will make further
* attempts to run the task. It will continue those attempts until either
* an attempt succeeds or it notices an exception is thrown that is not
* retryable. The <code>TaskManager</code> is permitted to treat a
* non-retryable exception as a hint. In particular, a task that throws a
* non-retryable exception may be retried if the node running the task
* crashes.
*
* @param task the task to run
* @throws IllegalArgumentException if <code>task</code> does not
* implement {@link Serializable}
* @throws TaskRejectedException if the <code>TaskManager</code> refuses
* to accept the task because of resource limitations
* @throws TransactionException if the operation failed because of a
* problem with the current transaction
*/
void scheduleTask(Task task);
/**
* Schedules a task to run after a delay. The <code>TaskManager</code>
* will wait for the specified number of milliseconds, and then call the
* task's {@link Task#run run} method as soon as possible after the
* completion of the task in which this method is called, according to its
* scheduling algorithm. <p>
*
* If the call to the <code>run</code> method throws an exception, that
* exception implements {@link ExceptionRetryStatus}, and its {@link
* ExceptionRetryStatus#shouldRetry shouldRetry} method returns
* <code>true</code>, then the <code>TaskManager</code> will make further
* attempts to run the task. It will continue those attempts until either
* an attempt succeeds or it notices an exception is thrown that is not
* retryable. The <code>TaskManager</code> is permitted to treat a
* non-retryable exception as a hint. In particular, a task that throws a
* non-retryable exception may be retried if the node running the task
* crashes.
*
* @param task the task to run
* @param delay the number of milliseconds to delay before running the
* task
* @throws IllegalArgumentException if <code>task</code> does not
* implement {@link Serializable}, or if delay is less than
* <code>0</code>
* @throws TaskRejectedException if the <code>TaskManager</code> refuses
* to accept the task because of resource limitations
* @throws TransactionException if the operation failed because of a
* problem with the current transaction
*/
void scheduleTask(Task task, long delay);
/**
* Schedules a task to run periodically after a delay. The
* <code>TaskManager</code> will wait for the specified number of
* milliseconds, and then call the task's {@link Task#run run} method as
* soon as possible after the completion of the task in which this method
* is called, according to its scheduling algorithm. It will also arrange
* to run the task periodically at the specified interval following the
* delay until the {@link PeriodicTaskHandle#cancel
* PeriodicTaskHandle.cancel} method is called on the associated handle.
* At the start of each period, which occurs <code>period</code>
* milliseconds after the scheduled start of the previous period, a new
* task will be scheduled to run. The <code>TaskManager</code> will make
* a best effort to run a new task in each period, but even if the task
* cannot be run in one period, a new task will always be scheduled for
* the following period. The <code>TaskManager</code> will wait until
* the current attempt to run the task has ended before making another
* attempt to run it, regardless of whether the attempts are for the same
* or different periods.
* <p>
* If the call to the <code>run</code> method throws an exception, that
* exception implements {@link ExceptionRetryStatus}, and its {@link
* ExceptionRetryStatus#shouldRetry shouldRetry} method returns
* <code>true</code>, then the <code>TaskManager</code> will make further
* attempts to run the task. It will continue those attempts until either
* an attempt succeeds or it notices an exception is thrown that is not
* retryable. Note that calls to <code>PeriodicTaskHandle.cancel</code>
* have no effect on attempts to retry a task after the first attempt. The
* <code>TaskManager</code> is permitted to treat a non-retryable exception
* as a hint. In particular, a task that throws a non-retryable exception
* may be retried if the node running the task crashes.
*
* @param task the task to run
* @param delay the number of milliseconds to delay before running the
* task
* @param period the number of milliseconds that should elapse between
* the starts of periodic attempts to run the task
* @return a handle for managing the scheduling of the task
* @throws IllegalArgumentException if <code>task</code> does not
* implement {@link Serializable}, if delay is less than
* <code>0</code>, or if period is less than <code>0</code>
* @throws TaskRejectedException if the <code>TaskManager</code> refuses
* to accept the task because of resource limitations
* @throws TransactionException if the operation failed because of a
* problem with the current transaction
*/
PeriodicTaskHandle schedulePeriodicTask(Task task, long delay,
long period);
/**
* Returns {@code true} if the currently running task should do more work
* if it is available. Otherwise, returns {@code false}. This method
* should always return {@code true} until the current task has done enough
* work such that the work required to reschedule the task is negligible in
* comparison to the work already done.
*
* @return {@code true} if the currently running task should do more work
* if possible; otherwise {@code false}
* @throws TransactionException if the operation failed because of a
* problem with the current transaction
*/
boolean shouldContinue();
}