@Override public void reRun(String cluster, String jobId, Properties props, boolean isForced) throws FalconException { InstanceState instanceState = STATE_STORE.getExecutionInstance(jobId); ExecutionInstance instance = instanceState.getInstance(); EntityExecutor executor = EXECUTION_SERVICE.getEntityExecutor(instance.getEntity(), cluster); executor.rerun(instance, props, isForced); }
@Test public void testInstanceInsertionAndUpdate() throws Exception { storeEntity(EntityType.CLUSTER, "testCluster"); storeEntity(EntityType.FEED, "clicksFeed"); storeEntity(EntityType.FEED, "clicksSummary"); EntityState entityState = getEntityState(EntityType.PROCESS, "process"); ExecutionInstance executionInstance = BeanMapperUtil.getExecutionInstance( entityState.getEntity().getEntityType(), entityState.getEntity(), System.currentTimeMillis(), "cluster", System.currentTimeMillis()); InstanceState instanceState = new InstanceState(executionInstance); initInstanceState(instanceState); stateStore.putExecutionInstance(instanceState); InstanceID instanceID = new InstanceID(instanceState.getInstance()); InstanceState actualInstanceState = stateStore.getExecutionInstance(instanceID); Assert.assertEquals(actualInstanceState, instanceState); instanceState.setCurrentState(InstanceState.STATE.RUNNING); Predicate predicate = new Predicate(Predicate.TYPE.DATA); instanceState.getInstance().getAwaitingPredicates().add(predicate); stateStore.updateExecutionInstance(instanceState); actualInstanceState = stateStore.getExecutionInstance(instanceID); Assert.assertEquals(actualInstanceState, instanceState); try { stateStore.putExecutionInstance(instanceState); Assert.fail("Exception must have been thrown"); } catch (StateStoreException e) { // no op } stateStore.deleteExecutionInstance(instanceID); try { stateStore.getExecutionInstance(instanceID); Assert.fail("Exception must have been thrown"); } catch (StateStoreException e) { // no op } try { stateStore.deleteExecutionInstance(instanceID); Assert.fail("Exception must have been thrown"); } catch (StateStoreException e) { // no op } try { stateStore.updateExecutionInstance(instanceState); Assert.fail("Exception must have been thrown"); } catch (StateStoreException e) { // no op } }
private void initInstanceState(InstanceState instanceState) { instanceState.setCurrentState(InstanceState.STATE.READY); instanceState.getInstance().setExternalID(RandomStringUtils.randomNumeric(6)); instanceState.getInstance().setInstanceSequence(randomValGenerator.nextInt()); instanceState.getInstance().setActualStart(new DateTime(System.currentTimeMillis())); instanceState.getInstance().setActualEnd(new DateTime(System.currentTimeMillis())); List<Predicate> predicates = new ArrayList<>(); Predicate predicate = new Predicate(Predicate.TYPE.JOB_COMPLETION); predicates.add(predicate); instanceState.getInstance().setAwaitingPredicates(predicates); }
@Test public void testGetExecutionSummaryWithRange() throws Exception { storeEntity(EntityType.CLUSTER, "testCluster"); storeEntity(EntityType.FEED, "clicksFeed"); storeEntity(EntityType.FEED, "clicksSummary"); long instance1Time = System.currentTimeMillis() - 180000; long instance2Time = System.currentTimeMillis(); EntityState entityState = getEntityState(EntityType.PROCESS, "clicksProcess"); ExecutionInstance processExecutionInstance1 = BeanMapperUtil.getExecutionInstance( entityState.getEntity().getEntityType(), entityState.getEntity(), instance1Time, "cluster1", instance1Time); InstanceState instanceState1 = new InstanceState(processExecutionInstance1); instanceState1.setCurrentState(InstanceState.STATE.RUNNING); ExecutionInstance processExecutionInstance2 = BeanMapperUtil.getExecutionInstance( entityState.getEntity().getEntityType(), entityState.getEntity(), instance2Time, "cluster1", instance2Time); InstanceState instanceState2 = new InstanceState(processExecutionInstance2); instanceState2.setCurrentState(InstanceState.STATE.SUCCEEDED); stateStore.putExecutionInstance(instanceState1); stateStore.putExecutionInstance(instanceState2); Map<InstanceState.STATE, Long> summary = stateStore.getExecutionInstanceSummary( entityState.getEntity(), "cluster1", new DateTime(instance1Time), new DateTime(instance1Time + 60000)); Assert.assertEquals(summary.size(), 1); Assert.assertEquals(summary.get(InstanceState.STATE.RUNNING).longValue(), 1L); summary = stateStore.getExecutionInstanceSummary( entityState.getEntity(), "cluster1", new DateTime(instance2Time), new DateTime(instance2Time + 60000)); Assert.assertEquals(summary.size(), 1); Assert.assertEquals(summary.get(InstanceState.STATE.SUCCEEDED).longValue(), 1L); }
@Override public String touch(Entity entity, String cluster, Boolean skipDryRun) throws FalconException { EntityID id = new EntityID(entity); // Ideally state store should have all entities, but, check anyway. if (STATE_STORE.entityExists(id)) { Date endTime = EntityUtil.getEndTime(entity, cluster); if (endTime.before(DateUtil.now())) { throw new FalconException( "Entity's end time " + SchemaHelper.formatDateUTC(endTime) + " is before current time. Entity can't be touch-ed as it has completed."); } Collection<InstanceState> instances = STATE_STORE.getExecutionInstances(entity, cluster, InstanceState.getRunningStates()); // touch should happen irrespective of the state the entity is in. DAGEngineFactory.getDAGEngine(cluster) .touch(entity, (skipDryRun == null) ? Boolean.FALSE : skipDryRun); StringBuilder builder = new StringBuilder(); builder .append(entity.toShortString()) .append("/Effective Time: ") .append(getEffectiveTime(entity, cluster, instances)); return builder.toString(); } throw new FalconException("Could not find entity " + id + " in state store."); }
@Test public void testCascadingDelete() throws Exception { storeEntity(EntityType.CLUSTER, "testCluster"); storeEntity(EntityType.FEED, "clicksFeed"); storeEntity(EntityType.FEED, "clicksSummary"); EntityState entityState = getEntityState(EntityType.PROCESS, "process1"); stateStore.putEntity(entityState); ExecutionInstance processExecutionInstance1 = BeanMapperUtil.getExecutionInstance( entityState.getEntity().getEntityType(), entityState.getEntity(), System.currentTimeMillis() - 60000, "cluster1", System.currentTimeMillis() - 60000); InstanceState instanceState1 = new InstanceState(processExecutionInstance1); instanceState1.setCurrentState(InstanceState.STATE.READY); ExecutionInstance processExecutionInstance2 = BeanMapperUtil.getExecutionInstance( entityState.getEntity().getEntityType(), entityState.getEntity(), System.currentTimeMillis(), "cluster1", System.currentTimeMillis()); InstanceState instanceState2 = new InstanceState(processExecutionInstance2); instanceState2.setCurrentState(InstanceState.STATE.RUNNING); stateStore.putExecutionInstance(instanceState1); stateStore.putExecutionInstance(instanceState2); Collection<InstanceState> instances = stateStore.getAllExecutionInstances(entityState.getEntity(), "cluster1"); Assert.assertEquals(instances.size(), 2); stateStore.deleteEntity(new EntityID(entityState.getEntity())); deleteEntity(EntityType.PROCESS, "process1"); instances = stateStore.getAllExecutionInstances(entityState.getEntity(), "cluster1"); Assert.assertEquals(instances.size(), 0); }
@Override public InstancesResult getRunningInstances(Entity entity, List<LifeCycle> lifeCycles) throws FalconException { Set<String> clusters = EntityUtil.getClustersDefinedInColos(entity); List<InstancesResult.Instance> runInstances = new ArrayList<>(); for (String cluster : clusters) { Collection<InstanceState> instances = STATE_STORE.getExecutionInstances(entity, cluster, InstanceState.getRunningStates()); for (InstanceState state : instances) { String instanceTimeStr = state.getInstance().getInstanceTime().toString(); InstancesResult.Instance instance = new InstancesResult.Instance( cluster, instanceTimeStr, InstancesResult.WorkflowStatus.RUNNING); instance.startTime = state.getInstance().getActualStart().toDate(); runInstances.add(instance); } } InstancesResult result = new InstancesResult(APIResult.Status.SUCCEEDED, "Running Instances"); result.setInstances(runInstances.toArray(new InstancesResult.Instance[runInstances.size()])); return result; }
@Test public void testGetInstanceFromExternalID() throws Exception { storeEntity(EntityType.CLUSTER, "testCluster"); storeEntity(EntityType.FEED, "clicksFeed"); storeEntity(EntityType.FEED, "clicksSummary"); long instance1Time = System.currentTimeMillis() - 180000; long instance2Time = System.currentTimeMillis(); EntityState entityState = getEntityState(EntityType.PROCESS, "processext"); ExecutionInstance processExecutionInstance1 = BeanMapperUtil.getExecutionInstance( entityState.getEntity().getEntityType(), entityState.getEntity(), instance1Time, "cluster1", instance1Time); processExecutionInstance1.setExternalID("external_id_1"); InstanceState instanceState1 = new InstanceState(processExecutionInstance1); instanceState1.setCurrentState(InstanceState.STATE.RUNNING); ExecutionInstance processExecutionInstance2 = BeanMapperUtil.getExecutionInstance( entityState.getEntity().getEntityType(), entityState.getEntity(), instance2Time, "cluster1", instance2Time); processExecutionInstance2.setExternalID("external_id_2"); InstanceState instanceState2 = new InstanceState(processExecutionInstance2); instanceState2.setCurrentState(InstanceState.STATE.RUNNING); stateStore.putExecutionInstance(instanceState1); stateStore.putExecutionInstance(instanceState2); InstanceState actualInstanceState = stateStore.getExecutionInstance("external_id_1"); Assert.assertEquals(actualInstanceState.getInstance(), processExecutionInstance1); actualInstanceState = stateStore.getExecutionInstance("external_id_2"); Assert.assertEquals(actualInstanceState.getInstance(), processExecutionInstance2); }
private InstancesResult doJobAction( JobAction action, Entity entity, Date start, Date end, Properties props, List<LifeCycle> lifeCycles, boolean isForced) throws FalconException { Set<String> clusters = EntityUtil.getClustersDefinedInColos(entity); List<String> clusterList = getIncludedClusters(props, FALCON_INSTANCE_ACTION_CLUSTERS); APIResult.Status overallStatus = APIResult.Status.SUCCEEDED; int instanceCount = 0; Collection<InstanceState.STATE> states; switch (action) { case KILL: case SUSPEND: states = InstanceState.getActiveStates(); break; case RESUME: states = new ArrayList<>(); states.add(InstanceState.STATE.SUSPENDED); break; case PARAMS: // Applicable only for running and finished jobs. states = InstanceState.getRunningStates(); states.addAll(InstanceState.getTerminalStates()); states.add(InstanceState.STATE.SUSPENDED); break; case STATUS: states = InstanceState.getActiveStates(); states.addAll(InstanceState.getTerminalStates()); states.add(InstanceState.STATE.SUSPENDED); break; case RERUN: // Applicable only for terminated States states = InstanceState.getTerminalStates(); break; default: throw new IllegalArgumentException("Unhandled action " + action); } List<ExecutionInstance> instancesToActOn = new ArrayList<>(); for (String cluster : clusters) { if (clusterList.size() != 0 && !clusterList.contains(cluster)) { continue; } LOG.debug("Retrieving instances for cluster : {} for action {}", cluster, action); Collection<InstanceState> instances = STATE_STORE.getExecutionInstances( entity, cluster, states, new DateTime(start), new DateTime(end)); for (InstanceState state : instances) { instancesToActOn.add(state.getInstance()); } } // To ensure compatibility with OozieWorkflowEngine. // Also because users would like to see the most recent instances first. sortInstancesDescBySequence(instancesToActOn); List<InstancesResult.Instance> instances = new ArrayList<>(); for (ExecutionInstance ins : instancesToActOn) { instanceCount++; String instanceTimeStr = SchemaHelper.formatDateUTC(ins.getInstanceTime().toDate()); InstancesResult.Instance instance = null; try { instance = performAction(ins.getCluster(), entity, action, ins, props, isForced); instance.instance = instanceTimeStr; } catch (FalconException e) { LOG.warn("Unable to perform action {} on cluster", action, e); instance = new InstancesResult.Instance(ins.getCluster(), instanceTimeStr, null); instance.status = InstancesResult.WorkflowStatus.ERROR; instance.details = e.getMessage(); overallStatus = APIResult.Status.PARTIAL; } instances.add(instance); } if (instanceCount < 2 && overallStatus == APIResult.Status.PARTIAL) { overallStatus = APIResult.Status.FAILED; } InstancesResult instancesResult = new InstancesResult(overallStatus, action.name()); instancesResult.setInstances(instances.toArray(new InstancesResult.Instance[instances.size()])); return instancesResult; }
@Test public void testGetExecutionInstancesWithRange() throws Exception { storeEntity(EntityType.CLUSTER, "testCluster"); storeEntity(EntityType.FEED, "clicksFeed"); storeEntity(EntityType.FEED, "clicksSummary"); long instance1Time = System.currentTimeMillis() - 180000; long instance2Time = System.currentTimeMillis(); EntityState entityState = getEntityState(EntityType.PROCESS, "process1"); ExecutionInstance processExecutionInstance1 = BeanMapperUtil.getExecutionInstance( entityState.getEntity().getEntityType(), entityState.getEntity(), instance1Time, "cluster1", instance1Time); InstanceState instanceState1 = new InstanceState(processExecutionInstance1); instanceState1.setCurrentState(InstanceState.STATE.RUNNING); ExecutionInstance processExecutionInstance2 = BeanMapperUtil.getExecutionInstance( entityState.getEntity().getEntityType(), entityState.getEntity(), instance2Time, "cluster1", instance2Time); InstanceState instanceState2 = new InstanceState(processExecutionInstance2); instanceState2.setCurrentState(InstanceState.STATE.RUNNING); ExecutionInstance processExecutionInstance3 = BeanMapperUtil.getExecutionInstance( entityState.getEntity().getEntityType(), entityState.getEntity(), instance2Time, "cluster2", instance2Time); InstanceState instanceState3 = new InstanceState(processExecutionInstance3); instanceState3.setCurrentState(InstanceState.STATE.RUNNING); stateStore.putExecutionInstance(instanceState1); stateStore.putExecutionInstance(instanceState2); stateStore.putExecutionInstance(instanceState3); List<InstanceState.STATE> states = new ArrayList<>(); states.add(InstanceState.STATE.RUNNING); Collection<InstanceState> actualInstances = stateStore.getExecutionInstances( entityState.getEntity(), "cluster1", states, new DateTime(instance1Time), new DateTime(instance1Time + 60000)); Assert.assertEquals(actualInstances.size(), 1); Assert.assertEquals(actualInstances.toArray()[0], instanceState1); actualInstances = stateStore.getExecutionInstances( entityState.getEntity(), "cluster1", states, new DateTime(instance2Time), new DateTime(instance2Time + 60000)); Assert.assertEquals(actualInstances.size(), 1); Assert.assertEquals(actualInstances.toArray()[0], instanceState2); // Ensure we can get instances for a different cluster actualInstances = stateStore.getExecutionInstances( entityState.getEntity(), "cluster2", states, new DateTime(instance2Time), new DateTime(instance2Time + 60000)); Assert.assertEquals(actualInstances.size(), 1); Assert.assertEquals(actualInstances.toArray()[0], instanceState3); }
@Test public void testBulkInstanceOperations() throws Exception { storeEntity(EntityType.CLUSTER, "testCluster"); storeEntity(EntityType.FEED, "clicksFeed"); storeEntity(EntityType.FEED, "clicksSummary"); EntityState entityState = getEntityState(EntityType.PROCESS, "process1"); ExecutionInstance processExecutionInstance1 = BeanMapperUtil.getExecutionInstance( entityState.getEntity().getEntityType(), entityState.getEntity(), System.currentTimeMillis() - 60000, "cluster1", System.currentTimeMillis() - 60000); InstanceState instanceState1 = new InstanceState(processExecutionInstance1); instanceState1.setCurrentState(InstanceState.STATE.READY); ExecutionInstance processExecutionInstance2 = BeanMapperUtil.getExecutionInstance( entityState.getEntity().getEntityType(), entityState.getEntity(), System.currentTimeMillis(), "cluster1", System.currentTimeMillis()); InstanceState instanceState2 = new InstanceState(processExecutionInstance2); instanceState2.setCurrentState(InstanceState.STATE.RUNNING); ExecutionInstance processExecutionInstance3 = BeanMapperUtil.getExecutionInstance( entityState.getEntity().getEntityType(), entityState.getEntity(), System.currentTimeMillis(), "cluster2", System.currentTimeMillis()); InstanceState instanceState3 = new InstanceState(processExecutionInstance3); instanceState3.setCurrentState(InstanceState.STATE.READY); stateStore.putExecutionInstance(instanceState1); stateStore.putExecutionInstance(instanceState2); stateStore.putExecutionInstance(instanceState3); Collection<InstanceState> actualInstances = stateStore.getAllExecutionInstances(entityState.getEntity(), "cluster1"); Assert.assertEquals(actualInstances.size(), 2); Assert.assertEquals(actualInstances.toArray()[0], instanceState1); Assert.assertEquals(actualInstances.toArray()[1], instanceState2); actualInstances = stateStore.getAllExecutionInstances(entityState.getEntity(), "cluster2"); Assert.assertEquals(actualInstances.size(), 1); Assert.assertEquals(actualInstances.toArray()[0], instanceState3); List<InstanceState.STATE> states = new ArrayList<>(); states.add(InstanceState.STATE.READY); actualInstances = stateStore.getExecutionInstances(entityState.getEntity(), "cluster1", states); Assert.assertEquals(actualInstances.size(), 1); Assert.assertEquals(actualInstances.toArray()[0], instanceState1); EntityClusterID entityClusterID = new EntityClusterID(entityState.getEntity(), "testCluster"); actualInstances = stateStore.getExecutionInstances(entityClusterID, states); Assert.assertEquals(actualInstances.size(), 2); Assert.assertEquals(actualInstances.toArray()[0], instanceState1); Assert.assertEquals(actualInstances.toArray()[1], instanceState3); states.add(InstanceState.STATE.RUNNING); actualInstances = stateStore.getExecutionInstances(entityState.getEntity(), "cluster1", states); Assert.assertEquals(actualInstances.size(), 2); Assert.assertEquals(actualInstances.toArray()[0], instanceState1); Assert.assertEquals(actualInstances.toArray()[1], instanceState2); InstanceState lastInstanceState = stateStore.getLastExecutionInstance(entityState.getEntity(), "cluster1"); Assert.assertEquals(lastInstanceState, instanceState2); InstanceID instanceKey = new InstanceID(instanceState3.getInstance()); stateStore.deleteExecutionInstance(instanceKey); actualInstances = stateStore.getAllExecutionInstances(entityState.getEntity(), "cluster2"); Assert.assertEquals(actualInstances.size(), 0); actualInstances = stateStore.getAllExecutionInstances(entityState.getEntity(), "cluster1"); Assert.assertEquals(actualInstances.size(), 2); stateStore.putExecutionInstance(instanceState3); actualInstances = stateStore.getAllExecutionInstances(entityState.getEntity(), "cluster2"); Assert.assertEquals(actualInstances.size(), 1); stateStore.deleteExecutionInstances(entityClusterID.getEntityID()); actualInstances = stateStore.getAllExecutionInstances(entityState.getEntity(), "cluster1"); Assert.assertEquals(actualInstances.size(), 0); actualInstances = stateStore.getAllExecutionInstances(entityState.getEntity(), "cluster2"); Assert.assertEquals(actualInstances.size(), 0); }