public virtual void testBackoffDecrease() { // when starting a number of process instances process instance for (int i = 0; i < 15; 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, 12); // when starting job execution, both acquisition threads wait before acquiring something jobExecutor1.start(); acquisitionThread1.waitForSync(); jobExecutor2.start(); acquisitionThread2.waitForSync(); // when continuing acquisition thread 1 // then it is able to acquire and execute all jobs acquisitionThread1.makeContinueAndWaitForSync(); // when continuing acquisition thread 2 // acquisition fails with an OLE acquisitionThread2.makeContinueAndWaitForSync(); jobExecutor1.shutdown(); acquisitionThread1.waitUntilDone(); acquisitionThread2.makeContinueAndWaitForSync(); // such that acquisition thread 2 performs backoff IList <RecordedWaitEvent> jobExecutor2WaitEvents = jobExecutor2.AcquireJobsRunnable.WaitEvents; Assert.assertEquals(1, jobExecutor2WaitEvents.Count); // when in the next cycles acquisition thread2 successfully acquires jobs without OLE for n times JobAcquisitionTestHelper.activateInstances(engineRule.ProcessEngine, 12); for (int i = 0; i < BACKOFF_DECREASE_THRESHOLD; i++) { // backoff has not decreased yet Assert.assertTrue(jobExecutor2WaitEvents[i].TimeBetweenAcquisitions > 0); acquisitionThread2.makeContinueAndWaitForSync(); // acquire acquisitionThread2.makeContinueAndWaitForSync(); // continue after acquisition with next cycle } // it decreases its backoff again long lastBackoff = jobExecutor2WaitEvents[BACKOFF_DECREASE_THRESHOLD].TimeBetweenAcquisitions; Assert.assertEquals(0, lastBackoff); }
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); }