Oozie-CoordinatorXCommand

CoordinatorXCommand是对Coordinator 组件 操作命令的封装类,对coord的命令我们整理为:


Oozie-CoordinatorXCommand_第1张图片
diagram3.png

CoordJobXCommand

/* (non-Javadoc)
 * @see org.apache.oozie.command.XCommand#execute()
 */
@Override
protected CoordinatorJobBean execute() throws CommandException {
    try {
        JPAService jpaService = Services.get().get(JPAService.class);
        CoordinatorJobBean coordJob = null;
        if (jpaService != null) {
            coordJob = jpaService.execute(new CoordJobGetJPAExecutor(id));
            if (getActionInfo) {
                int numAction = jpaService.execute(new CoordActionsCountForJobIdJPAExecutor(id));
                List coordActions = null;
                if (len == 0) {
                    coordActions = new ArrayList();
                }
                else {
                    coordActions = jpaService.execute(new CoordJobGetActionsSubsetJPAExecutor(id, filterMap, offset,
                            len, desc));
                }
                coordJob.setActions(coordActions);
                coordJob.setNumActions(numAction);
            }
        }
        else {
            LOG.error(ErrorCode.E0610);
        }
        return coordJob;
    }
    catch (XException ex) {
        throw new CommandException(ex);
    }
}

获取 coordinator任务信息;

CoordJobsXCommand

/* (non-Javadoc)
 * @see org.apache.oozie.command.XCommand#execute() */
@Override
protected CoordinatorJobInfo execute() throws CommandException {
    try {
        JPAService jpaService = Services.get().get(JPAService.class);
        CoordinatorJobInfo coordInfo = null;
        if (jpaService != null) {
            coordInfo = jpaService.execute(new CoordJobInfoGetJPAExecutor(filter, start, len));
        }
        else {
            LOG.error(ErrorCode.E0610);
        }
        return coordInfo;
    }
    catch (XException ex) {
        throw new CommandException(ex);
    }
}

获取 coordinator 任务列表 信息;

CoordChangeXCommand

@Override
protected Void execute() throws CommandException {
    LOG.info("STARTED CoordChangeXCommand for jobId=" + jobId);
    try {
        if (newEndTime != null) {
            // during coord materialization, nextMaterializedTime is set to
            // startTime + n(actions materialized) * frequency and this can be AFTER endTime,
            // while doneMaterialization is true. Hence the following checks
            // for newEndTime being in the middle of endTime and nextMatdTime.
            // Since job is already done materialization so no need to change            
boolean dontChange = coordJob.getEndTime().before(newEndTime)
                    && coordJob.getNextMaterializedTime() != null
                    && coordJob.getNextMaterializedTime().after(newEndTime);
            if (!dontChange) {
                coordJob.setEndTime(newEndTime);
                // OOZIE-1703, we should SUCCEEDED the coord, if it's in PREP and new endtime is before start time
                if (coordJob.getStartTime().compareTo(newEndTime) >= 0) {
                    if (coordJob.getStatus() != CoordinatorJob.Status.PREP) {
                        processLookaheadActions(coordJob, newEndTime);
                    }
                    if (coordJob.getStatus() == CoordinatorJob.Status.PREP
                            || coordJob.getStatus() == CoordinatorJob.Status.RUNNING) {
                        LOG.info("Changing coord status to SUCCEEDED, because it's in " + coordJob.getStatus()
                                + " and new end time is before start time. Startime is " + coordJob.getStartTime()
                                + " and new end time is " + newEndTime);
                        coordJob.setStatus(CoordinatorJob.Status.SUCCEEDED);                        coordJob.resetPending();
                    }
                    coordJob.setDoneMaterialization();
                }
                else {
                    // move it to running iff new end time is after starttime.
                    if (coordJob.getStatus() == CoordinatorJob.Status.SUCCEEDED) {
                        coordJob.setStatus(CoordinatorJob.Status.RUNNING);                    }
                    if (coordJob.getStatus() == CoordinatorJob.Status.DONEWITHERROR
                            || coordJob.getStatus() == CoordinatorJob.Status.FAILED) {
                        // Check for backward compatibility for Oozie versions (3.2 and before)
                        // when RUNNINGWITHERROR, SUSPENDEDWITHERROR and
                        // PAUSEDWITHERROR is not supported
                        coordJob.setStatus(StatusUtils
                                .getStatusIfBackwardSupportTrue(CoordinatorJob.Status.RUNNINGWITHERROR));
                    }
                    coordJob.setPending();
                    coordJob.resetDoneMaterialization();                    processLookaheadActions(coordJob, newEndTime);
                }
            }
            else {
                LOG.info("Didn't change endtime. Endtime is in between coord end time and next materialization time."
                        + "Coord endTime = " + DateUtils.formatDateOozieTZ(newEndTime)
                        + " next materialization time ="
                        + DateUtils.formatDateOozieTZ(coordJob.getNextMaterializedTime()));
            }
        }
        if (newConcurrency != null) {            this.coordJob.setConcurrency(newConcurrency);
        }
        if (newPauseTime != null || resetPauseTime == true) {
            this.coordJob.setPauseTime(newPauseTime);
            if (oldPauseTime != null && newPauseTime != null) {
                if (oldPauseTime.before(newPauseTime)) {
                    if (this.coordJob.getStatus() == Job.Status.PAUSED) {
                        this.coordJob.setStatus(Job.Status.RUNNING);                    }
                    else if (this.coordJob.getStatus() == Job.Status.PAUSEDWITHERROR) {
                        this.coordJob.setStatus(Job.Status.RUNNINGWITHERROR);                    }
                }
            }
            else if (oldPauseTime != null && newPauseTime == null) {
                if (this.coordJob.getStatus() == Job.Status.PAUSED) {
                    this.coordJob.setStatus(Job.Status.RUNNING);
                }
                else if (this.coordJob.getStatus() == Job.Status.PAUSEDWITHERROR) {
                    this.coordJob.setStatus(Job.Status.RUNNINGWITHERROR);                }
            }
            if (!resetPauseTime) {
                processLookaheadActions(coordJob, newPauseTime);
            }
        }
        if (jobStatus != null) {
            coordJob.setStatus(jobStatus);
            LOG.info("Coord status is changed to " + jobStatus + " from " + prevStatus);
            if (jobStatus.equals(CoordinatorJob.Status.RUNNING)) {
                coordJob.setPending();
                if (coordJob.getNextMaterializedTime() != null
                        && coordJob.getEndTime().after(coordJob.getNextMaterializedTime())) {
                    coordJob.resetDoneMaterialization();
                }
            } else if (jobStatus.equals(CoordinatorJob.Status.IGNORED)) {
                coordJob.resetPending();
                coordJob.setDoneMaterialization();
            }
        }
        if (coordJob.getNextMaterializedTime() != null && coordJob.getEndTime().compareTo(coordJob.getNextMaterializedTime()) <= 0) {
            LOG.info("[" + coordJob.getId() + "]: all actions have been materialized, job status = " + coordJob.getStatus()
                    + ", set pending to true");
           // set doneMaterialization to true when materialization is done            coordJob.setDoneMaterialization();
        }
        coordJob.setLastModifiedTime(new Date());
        updateList.add(new UpdateEntry(CoordJobQuery.UPDATE_COORD_JOB_CHANGE, coordJob));
        BatchQueryExecutor.getInstance().executeBatchInsertUpdateDelete(null, updateList, deleteList);
        return null;
    }
    catch (XException ex) {
        throw new CommandException(ex);
    }
    finally {
        LOG.info("ENDED CoordChangeXCommand for jobId=" + jobId);
        // update bundle action
        if (coordJob.getBundleId() != null) {
            //ignore pending as it'sync command
            BundleStatusUpdateXCommand bundleStatusUpdate = new BundleStatusUpdateXCommand(coordJob, prevStatus, true);
            bundleStatusUpdate.call();
        }
    }
}

更新 coordinator 任务命令;

CoordPushDependencyCheckXCommand

@Override
protected Void execute() throws CommandException {
    String pushMissingDeps = coordAction.getPushMissingDependencies();
    if (pushMissingDeps == null || pushMissingDeps.length() == 0) {
        LOG.info("Nothing to check. Empty push missing dependency");
    }
    else {
        String[] missingDepsArray = DependencyChecker.dependenciesAsArray(pushMissingDeps);
        LOG.info("First Push missing dependency is [{0}] ", missingDepsArray[0]);
        LOG.trace("Push missing dependencies are [{0}] ", pushMissingDeps);
        if (registerForNotification) {
            LOG.debug("Register for notifications is true");
        }
        try {
            Configuration actionConf = null;
            try {
                actionConf = new XConfiguration(new StringReader(coordAction.getRunConf()));
            }
            catch (IOException e) {
                throw new CommandException(ErrorCode.E1307, e.getMessage(), e);
            }
            // Check all dependencies during materialization to avoid registering in the cache.
            // But check only first missing one afterwards similar to
            // CoordActionInputCheckXCommand for efficiency. listPartitions is costly.
            ActionDependency actionDep = DependencyChecker.checkForAvailability(missingDepsArray, actionConf,
                    !registerForNotification);
            boolean isChangeInDependency = true;
            boolean timeout = false;
            if (actionDep.getMissingDependencies().size() == 0) {
                // All push-based dependencies are available
                onAllPushDependenciesAvailable();
            }
            else {
                if (actionDep.getMissingDependencies().size() == missingDepsArray.length) {
                    isChangeInDependency = false;
                }
                else {
                    String stillMissingDeps = DependencyChecker.dependenciesAsString(actionDep
                            .getMissingDependencies());
                    coordAction.setPushMissingDependencies(stillMissingDeps);                
}
                // Checking for timeout
                timeout = isTimeout();
                if (timeout) {
                    queue(new CoordActionTimeOutXCommand(coordAction, coordJob.getUser(), coordJob.getAppName()));
                }
                else {
                    queue(new CoordPushDependencyCheckXCommand(coordAction.getId()),
                            getCoordPushCheckRequeueInterval());
                }
            }
            updateCoordAction(coordAction, isChangeInDependency);
            if (registerForNotification) {
                registerForNotification(actionDep.getMissingDependencies(), actionConf);
            }
            if (removeAvailDependencies) {
                unregisterAvailableDependencies(actionDep.getAvailableDependencies());            }
            if (timeout) {
                unregisterMissingDependencies(actionDep.getMissingDependencies(), actionId);
            }
        }
        catch (Exception e) {
            final CallableQueueService callableQueueService = Services.get().get(CallableQueueService.class);
            if (isTimeout()) {
                LOG.debug("Queueing timeout command");
                // XCommand.queue() will not work when there is a Exception
                callableQueueService.queue(new CoordActionTimeOutXCommand(coordAction, coordJob.getUser(), coordJob.getAppName()));
                unregisterMissingDependencies(Arrays.asList(missingDepsArray), actionId);
            }
            else if (coordAction.getMissingDependencies() != null
                    && coordAction.getMissingDependencies().length() > 0) {
                // Queue again on exception as RecoveryService will not queue this again with
                // the action being updated regularly by CoordActionInputCheckXCommand
                callableQueueService.queue(new CoordPushDependencyCheckXCommand(coordAction.getId(),
                        registerForNotification, removeAvailDependencies),
                        Services.get().getConf().getInt(RecoveryService.CONF_COORD_OLDER_THAN, 600) * 1000);
            }
            throw new CommandException(ErrorCode.E1021, e.getMessage(), e);
        }
    }
    return null;
}

周期性检查coordinator action缺省的依赖,【主动检查】,订阅或者取消订阅分区数据【被动通知】

CoordActionStartXCommand

protected Void execute() throws CommandException {
    boolean makeFail = true;
    String errCode = "";
    String errMsg = "";
    ParamChecker.notEmpty(user, "user");
    log.debug("actionid=" + actionId + ", status=" + coordAction.getStatus());
    if (coordAction.getStatus() == CoordinatorAction.Status.SUBMITTED) {
        // log.debug("getting.. job id: " + coordAction.getJobId());
        // create merged runConf to pass to WF Engine
        Configuration runConf = mergeConfig(coordAction);
        coordAction.setRunConf(XmlUtils.prettyPrint(runConf).toString());
        // log.debug("%%% merged runconf=" +
        // XmlUtils.prettyPrint(runConf).toString());
        DagEngine dagEngine = Services.get().get(DagEngineService.class).getDagEngine(user);
        try {
            Configuration conf = new XConfiguration(new StringReader(coordAction.getRunConf()));
            SLAEventBean slaEvent = SLADbOperations.createStatusEvent(coordAction.getSlaXml(), coordAction.getId(), Status.STARTED,
                    SlaAppType.COORDINATOR_ACTION, log);
            if(slaEvent != null) {
                insertList.add(slaEvent);
            }
            if (OozieJobInfo.isJobInfoEnabled()) {
                conf.set(OozieJobInfo.COORD_NAME, appName);
                conf.set(OozieJobInfo.COORD_NOMINAL_TIME, coordAction.getNominalTimestamp().toString());
            }
            // Normalize workflow appPath here;
            JobUtils.normalizeAppPath(conf.get(OozieClient.USER_NAME), conf.get(OozieClient.GROUP_NAME), conf);
            if (coordAction.getExternalId() != null) {
                conf.setBoolean(OozieClient.RERUN_FAIL_NODES, true);
                dagEngine.reRun(coordAction.getExternalId(), conf);
            } else {
                String wfId = dagEngine.submitJobFromCoordinator(conf, actionId);
                coordAction.setExternalId(wfId);
            }
            coordAction.setStatus(CoordinatorAction.Status.RUNNING);
            coordAction.incrementAndGetPending();
            //store.updateCoordinatorAction(coordAction);
            JPAService jpaService = Services.get().get(JPAService.class);
            if (jpaService != null) {
                log.debug("Updating WF record for WFID :" + coordAction.getExternalId() + " with parent id: " + actionId);
                WorkflowJobBean wfJob = WorkflowJobQueryExecutor.getInstance().get(WorkflowJobQuery.GET_WORKFLOW_STARTTIME, coordAction.getExternalId());
                wfJob.setParentId(actionId);
                wfJob.setLastModifiedTime(new Date());
                BatchQueryExecutor executor = BatchQueryExecutor.getInstance();
                updateList.add(new UpdateEntry(                        WorkflowJobQuery.UPDATE_WORKFLOW_PARENT_MODIFIED, wfJob));                updateList.add(new UpdateEntry(
                        CoordActionQuery.UPDATE_COORD_ACTION_FOR_START, coordAction));
                try {
                    executor.executeBatchInsertUpdateDelete(insertList, updateList, null);
                    queue(new CoordActionNotificationXCommand(coordAction), 100);
                    if (EventHandlerService.isEnabled()) {
                        generateEvent(coordAction, user, appName, wfJob.getStartTime());
                    }
                }
                catch (JPAExecutorException je) {
                    throw new CommandException(je);
                }
            }
            else {
                log.error(ErrorCode.E0610);
            }
            makeFail = false;
        }
        catch (DagEngineException dee) {
            errMsg = dee.getMessage();
            errCode = dee.getErrorCode().toString();
            log.warn("can not create DagEngine for submitting jobs", dee);        }
        catch (CommandException ce) {
            errMsg = ce.getMessage();
            errCode = ce.getErrorCode().toString();
            log.warn("command exception occured ", ce);
        }
        catch (java.io.IOException ioe) {
            errMsg = ioe.getMessage();
            errCode = "E1005";
            log.warn("Configuration parse error. read from DB :" + coordAction.getRunConf(), ioe);
        }
        catch (Exception ex) {
            errMsg = ex.getMessage();
            errCode = "E1005";
            log.warn("can not create DagEngine for submitting jobs", ex);        }
        finally {
            if (makeFail == true) { // No DB exception occurs
                log.error("Failing the action " + coordAction.getId() + ". Because " + errCode + " : " + errMsg);
                coordAction.setStatus(CoordinatorAction.Status.FAILED);
                if (errMsg.length() > 254) { // Because table column size is 255
                    errMsg = errMsg.substring(0, 255);
                }
                coordAction.setErrorMessage(errMsg);
                coordAction.setErrorCode(errCode);
                updateList = new ArrayList();
                updateList.add(new UpdateEntry(
                                CoordActionQuery.UPDATE_COORD_ACTION_FOR_START, coordAction));
                insertList = new ArrayList();
                SLAEventBean slaEvent = SLADbOperations.createStatusEvent(coordAction.getSlaXml(), coordAction.getId(), Status.FAILED,
                        SlaAppType.COORDINATOR_ACTION, log);
                if(slaEvent != null) {

                    insertList.add(slaEvent); //Update SLA events
                }
                try {
                    // call JPAExecutor to do the bulk writes
                    BatchQueryExecutor.getInstance().executeBatchInsertUpdateDelete(insertList, updateList, null);
                    if (EventHandlerService.isEnabled()) {
                        generateEvent(coordAction, user, appName, null);
                    }
                } 
               catch (JPAExecutorException je) {
                    throw new CommandException(je);
                }
                queue(new CoordActionReadyXCommand(coordAction.getJobId()));
            }
        }
    }
    return null;
}

coordinator action开始命令,实际是执行启动了action关联的wf。

CoordActionCheckXCommand


protected Void execute() throws CommandException {
    try {
        InstrumentUtils.incrJobCounter(getName(), 1, getInstrumentation());
        Status slaStatus = null;
        CoordinatorAction.Status initialStatus = coordAction.getStatus();
        if (workflowJob.getStatus() == WorkflowJob.Status.SUCCEEDED) {
            coordAction.setStatus(CoordinatorAction.Status.SUCCEEDED);
            // set pending to false as the status is SUCCEEDED
            coordAction.setPending(0);
            slaStatus = Status.SUCCEEDED;
        }
        else {
            if (workflowJob.getStatus() == WorkflowJob.Status.FAILED) {
                coordAction.setStatus(CoordinatorAction.Status.FAILED);
                slaStatus = Status.FAILED;
                // set pending to false as the status is FAILED
                coordAction.setPending(0);
            }
            else {
                if (workflowJob.getStatus() == WorkflowJob.Status.KILLED) {
                    coordAction.setStatus(CoordinatorAction.Status.KILLED);
                    slaStatus = Status.KILLED;
                    // set pending to false as the status is KILLED
                    coordAction.setPending(0);
                }
                else {
                    LOG.warn("Unexpected workflow " + workflowJob.getId() + " STATUS " + workflowJob.getStatus());
                    coordAction.setLastModifiedTime(new Date());
                    CoordActionQueryExecutor.getInstance().executeUpdate(
                            CoordActionQueryExecutor.CoordActionQuery.UPDATE_COORD_ACTION_FOR_MODIFIED_DATE,
                            coordAction);
                    return null;
                }
            }
        }
        LOG.debug("Updating Coordinator actionId :" + coordAction.getId() + "status to ="
                        + coordAction.getStatus());
        coordAction.setLastModifiedTime(new Date());
        updateList.add(new UpdateEntry(CoordActionQuery.UPDATE_COORD_ACTION_STATUS_PENDING_TIME,
                coordAction));
        if (slaStatus != null) {
            SLAEventBean slaEvent = SLADbOperations.createStatusEvent(coordAction.getSlaXml(), coordAction.getId(), slaStatus,
                    SlaAppType.COORDINATOR_ACTION, LOG);
            if(slaEvent != null) {
                insertList.add(slaEvent);
            }
        }
        BatchQueryExecutor.getInstance().executeBatchInsertUpdateDelete(insertList, updateList, null);
        CoordinatorAction.Status endStatus = coordAction.getStatus();
        if (endStatus != initialStatus && EventHandlerService.isEnabled()) {
            generateEvent(coordAction, coordJob.getUser(), coordJob.getAppName(), workflowJob.getStartTime());
        }
    }
    catch (XException ex) {
        LOG.warn("CoordActionCheckCommand Failed ", ex);
        throw new CommandException(ex);
    }
    return null;
}

主动检查 coordinator action 关联wf的运行状态,来设置coordinator action的状态;[主动检查的方式,还有一种是wf完成后的通知]

CoordActionInfoXCommand

@Override
protected CoordinatorActionBean execute() throws CommandException {
    JPAService jpaService = Services.get().get(JPAService.class);
    if (jpaService != null) {
        CoordinatorActionBean action;
        try {
            action = jpaService.execute(new CoordActionGetForInfoJPAExecutor(this.id));
        }
        catch (JPAExecutorException e) {
           throw new CommandException(e);
        }
        return action;
    }
    else {
        LOG.error(ErrorCode.E0610);
        return null;
    }
}

查看 coordinator action 信息的命令;

CoordActionReadyXCommand

/** * Check for READY actions and change state to SUBMITTED by a command to submit the job to WF engine. 
* This method checks all the actions associated with a jobId to figure out which actions
* to start (based on concurrency and execution order [FIFO, LIFO, LAST_ONLY, NONE])
 * */
protected Void execute() throws CommandException {
    // number of actions to start (-1 means start ALL)
    int numActionsToStart = -1;
    // get execution setting for this job (FIFO, LIFO, LAST_ONLY)
    String jobExecution = coordJob.getExecution();
    // get concurrency setting for this job
    int jobConcurrency = coordJob.getConcurrency();
    // if less than 0, then UNLIMITED concurrency
    if (jobConcurrency >= 0) {
        // count number of actions that are already RUNNING or SUBMITTED
        // subtract from CONCURRENCY to calculate number of actions to start
        // in WF engine
        int numRunningJobs;
        try {
            numRunningJobs = jpaService.execute(new CoordJobGetRunningActionsCountJPAExecutor(jobId));
        }
        catch (JPAExecutorException je) {
            throw new CommandException(je);
        }
        numActionsToStart = jobConcurrency - numRunningJobs;
        if (numActionsToStart < 0) {
            numActionsToStart = 0;
        }
        log.debug("concurrency=" + jobConcurrency + ", execution=" + jobExecution + ", numRunningJobs="
                + numRunningJobs + ", numLeftover=" + numActionsToStart);
        // no actions to start
        if (numActionsToStart == 0) {
            log.warn("No actions to start for jobId=" + jobId + " as max concurrency reached!");
            return null;
        }
    }
    // get list of actions that are READY and fit in the concurrency and execution
List actions;
    try {
        actions = jpaService.execute(new CoordJobGetReadyActionsJPAExecutor(jobId, numActionsToStart, jobExecution));
    }
    catch (JPAExecutorException je) {
        throw new CommandException(je);
    }
    log.debug("Number of READY actions = " + actions.size());
    // make sure auth token is not null
    // log.denug("user=" + user + ", token=" + authToken);
    int counter = 0;
    for (CoordinatorActionBean action : actions) {
        // continue if numActionsToStart is negative (no limit on number of
        // actions), or if the counter is less than numActionsToStart
        if ((numActionsToStart < 0) || (counter < numActionsToStart)) {
            log.debug("Set status to SUBMITTED for id: " + action.getId());
            // change state of action to SUBMITTED
            action.setStatus(CoordinatorAction.Status.SUBMITTED);
            try {
                CoordActionQueryExecutor.getInstance().executeUpdate(
                        CoordActionQuery.UPDATE_COORD_ACTION_STATUS_PENDING_TIME, action);
            }
            catch (JPAExecutorException je) {
                throw new CommandException(je);
            }
            // start action
            new CoordActionStartXCommand(action.getId(), coordJob.getUser(), coordJob.getAppName(),
                    action.getJobId()).call(getEntityKey());
        }
        else {
            break;
        }
        counter++;
    }
    return null;
}

根据并发量,和出队列的方式,来设置 coordinator action 状态从ready到提交状态。

CoordActionSkipXCommand

protected Void execute() throws CommandException {
    if (actionBean.getStatus() == CoordinatorAction.Status.WAITING
            || actionBean.getStatus() == CoordinatorAction.Status.READY) {
        LOG.info("Setting action [{0}] status to SKIPPED", actionBean.getId());
        actionBean.setStatus(CoordinatorAction.Status.SKIPPED);
        try {
            queue(new CoordActionNotificationXCommand(actionBean), 100);
            actionBean.setLastModifiedTime(new Date());
            CoordActionQueryExecutor.getInstance().executeUpdate(
                    CoordActionQuery.UPDATE_COORD_ACTION_STATUS_PENDING_TIME, actionBean);
            if (EventHandlerService.isEnabled()) {
                generateEvent(actionBean, user, appName, null);
            }
        }
        catch (JPAExecutorException e) {
            throw new CommandException(e);
        }
    }
    return null;
}

设置Coordinator action 状态为 SKIPPED;

CoordActionTimeOutXCommand

protected Void execute() throws CommandException {
    if (actionBean.getStatus() == CoordinatorAction.Status.WAITING) {
        actionBean.setStatus(CoordinatorAction.Status.TIMEDOUT);
        try {
            queue(new CoordActionNotificationXCommand(actionBean), 100);
            actionBean.setLastModifiedTime(new Date());
            CoordActionQueryExecutor.getInstance().executeUpdate(
                    CoordActionQuery.UPDATE_COORD_ACTION_STATUS_PENDING_TIME, actionBean);
            if (EventHandlerService.isEnabled()) {
                generateEvent(actionBean, user, appName, null);
            }
        }
        catch (JPAExecutorException e) {
            throw new CommandException(e);
        }
    }
    return null;
}

设置Coordinator action 状态为 超时状态;

CoordActionUpdateXCommand

protected Void execute() throws CommandException {
    try {
        LOG.debug("STARTED CoordActionUpdateXCommand for wfId=" + workflow.getId());
        Status slaStatus = null;
        if (workflow.getStatus() == WorkflowJob.Status.SUCCEEDED) {
            coordAction.setStatus(CoordinatorAction.Status.SUCCEEDED);
            coordAction.setPending(0);
            slaStatus = Status.SUCCEEDED;
        }
        else if (workflow.getStatus() == WorkflowJob.Status.FAILED) {
            coordAction.setStatus(CoordinatorAction.Status.FAILED);
            coordAction.setPending(0);
            slaStatus = Status.FAILED;
        }
        else if (workflow.getStatus() == WorkflowJob.Status.KILLED) {
            coordAction.setStatus(CoordinatorAction.Status.KILLED);
            coordAction.setPending(0);
            slaStatus = Status.KILLED;
        }
        else if (workflow.getStatus() == WorkflowJob.Status.SUSPENDED) {
            coordAction.setStatus(CoordinatorAction.Status.SUSPENDED);
            coordAction.decrementAndGetPending();
        }
        else if (workflow.getStatus() == WorkflowJob.Status.RUNNING ||
                workflow.getStatus() == WorkflowJob.Status.PREP) {
            // resume workflow job and update coord action accordingly
            coordAction.setStatus(CoordinatorAction.Status.RUNNING);
            coordAction.decrementAndGetPending();
        }
        else {
            LOG.warn("Unexpected workflow " + workflow.getId() + " STATUS " + workflow.getStatus());
            // update lastModifiedTime
            coordAction.setLastModifiedTime(new Date());
            CoordActionQueryExecutor.getInstance().executeUpdate(
                    CoordActionQueryExecutor.CoordActionQuery.UPDATE_COORD_ACTION_FOR_MODIFIED_DATE, coordAction);
            // TODO - Uncomment this when bottom up rerun can change terminal state
            /* CoordinatorJobBean coordJob = jpaService.execute(new CoordJobGetJPAExecutor(coordAction.getJobId()));
            if (!coordJob.isPending()) {
                coordJob.setPending();
                jpaService.execute(new CoordJobUpdateJPAExecutor(coordJob));
            }*/
            return null;
        }
        LOG.info("Updating Coordintaor action id :" + coordAction.getId() + " status "
                + " to " + coordAction.getStatus() + ", pending = " + coordAction.getPending());
        coordAction.setLastModifiedTime(new Date());
        updateList.add(new UpdateEntry(CoordActionQuery.UPDATE_COORD_ACTION_STATUS_PENDING_TIME,
                coordAction));
        // TODO - Uncomment this when bottom up rerun can change terminal state
        /*CoordinatorJobBean coordJob = jpaService.execute(new CoordJobGetJPAExecutor(coordAction.getJobId()));
        if (!coordJob.isPending()) {
            coordJob.setPending();
            jpaService.execute(new CoordJobUpdateJPAExecutor(coordJob));
            LOG.info("Updating Coordinator job "+ coordJob.getId() + "pending to true");
        }*/
        if (slaStatus != null) {
            SLAEventBean slaEvent = SLADbOperations.createStatusEvent(coordAction.getSlaXml(), coordAction.getId(), slaStatus,
                    SlaAppType.COORDINATOR_ACTION, LOG);
            if(slaEvent != null) {
                insertList.add(slaEvent);
            }
        }
        if (workflow.getStatus() != WorkflowJob.Status.SUSPENDED
                && workflow.getStatus() != WorkflowJob.Status.RUNNING) {
            queue(new CoordActionReadyXCommand(coordAction.getJobId()));
        }
        BatchQueryExecutor.getInstance().executeBatchInsertUpdateDelete(insertList, updateList, null);
        if (EventHandlerService.isEnabled()) {
            generateEvent(coordAction, coordJob.getUser(), coordJob.getAppName(), workflow.getStartTime());
        }
        LOG.debug("ENDED CoordActionUpdateXCommand for wfId=" + workflow.getId());
    }
    catch (XException ex) {
        LOG.warn("CoordActionUpdate Failed ", ex.getMessage());        throw new CommandException(ex);
    }
    return null;
}

更新Coordinator action 状态

CoordActionInputCheckXCommand


protected Void execute() throws CommandException {
    LOG.debug("[" + actionId + "]::ActionInputCheck:: Action is in WAITING state.");
    // this action should only get processed if current time > nominal time;
    // otherwise, requeue this action for delay execution;
    Date nominalTime = coordAction.getNominalTime();
    Date currentTime = new Date();
    if (nominalTime.compareTo(currentTime) > 0) {
        queue(new CoordActionInputCheckXCommand(coordAction.getId(), coordAction.getJobId()), Math.max((nominalTime.getTime() - currentTime
                .getTime()), getCoordInputCheckRequeueInterval()));
        updateCoordAction(coordAction, false);
        LOG.info("[" + actionId
                + "]::ActionInputCheck:: nominal Time is newer than current time, so requeue and wait. Current="
                + DateUtils.formatDateOozieTZ(currentTime) + ", nominal=" + DateUtils.formatDateOozieTZ(nominalTime));
        return null;
    }
    StringBuilder actionXml = new StringBuilder(coordAction.getActionXml());
    boolean isChangeInDependency = false;
    try {
        Configuration actionConf = new XConfiguration(new StringReader(coordAction.getRunConf()));
        Date now = new Date();
        if (coordJob.getExecutionOrder().equals(CoordinatorJobBean.Execution.LAST_ONLY)) {
            Date nextNominalTime = computeNextNominalTime();
            if (nextNominalTime != null) {
                // If the current time is after the next action's nominal time, then we've passed the window where this action
                // should be started; so set it to SKIPPED
                if (now.after(nextNominalTime)) {
                    LOG.info("LAST_ONLY execution: Preparing to skip action [{0}] because the current time [{1}] is later than "
                            + "the nominal time [{2}] of the next action]", coordAction.getId(),
                            DateUtils.formatDateOozieTZ(now), DateUtils.formatDateOozieTZ(nextNominalTime));
                    queue(new CoordActionSkipXCommand(coordAction, coordJob.getUser(), coordJob.getAppName()));
                    return null;
                } else {
                    LOG.debug("LAST_ONLY execution: Not skipping action [{0}] because the current time [{1}] is earlier than "
                            + "the nominal time [{2}] of the next action]", coordAction.getId(),
                            DateUtils.formatDateOozieTZ(now), DateUtils.formatDateOozieTZ(nextNominalTime));
                }
            }
        }
        else if (coordJob.getExecutionOrder().equals(CoordinatorJobBean.Execution.NONE)) {
            // If the current time is after the nominal time of this action plus some tolerance,
            // then we've passed the window where this action
            // should be started; so set it to SKIPPED
            Calendar cal = Calendar.getInstance(DateUtils.getTimeZone(coordJob.getTimeZone()));
            cal.setTime(nominalTime);
            cal.add(Calendar.MINUTE, ConfigurationService.getInt(COORD_EXECUTION_NONE_TOLERANCE));
            nominalTime = cal.getTime();
            if (now.after(nominalTime)) {
                LOG.info("NONE execution: Preparing to skip action [{0}] because the current time [{1}] is later than "
                        + "the nominal time [{2}] of the current action]", coordAction.getId(),
                        DateUtils.formatDateOozieTZ(now), DateUtils.formatDateOozieTZ(nominalTime));
                queue(new CoordActionSkipXCommand(coordAction, coordJob.getUser(), coordJob.getAppName()));
                return null;
            } else {
                LOG.debug("NONE execution: Not skipping action [{0}] because the current time [{1}] is earlier than "
                        + "the nominal time [{2}] of the current action]", coordAction.getId(),
                        DateUtils.formatDateOozieTZ(now), DateUtils.formatDateOozieTZ(coordAction.getNominalTime()));
            }
        }
        StringBuilder existList = new StringBuilder();
        StringBuilder nonExistList = new StringBuilder();
        StringBuilder nonResolvedList = new StringBuilder();
        String firstMissingDependency = "";
        String missingDeps = coordAction.getMissingDependencies();
        CoordCommandUtils.getResolvedList(missingDeps, nonExistList, nonResolvedList);
        // For clarity regarding which is the missing dependency in synchronous order
        // instead of printing entire list, some of which, may be available
        if(nonExistList.length() > 0) {
            firstMissingDependency = nonExistList.toString().split(CoordELFunctions.INSTANCE_SEPARATOR)[0];
        }
        LOG.info("[" + actionId + "]::CoordActionInputCheck:: Missing deps:" + firstMissingDependency + " "
                + nonResolvedList.toString());
        // Updating the list of data dependencies that are available and those that are yet not
        boolean status = checkInput(actionXml, existList, nonExistList, actionConf);
        String pushDeps = coordAction.getPushMissingDependencies();
        // Resolve latest/future only when all current missingDependencies and
        // pushMissingDependencies are met
        if (status && nonResolvedList.length() > 0) {
            status = (pushDeps == null || pushDeps.length() == 0) ? checkUnResolvedInput(actionXml, actionConf)
                    : false;
        }
        coordAction.setLastModifiedTime(currentTime);
        coordAction.setActionXml(actionXml.toString());
        if (nonResolvedList.length() > 0 && status == false) {
            nonExistList.append(CoordCommandUtils.RESOLVED_UNRESOLVED_SEPARATOR).append(nonResolvedList);
        }
        String nonExistListStr = nonExistList.toString();
        if (!nonExistListStr.equals(missingDeps) || missingDeps.isEmpty()) {
            // missingDeps null or empty means action should become READY
            isChangeInDependency = true;
            coordAction.setMissingDependencies(nonExistListStr);
        }
        if (status && (pushDeps == null || pushDeps.length() == 0)) {
            String newActionXml = resolveCoordConfiguration(actionXml, actionConf, actionId);
            actionXml.replace(0, actionXml.length(), newActionXml);
            coordAction.setActionXml(actionXml.toString());
            coordAction.setStatus(CoordinatorAction.Status.READY);
            updateCoordAction(coordAction, true);
            new CoordActionReadyXCommand(coordAction.getJobId()).call(getEntityKey());        }
        else if (!isTimeout(currentTime)) {
            if (status == false) {
                queue(new CoordActionInputCheckXCommand(coordAction.getId(), coordAction.getJobId()),
                        getCoordInputCheckRequeueInterval());
            }
            updateCoordAction(coordAction, isChangeInDependency);
        }
        else {
            if (!nonExistListStr.isEmpty() && pushDeps == null || pushDeps.length() == 0) {
                queue(new CoordActionTimeOutXCommand(coordAction, coordJob.getUser(), coordJob.getAppName()));
            }
            else {
                // Let CoordPushDependencyCheckXCommand queue the timeout
                queue(new CoordPushDependencyCheckXCommand(coordAction.getId()));
            }
            updateCoordAction(coordAction, isChangeInDependency);
        }
    }
    catch (AccessControlException e) {
        LOG.error("Permission error in ActionInputCheck", e);
        if (isTimeout(currentTime)) {
            LOG.debug("Queueing timeout command");
            Services.get().get(CallableQueueService.class)                    .queue(new CoordActionTimeOutXCommand(coordAction, coordJob.getUser(), coordJob.getAppName()));
        }
        else {
            // Requeue InputCheckCommand for permission denied error with longer interval
            Services.get()
                    .get(CallableQueueService.class)
                    .queue(new CoordActionInputCheckXCommand(coordAction.getId(), coordAction.getJobId()),
                            2 * getCoordInputCheckRequeueInterval());
        }
        updateCoordAction(coordAction, isChangeInDependency);
    }    catch (Exception e) {
        if (isTimeout(currentTime)) {
            LOG.debug("Queueing timeout command");
            // XCommand.queue() will not work when there is a Exception
            Services.get().get(CallableQueueService.class)
                    .queue(new CoordActionTimeOutXCommand(coordAction, coordJob.getUser(), coordJob.getAppName()));
        }
        updateCoordAction(coordAction, isChangeInDependency);
        throw new CommandException(ErrorCode.E1021, e.getMessage(), e);
    }
    return null;
}

检查action的输入依赖是否满足,已经时间条件是否满足。

你可能感兴趣的:(Oozie-CoordinatorXCommand)