com.atlassian.scheduler.compat
Class AutoDetectingCompatibilityPluginScheduler

java.lang.Object
  extended by com.atlassian.scheduler.compat.AutoDetectingCompatibilityPluginScheduler
All Implemented Interfaces:
CompatibilityPluginScheduler

public class AutoDetectingCompatibilityPluginScheduler
extends Object
implements CompatibilityPluginScheduler

Compatibility plugin scheduler that dynamically selects an atlassian-scheduler or PluginScheduler implementation at runtime based on what is provided by the host application.

This is the component implementation for the CompatibilityPluginScheduler component that plugin developers would most like specify in atlassian-plugin.xml. It attempts to detect the presence of the atlassian-scheduler API by dynamically referencing the com.atlassian.scheduler.SchedulerRuntimeException class from it. If the class resolves, then it is assumed that the application is providing it and that it is safe to use; otherwise, it is assumed that the application predates that API and is not generally cluster-safe, so the SAL PluginScheduler implementation is used instead.

Since:
v1.0

Constructor Summary
AutoDetectingCompatibilityPluginScheduler(com.atlassian.sal.api.scheduling.PluginScheduler pluginScheduler)
           
 
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.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

AutoDetectingCompatibilityPluginScheduler

public AutoDetectingCompatibilityPluginScheduler(com.atlassian.sal.api.scheduling.PluginScheduler pluginScheduler)
Method Detail

registerJobHandler

public void registerJobHandler(JobHandlerKey jobHandlerKey,
                               JobHandler jobHandler)
Description copied from interface: CompatibilityPluginScheduler
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.

Specified by:
registerJobHandler in interface CompatibilityPluginScheduler
Parameters:
jobHandlerKey - the key that associates jobs with this job handler
jobHandler - the job handler which will process job requests

unregisterJobHandler

public void unregisterJobHandler(JobHandlerKey jobHandlerKey)
Description copied from interface: CompatibilityPluginScheduler
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.

Specified by:
unregisterJobHandler in interface CompatibilityPluginScheduler
Parameters:
jobHandlerKey - the key for the job handler that will be unregistered.

scheduleClusteredJob

public void scheduleClusteredJob(String jobKey,
                                 JobHandlerKey jobHandlerKey,
                                 Date startTime,
                                 long repeatInterval)
Description copied from interface: CompatibilityPluginScheduler
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.

Specified by:
scheduleClusteredJob in interface CompatibilityPluginScheduler
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).

getJobInfo

@Nullable
public JobInfo getJobInfo(String jobKey)
Description copied from interface: CompatibilityPluginScheduler
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.

Specified by:
getJobInfo in interface CompatibilityPluginScheduler
Parameters:
jobKey - the job's unique key
Returns:
the job's info, or null if it is not scheduled.

unscheduleClusteredJob

public void unscheduleClusteredJob(String jobKey)
Description copied from interface: CompatibilityPluginScheduler
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 CompatibilityPluginScheduler.unregisterJobHandler(JobHandlerKey), which will remove the jobs for you if the pre-clustering implementation is used.

Specified by:
unscheduleClusteredJob in interface CompatibilityPluginScheduler
Parameters:
jobKey - The job key to unschedule


Copyright © 2014 Atlassian. All Rights Reserved.