@Test public void testInitializationSecondFailed() throws Exception { DateTime expectedStartTime = new DateTime(0); DateTime falseStartTime = new DateTime(1); DateTime expectedEndTime = new DateTime(100); DateTime falseEndTime = new DateTime(99); EasyMock.expect(mockFlow1.getName()).andReturn("a").once(); EasyMock.expect(mockFlow2.getName()).andReturn("b").once(); EasyMock.expect(mockFlow1.getStatus()).andReturn(Status.READY).times(2); EasyMock.expect(mockFlow2.getStatus()).andReturn(Status.FAILED).times(2); EasyMock.expect(mockFlow1.getStartTime()).andReturn(expectedStartTime).once(); EasyMock.expect(mockFlow1.getEndTime()).andReturn(falseEndTime).once(); EasyMock.expect(mockFlow2.getStartTime()).andReturn(falseStartTime).once(); EasyMock.expect(mockFlow2.getEndTime()).andReturn(expectedEndTime).once(); EasyMock.expect(mockFlow2.getParentProps()).andReturn(props).once(); EasyMock.expect(mockFlow1.getName()).andReturn("1").once(); EasyMock.expect(mockFlow2.getName()).andReturn("2").once(); EasyMock.replay(mockFlow1, mockFlow2, props); flow = new GroupedExecutableFlow("blah", mockFlow1, mockFlow2); Assert.assertEquals(Status.FAILED, flow.getStatus()); Assert.assertEquals(expectedStartTime, flow.getStartTime()); Assert.assertEquals(expectedEndTime, flow.getEndTime()); Assert.assertEquals(emptyExceptions, flow.getExceptions()); Assert.assertEquals(props, flow.getParentProps()); }
public GroupedExecutableFlow(String id, ExecutableFlow... flows) { this.id = id; this.flows = flows; this.sortedFlows = Arrays.copyOf(this.flows, this.flows.length); Arrays.sort( this.sortedFlows, new Comparator<ExecutableFlow>() { @Override public int compare(ExecutableFlow o1, ExecutableFlow o2) { return o1.getName().compareTo(o2.getName()); } }); String[] names = new String[flows.length]; for (int i = 0; i < flows.length; i++) { names[i] = flows[i].getName(); } name = StringUtils.join(names, " + "); jobState = Status.READY; updateState(); callbacksToCall = new ArrayList<FlowCallback>(); theGroupCallback = new GroupedFlowCallback(); switch (jobState) { case SUCCEEDED: case COMPLETED: case FAILED: DateTime theStartTime = new DateTime(); DateTime theEndTime = new DateTime(0); for (ExecutableFlow flow : flows) { final DateTime subFlowStartTime = flow.getStartTime(); if (theStartTime.isAfter(subFlowStartTime)) { theStartTime = subFlowStartTime; } final DateTime subFlowEndTime = flow.getEndTime(); if (subFlowEndTime != null && subFlowEndTime.isAfter(theEndTime)) { theEndTime = subFlowEndTime; } } setAndVerifyParentProps(); startTime = theStartTime; endTime = theEndTime; break; default: // Check for Flows that are "RUNNING" boolean allRunning = true; List<ExecutableFlow> runningFlows = new ArrayList<ExecutableFlow>(); DateTime thisStartTime = null; for (ExecutableFlow flow : flows) { if (flow.getStatus() != Status.RUNNING) { allRunning = false; final DateTime subFlowStartTime = flow.getStartTime(); if (subFlowStartTime != null && subFlowStartTime.isBefore(thisStartTime)) { thisStartTime = subFlowStartTime; } } else { runningFlows.add(flow); } } if (allRunning) { jobState = Status.RUNNING; } for (ExecutableFlow runningFlow : runningFlows) { final DateTime subFlowStartTime = runningFlow.getStartTime(); if (subFlowStartTime != null && subFlowStartTime.isBefore(thisStartTime)) { thisStartTime = subFlowStartTime; } } setAndVerifyParentProps(); startTime = thisStartTime; endTime = null; // Make sure everything is initialized before leaking the pointer to "this". // This is just installing the callback in an already running flow. for (ExecutableFlow runningFlow : runningFlows) { runningFlow.execute(parentProps, theGroupCallback); } } }