mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Improve how scheduled actions with historic start dates are handled during startup. The last run time is used to decide when they need to be re-scheduled for (ALF-4505)
Also, don't add the new scheduled action to Quartz until the transaction commits, to ensure the nodes are really there before Quartz fires git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@22136 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -205,36 +205,116 @@ public class ScheduledPersistedActionImpl implements ScheduledPersistedAction
|
||||
return null;
|
||||
}
|
||||
|
||||
// If the end date is in the past, don't schedule
|
||||
if(scheduleEnd != null && scheduleEnd.getTime() < System.currentTimeMillis())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// Decide what to use as the start time
|
||||
// This will be based on the requested start time, when
|
||||
// the schedule last ran (if ever), and the interval
|
||||
Date startAt = scheduleStart;
|
||||
Date endAt = scheduleEnd;
|
||||
if(startAt == null)
|
||||
{
|
||||
// No start time specified, so start immediately
|
||||
startAt = new Date();
|
||||
}
|
||||
else
|
||||
{
|
||||
// A start time was given. Is it still to come?
|
||||
if(startAt.getTime() >= System.currentTimeMillis())
|
||||
{
|
||||
// The start date hasn't happened yet
|
||||
// This means we can just use it as-is
|
||||
}
|
||||
else
|
||||
{
|
||||
// The start date has passed. Have we ever run this?
|
||||
if(lastExecutedAt == null)
|
||||
{
|
||||
// The schedule has never run
|
||||
// Tell Quartz the requested start time, so it runs
|
||||
// immediately, and repeats are correctly calculated
|
||||
startAt = scheduleStart;
|
||||
}
|
||||
else if(lastExecutedAt.getTime() < startAt.getTime())
|
||||
{
|
||||
// The previous run time is before the scheduled
|
||||
// start time, so has probably been edited, and
|
||||
// both of these dates is in the past.
|
||||
// Tell Quartz the requested start time, so it runs
|
||||
// immediately, and repeats are correctly calculated
|
||||
startAt = scheduleStart;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The start date is in the past, and we have
|
||||
// previously run the job
|
||||
|
||||
if(getScheduleInterval() == null)
|
||||
{
|
||||
// There is no schedule setup, so this is
|
||||
// probably just an old job on startup/edit
|
||||
// So, don't run it
|
||||
return null;
|
||||
}
|
||||
|
||||
// Based on the start time, when would it next be
|
||||
// due to fire?
|
||||
DateIntervalTrigger testT = buildDateIntervalTrigger("TEST", scheduleStart, null);
|
||||
Date nextFireFromNow = testT.getFireTimeAfter(new Date());
|
||||
Date nextFireFromLast = testT.getFireTimeAfter(lastExecutedAt);
|
||||
|
||||
// If the next fire time from the last is before the
|
||||
// next due date, then we missed one
|
||||
if(nextFireFromLast.getTime() < nextFireFromNow.getTime())
|
||||
{
|
||||
// We missed one!
|
||||
// Tell Quartz the requested start time, so it runs
|
||||
// immediately, and repeats are correctly calculated
|
||||
startAt = scheduleStart;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The last run time was largely when due
|
||||
// So, don't run until the next time
|
||||
startAt = nextFireFromNow;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If they don't want it to repeat, just use a simple interval
|
||||
if(getScheduleInterval() == null)
|
||||
{
|
||||
SimpleTrigger trigger = new SimpleTrigger(
|
||||
triggerName, null,
|
||||
scheduleStart
|
||||
startAt
|
||||
);
|
||||
trigger.setMisfireInstruction(SimpleTrigger.MISFIRE_INSTRUCTION_FIRE_NOW);
|
||||
return trigger;
|
||||
}
|
||||
|
||||
return buildDateIntervalTrigger(triggerName, startAt, endAt);
|
||||
}
|
||||
|
||||
private DateIntervalTrigger buildDateIntervalTrigger(String triggerName, Date startAt, Date endAt)
|
||||
{
|
||||
// There are some repeating rules
|
||||
// Create a Date Interval trigger
|
||||
DateIntervalTrigger.IntervalUnit quartzInterval =
|
||||
DateIntervalTrigger.IntervalUnit.valueOf(
|
||||
intervalPeriod.toString().toUpperCase()
|
||||
);
|
||||
// Ensure we always have a start date, even if it's now
|
||||
Date start = scheduleStart;
|
||||
if(start == null)
|
||||
start = new Date();
|
||||
// The end date is allowed to be null
|
||||
Date end = scheduleEnd;
|
||||
|
||||
// Create the interval
|
||||
DateIntervalTrigger trigger = new DateIntervalTrigger(
|
||||
triggerName, null,
|
||||
start, end,
|
||||
startAt, endAt,
|
||||
quartzInterval, intervalCount
|
||||
);
|
||||
trigger.setMisfireInstruction( DateIntervalTrigger.MISFIRE_INSTRUCTION_FIRE_ONCE_NOW );
|
||||
|
@@ -33,7 +33,9 @@ import org.alfresco.repo.action.RuntimeActionService;
|
||||
import org.alfresco.repo.model.Repository;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.TransactionListenerAdapter;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ActionService;
|
||||
@@ -391,15 +393,24 @@ public class ScheduledPersistedActionServiceImpl implements ScheduledPersistedAc
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new entry into the scheduler
|
||||
* Builds up the Quartz details, and adds it to the Quartz
|
||||
* scheduler when the transaction completes.
|
||||
* We have to wait for the transaction to finish, otherwise
|
||||
* Quartz may end up trying and failing to load the details
|
||||
* of a job that hasn't been committed to the repo yet!
|
||||
*/
|
||||
protected void addToScheduler(ScheduledPersistedActionImpl schedule)
|
||||
{
|
||||
// Wrap it up in Quartz bits
|
||||
JobDetail details = buildJobDetail(schedule);
|
||||
Trigger trigger = schedule.asTrigger();
|
||||
final JobDetail details = buildJobDetail(schedule);
|
||||
final Trigger trigger = schedule.asTrigger();
|
||||
|
||||
// Schedule it
|
||||
// As soon as the transaction commits, add it
|
||||
AlfrescoTransactionSupport.bindListener(
|
||||
new TransactionListenerAdapter() {
|
||||
@Override
|
||||
public void afterCommit() {
|
||||
// Schedule it with Quartz
|
||||
try
|
||||
{
|
||||
scheduler.scheduleJob(details, trigger);
|
||||
@@ -410,6 +421,9 @@ public class ScheduledPersistedActionServiceImpl implements ScheduledPersistedAc
|
||||
log.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
protected JobDetail buildJobDetail(ScheduledPersistedActionImpl schedule)
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user