package com.lashpoint.quartz; import java.util.Calendar; import java.util.Date; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.SchedulerException; import org.quartz.SimpleTrigger; import com.lashpoint.twitter.quartz.RescheduleException; public abstract class RetriableTrigger extends SimpleTrigger { /** * */ private static final long serialVersionUID = 2986291750485640660L; private static final int DELAY_CEILING = 600; // 15 minutes private static final int DELAY_EXP_BASE = 2; // Delays will be a power of 2 public RetriableTrigger(String name, Date startDate) { super(name, startDate, null, 0, 0); } @Override public boolean hasAdditionalProperties() { return true; } @Override public int executionComplete(JobExecutionContext context, JobExecutionException result) { if (shouldReschedule(context, result)) { try { SimpleTrigger nextTrigger = createTriggerForReschedule(context, result); if (nextTrigger != null) { context.getScheduler().rescheduleJob(getName(), getGroup(), nextTrigger); return INSTRUCTION_NOOP; } } catch (SchedulerException e) { throw new RescheduleException(e); } } return INSTRUCTION_DELETE_TRIGGER; } protected abstract boolean shouldReschedule(JobExecutionContext context, JobExecutionException result); protected SimpleTrigger createTriggerForReschedule(JobExecutionContext context, JobExecutionException result) { try { SimpleTrigger trigger = getClass().newInstance(); Calendar nextFireTime = Calendar.getInstance(); nextFireTime.add(Calendar.SECOND, Math.min(DELAY_CEILING, (int)Math.pow(DELAY_EXP_BASE, getTimesTriggered()))); trigger.setStartTime(nextFireTime.getTime()); trigger.setJobName(getJobName()); trigger.setJobGroup(getJobGroup()); trigger.setTimesTriggered(getTimesTriggered()); return trigger; } catch (InstantiationException e) { throw new RescheduleException(e); } catch (IllegalAccessException e) { throw new RescheduleException(e); } } }