/** * Copyright 2016 vip.com. * <p> * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * </p> */ package com.vip.saturn.job.internal.execution; import java.util.Date; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Function; import com.google.common.collect.Lists; import com.vip.saturn.job.SaturnJobReturn; import com.vip.saturn.job.SaturnSystemErrorGroup; import com.vip.saturn.job.basic.AbstractSaturnService; import com.vip.saturn.job.basic.JobExecutionMultipleShardingContext; import com.vip.saturn.job.basic.JobScheduler; import com.vip.saturn.job.basic.SaturnExecutionContext; import com.vip.saturn.job.internal.config.ConfigurationService; import com.vip.saturn.job.internal.control.ExecutionInfo; import com.vip.saturn.job.internal.control.ReportService; import com.vip.saturn.job.internal.failover.FailoverNode; import com.vip.saturn.job.internal.server.ServerService; import com.vip.saturn.job.internal.server.ServerStatus; /** * 执行作业的服务. * @author dylan.xue */ public class ExecutionService extends AbstractSaturnService { private static final String NO_RETURN_VALUE = "No return value."; static Logger log = LoggerFactory.getLogger(ExecutionService.class); private ConfigurationService configService; private ServerService serverService; private ReportService reportService; public ExecutionService(final JobScheduler jobScheduler) { super(jobScheduler); } @Override public void start(){ configService = jobScheduler.getConfigService(); serverService = jobScheduler.getServerService(); reportService = jobScheduler.getReportService(); } /** * 更新当前作业服务器运行时分片的nextFireTime。 * * @param shardingItems 作业运行时分片上下文 */ public void updateNextFireTime(final List<Integer> shardingItems) { if (!shardingItems.isEmpty()) { for (int item : shardingItems) { updateNextFireTimeByItem(item); } } } private void updateNextFireTimeByItem(int item) { if (null == jobScheduler) { return; } Date nextFireTimePausePeriodEffected = jobScheduler.getNextFireTimePausePeriodEffected(); if (null != nextFireTimePausePeriodEffected) { //String pausePeriodEffectedNode = ExecutionNode.getPausePeriodEffectedNode(item); getJobNodeStorage().replaceJobNode(ExecutionNode.getNextFireTimeNode(item), nextFireTimePausePeriodEffected.getTime()); //getJobNodeStorage().replaceJobNode(pausePeriodEffectedNode, nextFireTimePausePeriodEffected.isPausePeriodEffected()); } } /** * 注册作业启动信息. * * @param jobExecutionShardingContext 作业运行时分片上下文 */ public void registerJobBegin(final JobExecutionMultipleShardingContext jobExecutionShardingContext) { List<Integer> shardingItems = jobExecutionShardingContext.getShardingItems(); if (!shardingItems.isEmpty()) { if (jobConfiguration.isEnabledReport() == null) { if ("JAVA_JOB".equals(jobConfiguration.getJobType()) || "SHELL_JOB".equals(jobConfiguration.getJobType())) { serverService.updateServerStatus(ServerStatus.RUNNING); } } else if (jobConfiguration.isEnabledReport()) { serverService.updateServerStatus(ServerStatus.RUNNING); } reportService.clearInfoMap(); Date nextFireTimePausePeriodEffected = jobScheduler.getNextFireTimePausePeriodEffected(); Long nextFireTime = nextFireTimePausePeriodEffected == null?null:nextFireTimePausePeriodEffected.getTime(); for (int item : shardingItems) { registerJobBeginByItem(jobExecutionShardingContext, item, nextFireTime); } } } public void registerJobBeginByItem(final JobExecutionMultipleShardingContext jobExecutionShardingContext, int item, Long nextFireTime) { if (log.isDebugEnabled()) { log.debug("registerJobBeginByItem: " + item); } if (jobConfiguration.isEnabledReport() == null){ if("JAVA_JOB".equals(jobConfiguration.getJobType()) || "SHELL_JOB".equals(jobConfiguration.getJobType())) { getJobNodeStorage().removeJobNodeIfExisted(ExecutionNode.getCompletedNode(item)); getJobNodeStorage().fillEphemeralJobNode(ExecutionNode.getRunningNode(item), ""); // 清除完成状态timeout等信息 cleanSaturnNode(item); } } else if (jobConfiguration.isEnabledReport()) { getJobNodeStorage().removeJobNodeIfExisted(ExecutionNode.getCompletedNode(item)); getJobNodeStorage().fillEphemeralJobNode(ExecutionNode.getRunningNode(item), ""); // 清除完成状态timeout等信息 cleanSaturnNode(item); } reportService.initInfoOnBegin(item, nextFireTime); //getJobNodeStorage().replaceJobNode(ExecutionNode.getLastBeginTimeNode(item), System.currentTimeMillis()); //updateNextFireTimeAndPausePeriodEffected(item); } public void registerJobCompletedByItem(final JobExecutionMultipleShardingContext jobExecutionShardingContext, int item, Date nextFireTimePausePeriodEffected) { registerJobCompletedControlInfoByItem(jobExecutionShardingContext, item); registerJobCompletedReportInfoByItem(jobExecutionShardingContext, item, nextFireTimePausePeriodEffected); } public void registerJobCompletedReportInfoByItem(final JobExecutionMultipleShardingContext jobExecutionShardingContext, int item, Date nextFireTimePausePeriodEffected) { ExecutionInfo info = reportService.getInfoByItem(item); if (info == null) { // old data has been flushed to zk. info = new ExecutionInfo(item); } if (jobExecutionShardingContext instanceof SaturnExecutionContext) { // 为了展现分片处理失败的状态 SaturnExecutionContext saturnContext = (SaturnExecutionContext) jobExecutionShardingContext; if (saturnContext.isSaturnJob()) { SaturnJobReturn jobRet = saturnContext.getShardingItemResults().get(item); if(jobRet != null) { int errorGroup = jobRet.getErrorGroup(); info.setJobLog(saturnContext.getJobLog(item)); info.setJobMsg(jobRet.getReturnMsg()); if(errorGroup == SaturnSystemErrorGroup.SUCCESS) { if (!configService.showNormalLog()) { info.setJobLog(null); } } } else { info.setJobMsg(NO_RETURN_VALUE); } } } //Date nextFireTimePausePeriodEffected = jobScheduler.getNextFireTimePausePeriodEffected(); if (null != nextFireTimePausePeriodEffected) { info.setNextFireTime(nextFireTimePausePeriodEffected.getTime()); } info.setLastCompleteTime(System.currentTimeMillis()); reportService.fillInfoOnAfter(info); } /** * 注册作业完成信息. * */ public void registerJobCompletedControlInfoByItem(final JobExecutionMultipleShardingContext jobExecutionShardingContext, int item) { if (jobExecutionShardingContext instanceof SaturnExecutionContext) { // 为了展现分片处理失败的状态 SaturnExecutionContext saturnContext = (SaturnExecutionContext) jobExecutionShardingContext; if (saturnContext.isSaturnJob()) { SaturnJobReturn jobRet = saturnContext.getShardingItemResults().get(item); if (jobRet != null) { int errorGroup = jobRet.getErrorGroup(); if (errorGroup == SaturnSystemErrorGroup.TIMEOUT) { if (jobConfiguration.isEnabledReport() == null) { if ("JAVA_JOB".equals(jobConfiguration.getJobType()) || "SHELL_JOB".equals(jobConfiguration.getJobType())) { getJobNodeStorage().createJobNodeIfNeeded(ExecutionNode.getTimeoutNode(item)); } } else if (jobConfiguration.isEnabledReport()) { getJobNodeStorage().createJobNodeIfNeeded(ExecutionNode.getTimeoutNode(item)); } } else if (errorGroup == SaturnSystemErrorGroup.FAIL) { if (jobConfiguration.isEnabledReport() == null) { if ("JAVA_JOB".equals(jobConfiguration.getJobType()) || "SHELL_JOB".equals(jobConfiguration.getJobType())) { getJobNodeStorage().createJobNodeIfNeeded(ExecutionNode.getFailedNode(item)); } } else if (jobConfiguration.isEnabledReport()) { getJobNodeStorage().createJobNodeIfNeeded(ExecutionNode.getFailedNode(item)); } } } else { if (jobConfiguration.isEnabledReport() == null){ if ("JAVA_JOB".equals(jobConfiguration.getJobType()) || "SHELL_JOB".equals(jobConfiguration.getJobType())) { getJobNodeStorage().createJobNodeIfNeeded(ExecutionNode.getFailedNode(item)); } } else if (jobConfiguration.isEnabledReport()) { getJobNodeStorage().createJobNodeIfNeeded(ExecutionNode.getFailedNode(item)); } } } } //updateNextFireTimeAndPausePeriodEffected(item); if(jobConfiguration.isEnabledReport() == null){ if("JAVA_JOB".equals(jobConfiguration.getJobType()) || "SHELL_JOB".equals(jobConfiguration.getJobType())){ getJobNodeStorage().createJobNodeIfNeeded(ExecutionNode.getCompletedNode(item)); getJobNodeStorage().removeJobNodeIfExisted(ExecutionNode.getRunningNode(item)); } }else if(jobConfiguration.isEnabledReport()){ getJobNodeStorage().createJobNodeIfNeeded(ExecutionNode.getCompletedNode(item)); getJobNodeStorage().removeJobNodeIfExisted(ExecutionNode.getRunningNode(item)); } } /** * 设置修复运行时分片信息标记的状态标志位. */ /* public void setNeedFixExecutionInfoFlag() { getJobNodeStorage().createJobNodeIfNeeded(ExecutionNode.NECESSARY); }*/ /** * 清除分配分片序列号的运行状态. * * <p> * 用于作业服务器恢复连接注册中心而重新上线的场景, 先清理上次运行时信息. * </p> * * @param items 需要清理的分片项列表 */ public void clearRunningInfo(final List<Integer> items) { for (int each : items) { // 已被其他executor接管的正在failover的分片不清理running节点,防止清理节点时触发JobCrashedJobListener导致重新failover了一次 if(!getJobNodeStorage().isJobNodeExisted(FailoverNode.getExecutionFailoverNode(each))){ getJobNodeStorage().removeJobNodeIfExisted(ExecutionNode.getRunningNode(each)); //清除完成状态timeout等信息 cleanSaturnNode(each); } } } /** * 删除作业执行时信息. */ public void removeExecutionInfo() { getJobNodeStorage().removeJobNodeIfExisted(ExecutionNode.ROOT); } /** * 判断该分片是否已完成. * * @param item 运行中的分片路径 * @return 该分片是否已完成 */ public boolean isCompleted(final int item) { return getJobNodeStorage().isJobNodeExisted(ExecutionNode.getCompletedNode(item)); } public boolean isRunning(final int item) { return getJobNodeStorage().isJobNodeExisted(ExecutionNode.getRunningNode(item)); } public boolean isFailover(final int item) { return getJobNodeStorage().isJobNodeExisted(FailoverNode.getExecutionFailoverNode(item)); } /** * 判断分片项中是否还有执行中的作业. * * @param items 需要判断的分片项列表 * @return 分片项中是否还有执行中的作业 */ public boolean hasRunningItems(final List<Integer> items) { for (int each : items) { if (getJobNodeStorage().isJobNodeExisted(ExecutionNode.getRunningNode(each))) { return true; } } return false; } /** * 判断是否还有执行中的作业. * * @return 是否还有执行中的作业 */ public boolean hasRunningItems() { return hasRunningItems(getAllItems()); } private List<Integer> getAllItems() { return Lists.transform(getJobNodeStorage().getJobNodeChildrenKeys(ExecutionNode.ROOT), new Function<String, Integer>() { @Override public Integer apply(final String input) { return Integer.parseInt(input); } }); } /** * 删除Saturn的作业item信息 * @param item 作业分片 */ private void cleanSaturnNode(int item){ getJobNodeStorage().removeJobNodeIfExisted(ExecutionNode.getFailedNode(item)); getJobNodeStorage().removeJobNodeIfExisted(ExecutionNode.getTimeoutNode(item)); // getJobNodeStorage().removeJobNodeIfExisted(ExecutionNode.getJobMsg(item)); // getJobNodeStorage().removeJobNodeIfExisted(ExecutionNode.getJobLog(item)); } }