package ee.telekom.workflow.core.recovery; import java.util.Collections; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import ee.telekom.workflow.TestApplicationContexts; import ee.telekom.workflow.core.common.WorkflowEngineConfiguration; import ee.telekom.workflow.core.error.ExecutionErrorService; import ee.telekom.workflow.core.node.NodeService; import ee.telekom.workflow.core.workflowinstance.WorkflowInstance; import ee.telekom.workflow.core.workflowinstance.WorkflowInstanceService; import ee.telekom.workflow.core.workflowinstance.WorkflowInstanceStatus; import ee.telekom.workflow.core.workitem.WorkItem; import ee.telekom.workflow.core.workitem.WorkItemDao; import ee.telekom.workflow.core.workitem.WorkItemService; import ee.telekom.workflow.graph.WorkItemStatus; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = TestApplicationContexts.DEFAULT) @DirtiesContext public class RecoveryIT extends TestApplicationContexts{ @Autowired private WorkflowInstanceService workflowInstanceService; @Autowired private WorkItemService workItemService; @Autowired private WorkItemDao workItemDao; @Autowired private ExecutionErrorService executionErrorService; @Autowired private RecoveryService recoveryService; @Autowired private NodeService nodeService; @Autowired private WorkflowEngineConfiguration config; @Test public void test_recoveryUnassigned(){ long woinRefNum = workflowInstanceService.create( "test", 1, null, null, null ).getRefNum(); workflowInstanceService.lock( Collections.singletonList( woinRefNum ) ); assertUnassignedtRecovery( woinRefNum ); } @Test public void test_recoveryAssigned_New(){ long woinRefNum = workflowInstanceService.create( "test", 1, null, null, null ).getRefNum(); workflowInstanceService.lock( Collections.singletonList( woinRefNum ) ); workflowInstanceService.updateNodeName( woinRefNum, config.getNodeName() ); assertAssignedRecovery( woinRefNum, WorkflowInstanceStatus.NEW, WorkflowInstanceStatus.NEW ); } @Test public void test_recoveryAssigned_Starting(){ long woinRefNum = workflowInstanceService.create( "test", 1, null, null, null ).getRefNum(); workflowInstanceService.lock( Collections.singletonList( woinRefNum ) ); workflowInstanceService.updateNodeName( woinRefNum, config.getNodeName() ); workflowInstanceService.markStarting( woinRefNum ); assertAssignedRecovery( woinRefNum, WorkflowInstanceStatus.STARTING, WorkflowInstanceStatus.NEW ); } @Test public void test_recoveryAssigned_Abort(){ long woinRefNum = workflowInstanceService.create( "test", 1, null, null, null ).getRefNum(); workflowInstanceService.lock( Collections.singletonList( woinRefNum ) ); workflowInstanceService.updateNodeName( woinRefNum, config.getNodeName() ); workflowInstanceService.markAbort( woinRefNum ); assertAssignedRecovery( woinRefNum, WorkflowInstanceStatus.ABORT, WorkflowInstanceStatus.ABORT ); } @Test public void test_recoveryAssigned_Aborting(){ long woinRefNum = workflowInstanceService.create( "test", 1, null, null, null ).getRefNum(); workflowInstanceService.lock( Collections.singletonList( woinRefNum ) ); workflowInstanceService.updateNodeName( woinRefNum, config.getNodeName() ); workflowInstanceService.markAbort( woinRefNum ); workflowInstanceService.markAborting( woinRefNum ); assertAssignedRecovery( woinRefNum, WorkflowInstanceStatus.ABORTING, WorkflowInstanceStatus.ABORT ); } @Test public void test_recoveryAssigned_Executing_New(){ long woinRefNum = workflowInstanceService.create( "test", 1, null, null, null ).getRefNum(); long woitRefNum = createWoit( woinRefNum, "signal", null, null ); workflowInstanceService.lock( Collections.singletonList( woinRefNum ) ); workflowInstanceService.updateNodeName( woinRefNum, config.getNodeName() ); workflowInstanceService.markStarting( woinRefNum ); workflowInstanceService.markExecuting( woinRefNum ); assertAssignedRecovery( woinRefNum, woitRefNum, WorkflowInstanceStatus.EXECUTING, WorkflowInstanceStatus.EXECUTING, WorkItemStatus.NEW, WorkItemStatus.NEW, false ); } @Test public void test_recoveryAssigned_Executing_Executing(){ long woinRefNum = workflowInstanceService.create( "test", 1, null, null, null ).getRefNum(); long woitRefNum = createWoit( woinRefNum, "signal", null, null ); workflowInstanceService.lock( Collections.singletonList( woinRefNum ) ); workflowInstanceService.updateNodeName( woinRefNum, config.getNodeName() ); workflowInstanceService.markStarting( woinRefNum ); workflowInstanceService.markExecuting( woinRefNum ); workItemService.markExecuting( woitRefNum ); assertAssignedRecovery( woinRefNum, woitRefNum, WorkflowInstanceStatus.EXECUTING, WorkflowInstanceStatus.EXECUTING, WorkItemStatus.EXECUTING, WorkItemStatus.NEW, false ); } @Test public void test_recoveryAssigned_Executing_Executing_Task(){ long woinRefNum = workflowInstanceService.create( "test", 1, null, null, null ).getRefNum(); long woitRefNum = createWoit( woinRefNum, null, "bean", "method" ); workflowInstanceService.lock( Collections.singletonList( woinRefNum ) ); workflowInstanceService.updateNodeName( woinRefNum, config.getNodeName() ); workflowInstanceService.markStarting( woinRefNum ); workflowInstanceService.markExecuting( woinRefNum ); workItemService.markExecuting( woitRefNum ); assertAssignedRecovery( woinRefNum, woitRefNum, WorkflowInstanceStatus.EXECUTING, WorkflowInstanceStatus.EXECUTING_ERROR, WorkItemStatus.EXECUTING, WorkItemStatus.EXECUTING_ERROR, true ); } @Test public void test_recoveryAssigned_Executing_Executed(){ long woinRefNum = workflowInstanceService.create( "test", 1, null, null, null ).getRefNum(); long woitRefNum = createWoit( woinRefNum, "signal", null, null ); workflowInstanceService.lock( Collections.singletonList( woinRefNum ) ); workflowInstanceService.updateNodeName( woinRefNum, config.getNodeName() ); workflowInstanceService.markStarting( woinRefNum ); workflowInstanceService.markExecuting( woinRefNum ); workItemService.markExecuting( woitRefNum ); workItemService.markExecutedAndSaveResult( woitRefNum, null ); assertAssignedRecovery( woinRefNum, woitRefNum, WorkflowInstanceStatus.EXECUTING, WorkflowInstanceStatus.EXECUTING, WorkItemStatus.EXECUTED, WorkItemStatus.EXECUTED, false ); } @Test public void test_recoveryAssigned_Executing_Completing(){ long woinRefNum = workflowInstanceService.create( "test", 1, null, null, null ).getRefNum(); long woitRefNum = createWoit( woinRefNum, "signal", null, null ); workflowInstanceService.lock( Collections.singletonList( woinRefNum ) ); workflowInstanceService.updateNodeName( woinRefNum, config.getNodeName() ); workflowInstanceService.markStarting( woinRefNum ); workflowInstanceService.markExecuting( woinRefNum ); workItemService.markExecuting( woitRefNum ); workItemService.markExecutedAndSaveResult( woitRefNum, null ); workItemService.markCompleting( woitRefNum ); assertAssignedRecovery( woinRefNum, woitRefNum, WorkflowInstanceStatus.EXECUTING, WorkflowInstanceStatus.EXECUTING, WorkItemStatus.COMPLETING, WorkItemStatus.EXECUTED, false ); } private void assertUnassignedtRecovery( long woinRefNum ){ assertWoinStatusAndLock( woinRefNum, WorkflowInstanceStatus.NEW, true, null ); recoveryService.recoverExecutionsNotAssignedToNodes( config.getClusterName() ); assertWoinStatusAndLock( woinRefNum, WorkflowInstanceStatus.NEW, false, null ); } private void assertAssignedRecovery( long woinRefNum, WorkflowInstanceStatus currentStatus, WorkflowInstanceStatus expectedStatus ){ assertWoinStatusAndLock( woinRefNum, currentStatus, true, config.getNodeName() ); recoveryService.recoverExecutionsAssignedToNodes( Collections.singletonList( config.getNodeName() ) ); assertWoinStatusAndLock( woinRefNum, expectedStatus, false, null ); } private void assertAssignedRecovery( long woinRefNum, long woitRefNum, WorkflowInstanceStatus currentStatus, WorkflowInstanceStatus expectedStatus, WorkItemStatus currentWoitStatus, WorkItemStatus expectedWoitStatus, boolean hasError ){ assertWoinStatusAndLock( woinRefNum, currentStatus, true, config.getNodeName() ); assertWoitStatus( woitRefNum, currentWoitStatus ); recoveryService.recoverExecutionsAssignedToNodes( Collections.singletonList( config.getNodeName() ) ); assertWoinStatusAndLock( woinRefNum, expectedStatus, hasError, hasError ? config.getNodeName() : null ); assertWoitStatus( woitRefNum, expectedWoitStatus ); Assert.assertEquals( hasError, executionErrorService.findByWoinRefNum( woinRefNum ) != null ); } private void assertWoinStatusAndLock( long refNum, WorkflowInstanceStatus status, boolean locked, String nodeName ){ WorkflowInstance woin = workflowInstanceService.find( refNum ); Assert.assertEquals( status, woin.getStatus() ); Assert.assertEquals( locked, woin.isLocked() ); Assert.assertEquals( nodeName, woin.getNodeName() ); } private void assertWoitStatus( long refNum, WorkItemStatus status ){ WorkItem woit = workItemService.find( refNum ); Assert.assertEquals( status, woit.getStatus() ); } private long createWoit( long woinRefNum, String signal, String bean, String method ){ WorkItem woit = new WorkItem(); woit.setStatus( WorkItemStatus.NEW ); woit.setWoinRefNum( woinRefNum ); woit.setSignal( signal ); woit.setBean( bean ); woit.setMethod( method ); workItemDao.create( Collections.singletonList( woit ) ); return woit.getRefNum(); } @Before public void prepareTest(){ nodeService.findOrCreateByName( config.getNodeName() ); } }