Skip to content

Commit

Permalink
RHBPMS-4729 QuartzSchedulerService increments NEXT_FIRE_TIME by timeC…
Browse files Browse the repository at this point in the history
…ycle regardless of current time when calling rescheduleJob() (#847)
  • Loading branch information
tkobayas authored and mswiderski committed May 18, 2017
1 parent 5392801 commit 9cc0732
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 4 deletions.
Expand Up @@ -48,6 +48,7 @@
import java.io.NotSerializableException;
import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
Expand All @@ -67,6 +68,8 @@ public class QuartzSchedulerService implements GlobalSchedulerService {
private static final Integer FAILED_JOB_RETRIES = Integer.parseInt(System.getProperty("org.jbpm.timer.quartz.retries", "5"));
private static final Integer FAILED_JOB_DELAY = Integer.parseInt(System.getProperty("org.jbpm.timer.quartz.delay", "1000"));

private static final Integer RESCHEDULE_DELAY = Integer.parseInt(System.getProperty("org.jbpm.timer.quartz.reschedule.delay", "500"));

private AtomicLong idCounter = new AtomicLong();
private TimerService globalTimerService;
private SchedulerServiceInterceptor interceptor = new DelegateSchedulerServiceInterceptor(this);
Expand Down Expand Up @@ -156,8 +159,16 @@ public void internalSchedule(TimerJobInstance timerJobInstance) {
jobq.setRequestsRecovery(true);
jobq.getJobDataMap().put("timerJobInstance", timerJobInstance);

// Amend nextFireTime not to schedule older than now + RESCHEDULE_DELAY
Date nextFireTime = timerJobInstance.getTrigger().hasNextFireTime();
Date threshold = new Date(System.currentTimeMillis() + RESCHEDULE_DELAY);
if (nextFireTime.before(threshold)) {
logger.debug("nextFireTime [" + nextFireTime + "] is older than (now + RESCHEDULE_DELAY). Amending it to [" + threshold + "]");
nextFireTime = threshold;
}

// Define a Trigger that will fire "now"
org.quartz.Trigger triggerq = new SimpleTrigger(quartzJobHandle.getJobName()+"_trigger", quartzJobHandle.getJobGroup(), timerJobInstance.getTrigger().hasNextFireTime());
org.quartz.Trigger triggerq = new SimpleTrigger(quartzJobHandle.getJobName()+"_trigger", quartzJobHandle.getJobGroup(), nextFireTime);

// Schedule the job with the trigger
try {
Expand Down
Expand Up @@ -305,9 +305,6 @@ public void afterNodeLeft(ProcessNodeLeftEvent event) {

countDownListener.waitTillCompleted(3000);
assertEquals(2, timerExporations.size());


manager.close();
}

@Test(timeout=20000)
Expand Down Expand Up @@ -355,4 +352,58 @@ public void testTimerRequiresRecoveryFlagSet() throws Exception {
ksession.abortProcessInstance(processInstance.getId());
manager.disposeRuntimeEngine(runtime);
}

@Test(timeout=25000)
public void testContinueTimerWithMisfire() throws Exception {
// RHBPMS-4729
System.setProperty("org.quartz.properties", "quartz-db-short-misfire.properties");

CountDownProcessEventListener countDownListener = new CountDownProcessEventListener("StartProcess", 2);
// prepare listener to assert results
final List<Long> timerExporations = new ArrayList<Long>();
ProcessEventListener listener = new DefaultProcessEventListener(){
@Override
public void beforeProcessStarted(ProcessStartedEvent event) {
timerExporations.add(event.getProcessInstance().getId());
}
};

// No special configuration for TimerService in order to test RuntimeManager default
environment = RuntimeEnvironmentBuilder.Factory.get()
.newDefaultBuilder()
.entityManagerFactory(emf)
.addAsset(ResourceFactory.newClassPathResource("org/jbpm/test/functional/timer/TimerStart2.bpmn2"), ResourceType.BPMN2)
.registerableItemsFactory(new TestRegisterableItemsFactory(listener, countDownListener))
.get();
manager = getManager(environment, true);

RuntimeEngine runtime = manager.getRuntimeEngine(ProcessInstanceIdContext.get());
KieSession ksession = runtime.getKieSession();

countDownListener.waitTillCompleted();

manager.disposeRuntimeEngine(runtime);
manager.close();

System.out.println("==== manager.close() ====");

countDownListener.reset(3);

// Simulate interval between shutdown and start so the Trigger is older than (now - misfireThreshold)
Thread.sleep(5000);

// ---- restart ----
environment = RuntimeEnvironmentBuilder.Factory.get()
.newDefaultBuilder()
.entityManagerFactory(emf)
.addAsset(ResourceFactory.newClassPathResource("org/jbpm/test/functional/timer/TimerStart2.bpmn2"), ResourceType.BPMN2)
.registerableItemsFactory(new TestRegisterableItemsFactory(listener, countDownListener))
.get();
manager = getManager(environment, true);

countDownListener.waitTillCompleted(4000);

assertEquals(5, timerExporations.size());
}

}
@@ -0,0 +1,66 @@
#org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore


#============================================================================
# Configure Main Scheduler Properties
#============================================================================

org.quartz.scheduler.instanceName = TestScheduler
org.quartz.scheduler.instanceId = instance_one
org.quartz.scheduler.skipUpdateCheck=true
org.quartz.scheduler.idleWaitTime=1000
#============================================================================
# Configure ThreadPool
#============================================================================

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 15
org.quartz.threadPool.threadPriority = 5


#============================================================================
# Configure JobStore
#============================================================================

org.quartz.jobStore.misfireThreshold = 3000

org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreCMT
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties=false
org.quartz.jobStore.dataSource=myDS
org.quartz.jobStore.nonManagedTXDataSource=notManagedDS
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.isClustered=false

#============================================================================
# Other Example Delegates
#============================================================================
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.CloudscapeDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DB2v6Delegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DB2v7Delegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DriverDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.HSQLDBDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.MSSQLDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PointbaseDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.WebLogicDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.WebLogicOracleDelegate

#============================================================================
# Configure Datasources
#============================================================================
org.quartz.dataSource.myDS.jndiURL=jdbc/jbpm-ds
#this notManagedDS should be same as one defined in TimerBaseTest class
#org.quartz.dataSource.notManagedDS.driver=org.h2.Driver
#org.quartz.dataSource.notManagedDS.URL=jdbc:h2:mem:test;MVCC=true
#org.quartz.dataSource.notManagedDS.user=sa
#org.quartz.dataSource.notManagedDS.password=
#org.quartz.dataSource.notManagedDS.maxConnections=5
org.quartz.dataSource.notManagedDS.connectionProvider.class=org.jbpm.test.functional.timer.addon.NonTransactionalConnectionProvider
org.quartz.dataSource.notManagedDS.driverClassName=org.h2.Driver
org.quartz.dataSource.notManagedDS.user=sa
org.quartz.dataSource.notManagedDS.password=sasa
org.quartz.dataSource.notManagedDS.url=jdbc:h2:mem:test;MVCC=true

0 comments on commit 9cc0732

Please sign in to comment.