public virtual void testConcurrentExclusiveCorrelation() { InvocationLogListener.reset(); // given a process instance runtimeService.StartProcessInstanceByKey("testProcess"); // and two threads correlating in parallel ThreadControl thread1 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("Message", true)); thread1.ReportInterrupts(); ThreadControl thread2 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("Message", true)); thread2.ReportInterrupts(); // both threads open a transaction and wait before correlating the message thread1.WaitForSync(); thread2.WaitForSync(); // thread one correlates and acquires the exclusive lock thread1.MakeContinue(); thread1.WaitForSync(); // the service task was executed once Assert.AreEqual(1, InvocationLogListener.Invocations); // thread two attempts to acquire the exclusive lock but can't since thread 1 hasn't released it yet thread2.MakeContinue(); Thread.Sleep(2000); // let the first thread ends its transaction thread1.MakeContinue(); Assert.IsNull(thread1.Exception); // thread 2 can't continue because the event subscription it tried to lock was deleted thread2.WaitForSync(); Assert.True(thread2.Exception != null); Assert.True(thread2.Exception is ProcessEngineException); AssertTextPresent("does not have a subscription to a message event with name 'Message'", thread2.Exception.Message); // the first thread ended successfully without an exception thread1.Join(); Assert.IsNull(thread1.Exception); // the follow-up task was reached ITask afterMessageTask = taskService.CreateTaskQuery().First(); Assert.AreEqual(afterMessageTask.TaskDefinitionKey, "afterMessageUserTask"); // the service task was not executed a second time Assert.AreEqual(1, InvocationLogListener.Invocations); }
public virtual void FAILING_testConcurrentMixedCorrelationCase2() { InvocationLogListener.reset(); // given a process instance runtimeService.StartProcessInstanceByKey("testProcess"); // and two threads correlating in parallel (one exclusive, one non-exclusive) ThreadControl thread1 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("Message", false)); thread1.ReportInterrupts(); ThreadControl thread2 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("Message", true)); thread2.ReportInterrupts(); // both threads open a transaction and wait before correlating the message thread1.WaitForSync(); thread2.WaitForSync(); // thread one correlates and acquires no lock thread1.MakeContinue(); thread1.WaitForSync(); // thread two acquires a lock and succeeds because thread one hasn't acquired one thread2.MakeContinue(); thread2.WaitForSync(); // the service task was executed twice Assert.AreEqual(2, InvocationLogListener.Invocations); // thread one ends its transaction and blocks on flush when it attempts to Delete the event subscription thread1.MakeContinue(); Thread.Sleep(5000); Assert.IsNull(thread1.Exception); Assert.AreEqual(0, taskService.CreateTaskQuery().Count()); // thread 2 flushes successfully and releases the lock thread2.WaitUntilDone(); Assert.IsNull(thread2.Exception); ITask afterMessageTask = taskService.CreateTaskQuery().First(); Assert.NotNull(afterMessageTask); Assert.AreEqual(afterMessageTask.TaskDefinitionKey, "afterMessageUserTask"); // thread 1 flush fails with optimistic locking thread1.Join(); Assert.True(thread1.Exception != null); Assert.True(thread1.Exception is OptimisticLockingException); }
public virtual void testTimeoutOnUpdate() { createJobEntity(); thread1 = ExecuteControllableCommand(new UpdateJobCommand("p1")); // wait for thread 1 to perform UPDATE thread1.WaitForSync(); thread2 = ExecuteControllableCommand(new UpdateJobCommand("p2")); // wait for thread 2 to perform UPDATE thread2.WaitForSync(); // perform FLUSH for thread 1 (but no commit of transaction) thread1.MakeContinue(); // wait for thread 1 to perform FLUSH thread1.WaitForSync(); // perform FLUSH for thread 2 thread2.MakeContinue(); // wait for thread 2 to cancel FLUSH because of timeout thread2.ReportInterrupts(); thread2.WaitForSync(TEST_TIMEOUT_IN_MILLIS); Assert.NotNull(thread2.Exception, "expected timeout exception"); }
protected internal virtual void deployOnTwoConcurrentThreads(IDeploymentBuilder deploymentOne, IDeploymentBuilder deploymentTwo) { Assert.That(deploymentOne, Is.Not.EqualTo(deploymentTwo)); // STEP 1: bring two threads to a point where they have // 1) started a new transaction // 2) are ready to deploy ThreadControl thread1 = ExecuteControllableCommand(new ControllableDeployCommand(deploymentOne)); thread1.WaitForSync(); ThreadControl thread2 = ExecuteControllableCommand(new ControllableDeployCommand(deploymentTwo)); thread2.WaitForSync(); // STEP 2: make Thread 1 proceed and wait until it has deployed but not yet committed // -> will still hold the exclusive lock thread1.MakeContinue(); thread1.WaitForSync(); // STEP 3: make Thread 2 continue // -> it will attempt to acquire the exclusive lock and block on the lock thread2.MakeContinue(); // wait for 2 seconds (Thread 2 is blocked on the lock) Thread.Sleep(2000); // STEP 4: allow Thread 1 to terminate // -> Thread 1 will commit and release the lock thread1.WaitUntilDone(); // STEP 5: wait for Thread 2 to terminate thread2.WaitForSync(); thread2.WaitUntilDone(); }
public virtual void testConcurrentFetchAndDelete() { Deployment(ESS.FW.Bpm.Model.Bpmn.Bpmn.CreateExecutableProcess("test").StartEvent().UserTask().EndEvent().Done()); //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final java.util.List<String> listVar = java.util.("a", "b"); IList <string> listVar = new List <string> { "a", "b" }; string pid = runtimeService.StartProcessInstanceByKey("test", ESS.FW.Bpm.Engine.Variable.Variables.CreateVariables().PutValue("listVar", listVar)).Id; // start a controlled Fetch variable command asyncThread = ExecuteControllableCommand <object>(new FetchVariableCmd(pid, "listVar")); // wait for async thread to load the variable (but not the byte array) asyncThread.WaitForSync(); // now Delete the process instance runtimeService.DeleteProcessInstance(pid, null); // make the second thread continue // => this will a flush the FetchVariableCmd Context. // if the flush performs an update to the variable, it will Assert.Fail with an OLE asyncThread.MakeContinue(); asyncThread.WaitUntilDone(); }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public void testRunTwoHistoryCleanups() throws InterruptedException public virtual void testRunTwoHistoryCleanups() { ThreadControl thread1 = ExecuteControllableCommand(new ControllableHistoryCleanupCommand()); thread1.WaitForSync(); ThreadControl thread2 = ExecuteControllableCommand(new ControllableHistoryCleanupCommand()); thread2.WaitForSync(); thread1.MakeContinue(); thread1.WaitForSync(); thread2.MakeContinue(); Thread.Sleep(2000); thread1.WaitUntilDone(); thread2.WaitForSync(); thread2.WaitUntilDone(); //only one history cleanup job exists -> no exception IJob historyCleanupJob = ProcessEngine.HistoryService.FindHistoryCleanupJob(); Assert.NotNull(historyCleanupJob); Assert.IsNull(thread1.Exception); Assert.IsNull(thread2.Exception); }
public virtual void testEventSubprocess() { InvocationLogListener.reset(); // given a process instance runtimeService.StartProcessInstanceByKey("testProcess"); // and two threads correlating in parallel ThreadControl thread1 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("incoming", false)); thread1.ReportInterrupts(); ThreadControl thread2 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("incoming", false)); thread2.ReportInterrupts(); // both threads open a transaction and wait before correlating the message thread1.WaitForSync(); thread2.WaitForSync(); // both threads correlate thread1.MakeContinue(); thread2.MakeContinue(); thread1.WaitForSync(); thread2.WaitForSync(); // the first thread ends its transaction thread1.WaitUntilDone(); Assert.IsNull(thread1.Exception); // the second thread ends its transaction and fails with optimistic locking exception thread2.WaitUntilDone(); Assert.True(thread2.Exception != null); Assert.True(thread2.Exception is OptimisticLockingException); }
public virtual void testConcurrentMixedCorrelation() { InvocationLogListener.reset(); // given a process instance runtimeService.StartProcessInstanceByKey("testProcess"); // and two threads correlating in parallel (one exclusive, one non-exclusive) ThreadControl thread1 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("Message", true)); thread1.ReportInterrupts(); ThreadControl thread2 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("Message", false)); thread2.ReportInterrupts(); // both threads open a transaction and wait before correlating the message thread1.WaitForSync(); thread2.WaitForSync(); // thread one correlates and acquires the exclusive lock thread1.MakeContinue(); thread1.WaitForSync(); // thread two correlates since it does not need a pessimistic lock thread2.MakeContinue(); thread2.WaitForSync(); // the service task was executed twice Assert.AreEqual(2, InvocationLogListener.Invocations); // the first thread ends its transaction and releases the lock; the event subscription is now gone thread1.WaitUntilDone(); Assert.IsNull(thread1.Exception); ITask afterMessageTask = taskService.CreateTaskQuery().First(); Assert.AreEqual(afterMessageTask.TaskDefinitionKey, "afterMessageUserTask"); // thread two attempts to end its transaction and fails with optimistic locking thread2.MakeContinue(); thread2.WaitForSync(); Assert.True(thread2.Exception != null); Assert.True(thread2.Exception is OptimisticLockingException); }
public virtual void testConcurrentExclusiveCorrelationToDifferentExecutions() { InvocationLogListener.reset(); // given a process instance IProcessInstance instance1 = runtimeService.StartProcessInstanceByKey("testProcess"); IProcessInstance instance2 = runtimeService.StartProcessInstanceByKey("testProcess"); // and two threads correlating in parallel to each of the two instances ThreadControl thread1 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("Message", instance1.Id, true)); thread1.ReportInterrupts(); ThreadControl thread2 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("Message", instance2.Id, true)); thread2.ReportInterrupts(); // both threads open a transaction and wait before correlating the message thread1.WaitForSync(); thread2.WaitForSync(); // thread one correlates and acquires the exclusive lock on the event subscription of instance1 thread1.MakeContinue(); thread1.WaitForSync(); // the service task was executed once Assert.AreEqual(1, InvocationLogListener.Invocations); // thread two correlates and acquires the exclusive lock on the event subscription of instance2 // depending on the database and locking used, this may block thread2 thread2.MakeContinue(); // thread 1 completes successfully thread1.WaitUntilDone(); Assert.IsNull(thread1.Exception); // thread2 should be able to continue at least after thread1 has finished and released its lock thread2.WaitForSync(); // the service task was executed the second time Assert.AreEqual(2, InvocationLogListener.Invocations); // thread 2 completes successfully thread2.WaitUntilDone(); Assert.IsNull(thread2.Exception); // the follow-up task was reached in both instances Assert.AreEqual(2, taskService.CreateTaskQuery(c => c.TaskDefinitionKey == "afterMessageUserTask").Count()); }
public virtual void testConcurrentCorrelationFailsWithOptimisticLockingException() { InvocationLogListener.reset(); // given a process instance runtimeService.StartProcessInstanceByKey("testProcess"); // and two threads correlating in parallel ThreadControl thread1 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("Message", false)); thread1.ReportInterrupts(); ThreadControl thread2 = ExecuteControllableCommand(new ControllableMessageCorrelationCommand("Message", false)); thread2.ReportInterrupts(); // both threads open a transaction and wait before correlating the message thread1.WaitForSync(); thread2.WaitForSync(); // both threads correlate thread1.MakeContinue(); thread2.MakeContinue(); thread1.WaitForSync(); thread2.WaitForSync(); // the service task was executed twice Assert.AreEqual(2, InvocationLogListener.Invocations); // the first thread ends its transcation thread1.WaitUntilDone(); Assert.IsNull(thread1.Exception); ITask afterMessageTask = taskService.CreateTaskQuery().First(); Assert.AreEqual(afterMessageTask.TaskDefinitionKey, "afterMessageUserTask"); // the second thread ends its transaction and fails with optimistic locking exception thread2.WaitUntilDone(); Assert.True(thread2.Exception != null); Assert.True(thread2.Exception is OptimisticLockingException); }
/// <summary> /// In this test, we run two transactions concurrently. /// The transactions have the following behavior: /// /// (1) INSERT row into a table /// (2) SELECT ALL rows from that table /// /// We execute it with two threads in the following interleaving: /// /// Thread 1 Thread 2 /// ======== ======== /// ------INSERT--------------------------- | /// ---------------------------INSERT------ | /// ---------------------------SELECT------ v time /// ------SELECT--------------------------- /// /// Deadlocks may occur if readers are not properly isolated from writers. /// /// </summary> public virtual void testTransactionIsolation() { thread1 = ExecuteControllableCommand(new TestCommand("p1")); // wait for Thread 1 to perform INSERT thread1.WaitForSync(); thread2 = ExecuteControllableCommand(new TestCommand("p2")); // wait for Thread 2 to perform INSERT thread2.WaitForSync(); // wait for Thread 2 to perform SELECT thread2.MakeContinue(); // wait for Thread 1 to perform same SELECT => deadlock thread1.MakeContinue(); thread2.WaitForSync(); thread1.WaitForSync(); }