@Test public void testDefaultChainedExecutable() throws Exception { DefaultChainedExecutable job = new DefaultChainedExecutable(); job.addTask(new SucceedTestExecutable()); job.addTask(new SucceedTestExecutable()); service.addJob(job); assertEquals(2, job.getTasks().size()); AbstractExecutable anotherJob = service.getJob(job.getId()); assertEquals(DefaultChainedExecutable.class, anotherJob.getClass()); assertEquals(2, ((DefaultChainedExecutable) anotherJob).getTasks().size()); assertJobEqual(job, anotherJob); }
@Override protected void addStepPhase1_DoCreateFlatTable(DefaultChainedExecutable jobFlow) { final String cubeName = CubingExecutableUtil.getCubeName(jobFlow.getParams()); final String hiveInitStatements = JoinedFlatTable.generateHiveInitStatements(flatTableDatabase); final String jobWorkingDir = getJobWorkingDir(jobFlow, hdfsWorkingDir); jobFlow.addTask(createSqoopToFlatHiveStep(jobWorkingDir, cubeName)); jobFlow.addTask(createFlatHiveTableFromFiles(hiveInitStatements, jobWorkingDir)); }
@Override protected void onExecuteStart(ExecutableContext executableContext) { final long startTime = getStartTime(); Map<String, String> info = Maps.newHashMap(); info.put(BUILD_INSTANCE, DistributedLockFactory.processAndHost()); if (startTime > 0) { getManager().updateJobOutput(getId(), ExecutableState.RUNNING, info, null); } else { info.put(START_TIME, Long.toString(System.currentTimeMillis())); getManager().updateJobOutput(getId(), ExecutableState.RUNNING, info, null); } }
@Test public void testSchedulerStop() throws Exception { logger.info("testSchedulerStop"); thrown.expect(RuntimeException.class); thrown.expectMessage("too long wait time"); DefaultChainedExecutable job = new DefaultChainedExecutable(); BaseTestExecutable task1 = new FiveSecondSucceedTestExecutable(); job.addTask(task1); execMgr.addJob(job); //sleep 3s to make sure SucceedTestExecutable is running Thread.sleep(3000); //scheduler failed due to some reason scheduler.shutdown(); waitForJobFinish(job.getId(), 6000); }
DefaultChainedExecutable job = new DefaultChainedExecutable(); job.setParam("segmentId", tableName); job.setName("Hive Column Cardinality calculation for table '" + tableName + "'"); job.setSubmitter(submitter); String outPath = getConfig().getHdfsWorkingDirectory() + "cardinality/" + job.getId() + "/" + tableName; String param = "-table " + tableName + " -output " + outPath + " -project " + prj; step1.setParam("segmentId", tableName); job.addTask(step1); step2.setJobParams(param); step2.setParam("segmentId", tableName); job.addTask(step2); tableExt.setJodID(job.getId()); getTableManager().saveTableExt(tableExt, prj);
@Override protected void onExecuteFinished(ExecuteResult result, ExecutableContext executableContext) { ExecutableManager mgr = getManager(); if (isDiscarded()) { setEndTime(System.currentTimeMillis()); onStatusChange(executableContext, result, ExecutableState.DISCARDED); } else if (isPaused()) { setEndTime(System.currentTimeMillis()); onStatusChange(executableContext, result, ExecutableState.STOPPED); } else if (result.succeed()) { List<? extends Executable> jobs = getTasks(); boolean allSucceed = true; boolean hasError = false; + "it might cause endless state, will retry to fetch subtask's state.", task.getId(), task.getName()); getManager().updateJobOutput(task.getId(), ExecutableState.ERROR, null, "killed due to inconsistent state"); hasError = true; setEndTime(System.currentTimeMillis()); mgr.updateJobOutput(getId(), ExecutableState.SUCCEED, null, null); onStatusChange(executableContext, result, ExecutableState.SUCCEED); } else if (hasError) { setEndTime(System.currentTimeMillis()); mgr.updateJobOutput(getId(), ExecutableState.ERROR, null, null); onStatusChange(executableContext, result, ExecutableState.ERROR); } else if (hasDiscarded) { setEndTime(System.currentTimeMillis());
@Override protected void onExecuteFinished(ExecuteResult result, ExecutableContext executableContext) { if (isDiscarded()) { setEndTime(System.currentTimeMillis()); notifyUserStatusChange(ExecutableState.DISCARDED); } else if (result.succeed()) { List<? extends Executable> jobs = getTasks(); boolean allSucceed = true; boolean hasError = false; setEndTime(System.currentTimeMillis()); jobService.updateJobOutput(getId(), ExecutableState.SUCCEED, null, null); notifyUserStatusChange(ExecutableState.SUCCEED); } else if (hasError) { setEndTime(System.currentTimeMillis()); jobService.updateJobOutput(getId(), ExecutableState.ERROR, null, null); notifyUserStatusChange(ExecutableState.ERROR); } else { jobService.updateJobOutput(getId(), ExecutableState.READY, null, null); setEndTime(System.currentTimeMillis()); jobService.updateJobOutput(getId(), ExecutableState.ERROR, null, null); notifyUserStatusChange(ExecutableState.ERROR);
@Override public void addTask(AbstractExecutable executable) { executable.setParentExecutable(this); executable.setId(getId() + "-" + String.format(Locale.ROOT, "%02d", subTasks.size())); this.subTasks.add(executable); }
ExecutableOutputPO output = outputs.get(job.getId()); if (output == null) { logger.warn("job output is null."); String cubeName = CubingExecutableUtil.getCubeName(job.getParams()); cubeName = job.getParam("model_name"); } else { CubeInstance cube = CubeManager.getInstance(KylinConfig.getInstanceFromEnv()).getCube(cubeName); result.setId(job.getId()); result.setJobName(job.getName()); result.setLastModified(output.getLastModified()); return result;
@Override public void addStepPhase4_Cleanup(DefaultChainedExecutable jobFlow) { jobFlow.addTask(createGCStep(intermediateTables, intermediatePaths)); } }
@Override protected ExecuteResult doWork(ExecutableContext context) throws ExecuteException { List<? extends Executable> executables = getTasks(); final int size = executables.size(); for (int i = 0; i < size; ++i) { Executable subTask = executables.get(i); ExecutableState state = subTask.getStatus(); if (state == ExecutableState.RUNNING) { // there is already running subtask, no need to start a new subtask break; } else if (state == ExecutableState.STOPPED) { // the job is paused break; } else if (state == ExecutableState.ERROR) { throw new IllegalStateException( "invalid subtask state, subtask:" + subTask.getName() + ", state:" + subTask.getStatus()); } if (subTask.isRunnable()) { return subTask.execute(context); } } return new ExecuteResult(ExecuteResult.State.SUCCEED); }
@Test public void testRetryableException() throws Exception { DefaultChainedExecutable job = new DefaultChainedExecutable(); BaseTestExecutable task = new ErrorTestExecutable(); job.addTask(task); System.setProperty("kylin.job.retry", "3"); //don't retry on DefaultChainedExecutable, only retry on subtasks Assert.assertFalse(job.needRetry(1, new Exception(""))); Assert.assertTrue(task.needRetry(1, new Exception(""))); Assert.assertFalse(task.needRetry(1, null)); Assert.assertFalse(task.needRetry(4, new Exception(""))); System.setProperty("kylin.job.retry-exception-classes", "java.io.FileNotFoundException"); Assert.assertTrue(task.needRetry(1, new FileNotFoundException())); Assert.assertFalse(task.needRetry(1, new Exception(""))); } }
@Override protected void onExecuteStart(ExecutableContext executableContext) { Map<String, String> info = Maps.newHashMap(); info.put(START_TIME, Long.toString(System.currentTimeMillis())); final long startTime = getStartTime(); if (startTime > 0) { jobService.updateJobOutput(getId(), ExecutableState.RUNNING, null, null); } else { jobService.updateJobOutput(getId(), ExecutableState.RUNNING, info, null); } }
@Override protected void onExecuteFinished(ExecuteResult result, ExecutableContext executableContext) { long time = 0L; for (AbstractExecutable task : getTasks()) { final ExecutableState status = task.getStatus(); if (status != ExecutableState.SUCCEED) { break; } if (task instanceof MapReduceExecutable) { time += ((MapReduceExecutable) task).getMapReduceWaitTime(); } } setMapReduceWaitTime(time); super.onExecuteFinished(result, executableContext); }
private String findExtraInfo(String key, String dft, boolean backward) { ArrayList<AbstractExecutable> tasks = new ArrayList<AbstractExecutable>(getTasks()); if (backward) { Collections.reverse(tasks); } for (AbstractExecutable child : tasks) { Output output = getManager().getOutput(child.getId()); String value = output.getExtra().get(key); if (value != null) return value; } return dft; } }
@Test public void testDiscard() throws Exception { logger.info("testDiscard"); DefaultChainedExecutable job = new DefaultChainedExecutable(); SelfStopExecutable task1 = new SelfStopExecutable(); job.addTask(task1); execMgr.addJob(job); Thread.sleep(1100); // give time to launch job/task1 waitForJobStatus(job.getId(), ExecutableState.RUNNING, 500); execMgr.discardJob(job.getId()); waitForJobFinish(job.getId(), 10000); Assert.assertEquals(ExecutableState.DISCARDED, execMgr.getOutput(job.getId()).getState()); Assert.assertEquals(ExecutableState.DISCARDED, execMgr.getOutput(task1.getId()).getState()); task1.waitForDoWork(); }
@Override protected void onExecuteFinished(ExecuteResult result, ExecutableContext executableContext) { ExecutableManager mgr = getManager(); if (isDiscarded()) { setEndTime(System.currentTimeMillis()); onStatusChange(executableContext, result, ExecutableState.DISCARDED); } else if (isPaused()) { setEndTime(System.currentTimeMillis()); onStatusChange(executableContext, result, ExecutableState.STOPPED); } else if (result.succeed()) { List<? extends Executable> jobs = getTasks(); boolean allSucceed = true; boolean hasError = false; + "it might cause endless state, will retry to fetch subtask's state.", task.getId(), task.getName()); getManager().updateJobOutput(task.getId(), ExecutableState.ERROR, null, "killed due to inconsistent state"); hasError = true; setEndTime(System.currentTimeMillis()); mgr.updateJobOutput(getId(), ExecutableState.SUCCEED, null, null); onStatusChange(executableContext, result, ExecutableState.SUCCEED); } else if (hasError) { setEndTime(System.currentTimeMillis()); mgr.updateJobOutput(getId(), ExecutableState.ERROR, null, null); onStatusChange(executableContext, result, ExecutableState.ERROR); } else if (hasDiscarded) { setEndTime(System.currentTimeMillis());
@Override protected void onExecuteFinished(ExecuteResult result, ExecutableContext executableContext) { if (isDiscarded()) { setEndTime(System.currentTimeMillis()); notifyUserStatusChange(ExecutableState.DISCARDED); } else if (result.succeed()) { List<? extends Executable> jobs = getTasks(); boolean allSucceed = true; boolean hasError = false; setEndTime(System.currentTimeMillis()); jobService.updateJobOutput(getId(), ExecutableState.SUCCEED, null, null); notifyUserStatusChange(ExecutableState.SUCCEED); } else if (hasError) { setEndTime(System.currentTimeMillis()); jobService.updateJobOutput(getId(), ExecutableState.ERROR, null, null); notifyUserStatusChange(ExecutableState.ERROR); } else { jobService.updateJobOutput(getId(), ExecutableState.READY, null, null); setEndTime(System.currentTimeMillis()); jobService.updateJobOutput(getId(), ExecutableState.ERROR, null, null); notifyUserStatusChange(ExecutableState.ERROR);
protected String getJobWorkingDir(DefaultChainedExecutable jobFlow) { return JobBuilderSupport.getJobWorkingDir(config.getHdfsWorkingDirectory(), jobFlow.getId()); }