com.atlassian.scheduler.compat
Interface CompatibilityPluginScheduler

All Known Implementing Classes:
AutoDetectingCompatibilityPluginScheduler, ClusteredCompatibilityPluginScheduler, LocalOnlyCompatibilityPluginScheduler

@PublicApi
public interface CompatibilityPluginScheduler

Provides a compatibility abstraction of scheduling cluster-safe tasks.

Plugins have historically either scheduled work through the PluginScheduler in the Shared Access Layer or dealt with Quartz directly. The atlassian-scheduler library is intended to replace both of these by hiding most of the complexity behind dealing with scheduler systems, including making it easier for plugins to contend with lifecycle and ClassLoader problems.

Plugins that do not need to run on older versions of Atlassian products should adopt the atlassian-scheduler library directly as soon as the product does, but since many plugin developers need to support older versions of the products as well, this is not always possible.

This component provides a middle ground. The interface is closer in design to that of atlassian-scheduler, but it will use SAL's PluginScheduler for its implementation when atlassian-scheduler is not available. These details are mostly hidden from the plugin developer; where differences in behaviour were unavoidable, they are explicitly called out in the documentation. In particular:

Since:
v1.0

Method Summary
 JobInfo getJobInfo(String jobKey)
          Returns information about a scheduled clustered job, if it exists.
 void registerJobHandler(JobHandlerKey jobHandlerKey, JobHandler jobHandler)
          Registers a job handler to accept jobs.
 void scheduleClusteredJob(String jobKey, JobHandlerKey jobHandlerKey, Date startTime, long repeatInterval)
          Schedule the given job to run once per cluster node.
 void unregisterJobHandler(JobHandlerKey jobHandlerKey)
          Unregisters the specified job handler.
 void unscheduleClusteredJob(String jobKey)
          Unschedule the given job for the entire cluster.
 

Method Detail

registerJobHandler

void registerJobHandler(JobHandlerKey jobHandlerKey,
                        JobHandler jobHandler)
Registers a job handler to accept jobs.

WARNING: Unlike the atlassian-scheduler, this compatibility library requires that the job handler be registered exactly once before any jobs are scheduled. The compatibility implementation that uses SAL's plugin scheduler binds the scheduled job to the implementation that was registered at the time that it was scheduled. If there is no such implementation registered, then there is nothing to associate the job with. If the implementation later changed, the job would already bound with the old registration. To prevent inconsistent behaviour, multiple registration is explicitly disallowed.

Parameters:
jobHandlerKey - the key that associates jobs with this job handler
jobHandler - the job handler which will process job requests
Throws:
IllegalArgumentException - if the job handler key is already registered

unregisterJobHandler

void unregisterJobHandler(JobHandlerKey jobHandlerKey)
Unregisters the specified job handler.

During cleanup, the plugin should call this for each job handler that it has registered. Whether or not this automatically unschedules that job handler's jobs is implementation-dependent, as it makes sense for the PluginScheduler implementation to do this and does not make sense for the atlassian-scheduler implementation.

Parameters:
jobHandlerKey - the key for the job handler that will be unregistered.

scheduleClusteredJob

void scheduleClusteredJob(String jobKey,
                          JobHandlerKey jobHandlerKey,
                          Date startTime,
                          long repeatInterval)
Schedule the given job to run once per cluster node.

WARNING: it is very important not to try to call this method until the underlying application is fully started. You should implement com.atlassian.sal.api.lifecycle.LifecycleAware and call scheduleJob() only on com.atlassian.sal.api.lifecycle.LifecycleAware#onStart().

Only one node in the cluster needs to do this. If every node in the cluster schedules the same job to run immediately, then it will do so at the time each node schedules it (or shortly thereafter). For example, if you call this method unconditionally on start-up, then if two nodes are started 5 minutes apart, the job will run both times even if it is only supposed to happen once an hour.

To prevent this, plugin developers should be aware that a job could already be scheduled, either because it was scheduled by another cluster node or because it remained scheduled across a system restart. Write the scheduling call in a way that avoids changing the schedule when it already exists with the desired settings. Assuming that the schedule does not normally need to be updated, this will probably be as simple as:

     if (compatibilityPluginScheduler.getJobInfo(JOB_KEY) != null)
     {
         compatibilityPluginScheduler.scheduleClusteredJob(JOB_KEY, JOB_HANDLER_KEY,
                  new Date(System.currentTimeMillis() + SCHEDULER_RACE_PADDING), INTERVAL);
     }
 

Note the use of the scheduler race padding to offset the initial run time of the job. Using a value like 15000L (15 seconds) here provides a window where multiple nodes starting at once might all decide to create the same job schedule. The padding helps ensure that this race condition has resolved by the time the job runs for the first time, which guarantees that it only runs the expected number of times.

Parameters:
jobKey - A unique key for the job
jobHandlerKey - The lookup key for the job handler that will process the request. Unlike the JobRunner in atlassian-scheduler, this must be registered before the job is scheduled.
startTime - The time the job is to start.
repeatInterval - How long of an interval to wait between repeated job executions, in milliseconds. Note that implementations may restrict what values may be used here, and that it is safest to use intervals that are a multiple of 60000L milliseconds (1 minute).
Throws:
IllegalArgumentException - if the jobHandlerKey is not registered.

getJobInfo

@Nullable
JobInfo getJobInfo(String jobKey)
Returns information about a scheduled clustered job, if it exists.

Note that this method should only be used if the compatibility layer would have been used to register the job. Jobs that are scheduled directly with atlassian-scheduler or PluginScheduler may or may not be known to this method depending on the implementation.

Parameters:
jobKey - the job's unique key
Returns:
the job's info, or null if it is not scheduled.

unscheduleClusteredJob

void unscheduleClusteredJob(String jobKey)
Unschedule the given job for the entire cluster.

WARNING: This applies across the entire cluster. If the plugin is just being disabled on one node as part of a graceful shutdown of the node, then calling this method would remove the job from the other nodes as well, which is probably the wrong thing to do. It will usually make more sense to call unregisterJobHandler(JobHandlerKey), which will remove the jobs for you if the pre-clustering implementation is used.

Parameters:
jobKey - The job key to unschedule
Throws:
IllegalArgumentException - If the job doesn't exist thus cannot be unscheduled.


Copyright © 2014 Atlassian. All Rights Reserved.