public virtual void testIdlingAfterConcurrentJobAddedNotification() { // start job acquisition - waiting before acquiring jobs jobExecutor.start(); acquisitionThread.waitForSync(); // acquire jobs acquisitionThread.makeContinueAndWaitForSync(); // issue a message added notification engineRule.RuntimeService.startProcessInstanceByKey("simpleAsyncProcess"); // complete job acquisition - trigger re-configuration // => due to the hint, the job executor should not become idle acquisitionThread.makeContinueAndWaitForSync(); assertJobExecutorWaitEvent(0L); // another cycle of job acquisition // => acquires and executes the new job // => acquisition does not become idle because enough jobs could be acquired triggerReconfigurationAndNextCycle(); assertJobExecutorWaitEvent(0L); cycleJobAcquisitionToMaxIdleTime(); }
public virtual void testJobLockingFailure() { int numberOfInstances = 3; // when starting a number of process instances for (int i = 0; i < numberOfInstances; i++) { engineRule.RuntimeService.startProcessInstanceByKey("simpleAsyncProcess").Id; } // when starting job execution, both acquisition threads wait before acquiring something jobExecutor1.start(); acquisitionThread1.waitForSync(); jobExecutor2.start(); acquisitionThread2.waitForSync(); // when having both threads acquire jobs // then both wait before committing the acquiring transaction (AcquireJobsCmd) acquisitionThread1.makeContinueAndWaitForSync(); acquisitionThread2.makeContinueAndWaitForSync(); // when continuing acquisition thread 1 acquisitionThread1.makeContinueAndWaitForSync(); // then it has not performed waiting since it was able to acquire and execute all jobs Assert.assertEquals(0, engineRule.ManagementService.createJobQuery().active().count()); IList <RecordedWaitEvent> jobExecutor1WaitEvents = jobExecutor1.AcquireJobsRunnable.WaitEvents; Assert.assertEquals(1, jobExecutor1WaitEvents.Count); Assert.assertEquals(0, jobExecutor1WaitEvents[0].TimeBetweenAcquisitions); // when continuing acquisition thread 2 acquisitionThread2.makeContinueAndWaitForSync(); // then its acquisition cycle fails with OLEs // but the acquisition thread immediately tries again IList <RecordedWaitEvent> jobExecutor2WaitEvents = jobExecutor2.AcquireJobsRunnable.WaitEvents; Assert.assertEquals(1, jobExecutor2WaitEvents.Count); Assert.assertEquals(0, jobExecutor2WaitEvents[0].TimeBetweenAcquisitions); }
public virtual void testBackoffOnOptimisticLocking() { // when starting a number of process instances process instance for (int i = 0; i < 9; i++) { engineRule.RuntimeService.startProcessInstanceByKey("simpleAsyncProcess").Id; } // ensure that both acquisition threads acquire the same jobs thereby provoking an optimistic locking exception JobAcquisitionTestHelper.suspendInstances(engineRule.ProcessEngine, 6); // when starting job execution, both acquisition threads wait before acquiring something jobExecutor1.start(); acquisitionThread1.waitForSync(); jobExecutor2.start(); acquisitionThread2.waitForSync(); // when having both threads acquire jobs // then both wait before committing the acquiring transaction (AcquireJobsCmd) acquisitionThread1.makeContinueAndWaitForSync(); acquisitionThread2.makeContinueAndWaitForSync(); // when continuing acquisition thread 1 acquisitionThread1.makeContinueAndWaitForSync(); // then it has not performed waiting since it was able to acquire and execute all jobs IList <RecordedWaitEvent> jobExecutor1WaitEvents = jobExecutor1.AcquireJobsRunnable.WaitEvents; Assert.assertEquals(1, jobExecutor1WaitEvents.Count); Assert.assertEquals(0, jobExecutor1WaitEvents[0].TimeBetweenAcquisitions); // when continuing acquisition thread 2, acquisition fails with an OLE acquisitionThread2.makeContinueAndWaitForSync(); // and has performed backoff IList <RecordedWaitEvent> jobExecutor2WaitEvents = jobExecutor2.AcquireJobsRunnable.WaitEvents; Assert.assertEquals(1, jobExecutor2WaitEvents.Count); RecordedWaitEvent waitEvent = jobExecutor2WaitEvents[0]; // we don't know the exact wait time, // since there is random jitter applied JobAcquisitionTestHelper.assertInBetween(BASE_BACKOFF_TIME, BASE_BACKOFF_TIME + BASE_BACKOFF_TIME / 2, waitEvent.TimeBetweenAcquisitions); // when performing another cycle of acquisition JobAcquisitionTestHelper.activateInstances(engineRule.ProcessEngine, 6); acquisitionThread1.makeContinueAndWaitForSync(); acquisitionThread2.makeContinueAndWaitForSync(); // and thread 1 again acquires all jobs successfully acquisitionThread1.makeContinueAndWaitForSync(); // while thread 2 again fails with OLE acquisitionThread2.makeContinueAndWaitForSync(); // then thread 1 has tried to acquired 3 jobs again IList <RecordedAcquisitionEvent> jobExecutor1AcquisitionEvents = jobExecutor1.AcquireJobsRunnable.AcquisitionEvents; RecordedAcquisitionEvent secondAcquisitionAttempt = jobExecutor1AcquisitionEvents[1]; Assert.assertEquals(3, secondAcquisitionAttempt.NumJobsToAcquire); // and not waited jobExecutor1WaitEvents = jobExecutor1.AcquireJobsRunnable.WaitEvents; Assert.assertEquals(2, jobExecutor1WaitEvents.Count); Assert.assertEquals(0, jobExecutor1WaitEvents[1].TimeBetweenAcquisitions); // then thread 2 has tried to acquire 6 jobs this time IList <RecordedAcquisitionEvent> jobExecutor2AcquisitionEvents = jobExecutor2.AcquireJobsRunnable.AcquisitionEvents; secondAcquisitionAttempt = jobExecutor2AcquisitionEvents[1]; Assert.assertEquals(6, secondAcquisitionAttempt.NumJobsToAcquire); // and again increased its backoff jobExecutor2WaitEvents = jobExecutor2.AcquireJobsRunnable.WaitEvents; Assert.assertEquals(2, jobExecutor2WaitEvents.Count); RecordedWaitEvent secondWaitEvent = jobExecutor2WaitEvents[1]; long expectedBackoffTime = BASE_BACKOFF_TIME * BACKOFF_FACTOR; // 1000 * 2^1 JobAcquisitionTestHelper.assertInBetween(expectedBackoffTime, expectedBackoffTime + expectedBackoffTime / 2, secondWaitEvent.TimeBetweenAcquisitions); }