com.vip.saturn.job.console.service.impl.RestApiServiceImpl Maven / Gradle / Ivy
/**
* Copyright 2016 vip.com.
*
* 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.
*
**/
package com.vip.saturn.job.console.service.impl;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.gson.Gson;
import com.vip.saturn.job.console.domain.*;
import com.vip.saturn.job.console.exception.SaturnJobConsoleException;
import com.vip.saturn.job.console.exception.SaturnJobConsoleHttpException;
import com.vip.saturn.job.console.mybatis.entity.JobConfig4DB;
import com.vip.saturn.job.console.mybatis.service.CurrentJobConfigService;
import com.vip.saturn.job.console.repository.zookeeper.CuratorRepository;
import com.vip.saturn.job.console.service.JobService;
import com.vip.saturn.job.console.service.RegistryCenterService;
import com.vip.saturn.job.console.service.RestApiService;
import com.vip.saturn.job.console.service.helper.ReuseCallBack;
import com.vip.saturn.job.console.service.helper.ReuseCallBackWithoutReturn;
import com.vip.saturn.job.console.service.helper.ReuseUtils;
import com.vip.saturn.job.console.utils.JobNodePath;
import com.vip.saturn.job.console.utils.SaturnConstants;
import com.vip.saturn.job.integrate.entity.AlarmInfo;
import com.vip.saturn.job.integrate.exception.ReportAlarmException;
import com.vip.saturn.job.integrate.service.ReportAlarmService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.*;
/**
* @author hebelala
*/
public class RestApiServiceImpl implements RestApiService {
private static final Logger log = LoggerFactory.getLogger(RestApiServiceImpl.class);
private static final long STATUS_UPDATE_FORBIDDEN_INTERVAL_IN_MILL_SECONDS = 3 * 1000L;
private static final long OPERATION_FORBIDDEN_INTERVAL_AFTER_CREATION_IN_MILL_SECONDS = 10 * 1000L;
private static final String JOB_STATUS_NOT_CORRECT_TEMPATE = "job's status is not {%s}";
private static final String ALL_EXECUTORS_ARE_OFFLINE = "all executors are offline";
private static final String NO_EXECUTOR_FOUND = "no executor found for this job";
private static final String EXECUTOR_RESTART_TIME_PREFIX = "restart on ";
@Resource
private RegistryCenterService registryCenterService;
@Resource
private CuratorRepository curatorRepository;
@Resource
private JobService jobService;
@Resource
private CurrentJobConfigService currentJobConfigService;
@Resource
private ReportAlarmService reportAlarmService;
private Gson gson = new Gson();
@Override
public void createJob(final String namespace, final JobConfig jobConfig) throws SaturnJobConsoleException {
ReuseUtils.reuse(namespace, registryCenterService, curatorRepository, new ReuseCallBackWithoutReturn() {
@Override
public void call(CuratorRepository.CuratorFrameworkOp curatorFrameworkOp) throws SaturnJobConsoleException {
jobService.addJob(namespace, jobConfig, "");
}
});
}
@Override
public RestApiJobInfo getRestAPIJobInfo(String namespace, final String jobName) throws SaturnJobConsoleException {
return ReuseUtils.reuse(namespace, jobName, registryCenterService, curatorRepository,
new ReuseCallBack() {
@Override
public RestApiJobInfo call(CuratorRepository.CuratorFrameworkOp curatorFrameworkOp)
throws SaturnJobConsoleException {
if (!curatorFrameworkOp.checkExists(JobNodePath.getConfigNodePath(jobName))) {
throw new SaturnJobConsoleHttpException(HttpStatus.NOT_FOUND.value(),
"The jobName does not existed");
}
return constructJobInfo(curatorFrameworkOp, jobName);
}
});
}
@Override
public List getRestApiJobInfos(final String namespace) throws SaturnJobConsoleException {
return ReuseUtils
.reuse(namespace, registryCenterService, curatorRepository, new ReuseCallBack>() {
@Override
public List call(CuratorRepository.CuratorFrameworkOp curatorFrameworkOp)
throws SaturnJobConsoleException {
List restApiJobInfos = new ArrayList<>();
List unSystemJobs = jobService.getUnSystemJobs(namespace);
if (unSystemJobs != null) {
for (JobConfig job : unSystemJobs) {
try {
RestApiJobInfo restApiJobInfo = constructJobInfo(curatorFrameworkOp,
job.getJobName());
restApiJobInfos.add(restApiJobInfo);
} catch (Exception e) {
log.error("getRestApiJobInfos exception:", e);
continue;
}
}
}
return restApiJobInfos;
}
});
}
private RestApiJobInfo constructJobInfo(CuratorRepository.CuratorFrameworkOp curatorFrameworkOp, String job) {
RestApiJobInfo restApiJobInfo = new RestApiJobInfo();
restApiJobInfo.setJobName(job);
// 设置作业配置信息
setJobConfig(curatorFrameworkOp, restApiJobInfo, job);
// 设置运行状态
setRunningStatus(curatorFrameworkOp, restApiJobInfo, job);
// 设置统计信息
RestApiJobStatistics restApiJobStatistics = new RestApiJobStatistics();
setStatics(curatorFrameworkOp, restApiJobStatistics, job);
restApiJobInfo.setStatistics(restApiJobStatistics);
return restApiJobInfo;
}
private void setRunningStatus(CuratorRepository.CuratorFrameworkOp curatorFrameworkOp,
RestApiJobInfo restApiJobInfo, String jobName) {
String executionNodePath = JobNodePath.getExecutionNodePath(jobName);
List items = curatorFrameworkOp.getChildren(executionNodePath);
boolean isRunning = false;
if (items != null) {
for (String item : items) {
String runningNodePath = JobNodePath.getExecutionNodePath(jobName, item, "running");
if (curatorFrameworkOp.checkExists(runningNodePath)) {
isRunning = true;
break;
}
}
}
String enabledNodePath = JobNodePath.getConfigNodePath(jobName, "enabled");
if (Boolean.parseBoolean(curatorFrameworkOp.getData(enabledNodePath))) {
if (isRunning) {
restApiJobInfo.setRunningStatus(JobStatus.RUNNING.name());
} else {
restApiJobInfo.setRunningStatus(JobStatus.READY.name());
}
} else {
if (isRunning) {
restApiJobInfo.setRunningStatus(JobStatus.STOPPING.name());
} else {
restApiJobInfo.setRunningStatus(JobStatus.STOPPED.name());
}
}
}
private void setJobConfig(CuratorRepository.CuratorFrameworkOp curatorFrameworkOp, RestApiJobInfo restApiJobInfo,
String jobName) {
String configNodePath = JobNodePath.getConfigNodePath(jobName);
if (curatorFrameworkOp.checkExists(configNodePath)) {
restApiJobInfo
.setDescription(curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "description")));
restApiJobInfo.setEnabled(
Boolean.valueOf(curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "enabled"))));
RestApiJobConfig restApiJobConfig = new RestApiJobConfig();
restApiJobConfig
.setJobClass(curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "jobClass")));
restApiJobConfig.setJobType(curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "jobType")));
restApiJobConfig.setShardingTotalCount(Integer.valueOf(
curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "shardingTotalCount"))));
restApiJobConfig.setShardingItemParameters(
curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "shardingItemParameters")));
restApiJobConfig.setJobParameter(
curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "jobParameter")));
String timeZone = curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "timeZone"));
if (timeZone == null || timeZone.trim().length() == 0) {
timeZone = SaturnConstants.TIME_ZONE_ID_DEFAULT;
}
restApiJobConfig.setTimeZone(timeZone);
restApiJobConfig.setCron(curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "cron")));
restApiJobConfig.setPausePeriodDate(
curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "pausePeriodDate")));
restApiJobConfig.setPausePeriodTime(
curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "pausePeriodTime")));
String timeout4AlarmSecondsStr = curatorFrameworkOp
.getData(JobNodePath.getConfigNodePath(jobName, "timeout4AlarmSeconds"));
if (timeout4AlarmSecondsStr != null) {
restApiJobConfig.setTimeout4AlarmSeconds(Integer.valueOf(timeout4AlarmSecondsStr));
} else {
restApiJobConfig.setTimeout4AlarmSeconds(0);
}
restApiJobConfig.setTimeoutSeconds(Integer.valueOf(
curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "timeoutSeconds"))));
restApiJobConfig
.setChannelName(curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "channelName")));
restApiJobConfig
.setQueueName(curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "queueName")));
restApiJobConfig.setLoadLevel(
Integer.valueOf(curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "loadLevel"))));
String jobDegree = curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "jobDegree"));
if (!Strings.isNullOrEmpty(jobDegree)) {
restApiJobConfig.setJobDegree(Integer.valueOf(
curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "jobDegree"))));
}
restApiJobConfig.setEnabledReport(Boolean.valueOf(
curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "enabledReport"))));
restApiJobConfig
.setPreferList(curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "preferList")));
restApiJobConfig.setUseDispreferList(Boolean.valueOf(
curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "useDispreferList"))));
restApiJobConfig.setLocalMode(
Boolean.valueOf(curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "localMode"))));
restApiJobConfig.setUseSerial(
Boolean.valueOf(curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "useSerial"))));
restApiJobConfig.setDependencies(
curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "dependencies")));
restApiJobConfig.setGroups(curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "groups")));
restApiJobConfig.setShowNormalLog(Boolean.valueOf(
curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "showNormalLog"))));
restApiJobConfig.setProcessCountInterValSeconds(Integer.valueOf(
curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "processCountIntervalSeconds"))));
restApiJobInfo.setJobConfig(restApiJobConfig);
}
}
private void setStatics(CuratorRepository.CuratorFrameworkOp curatorFrameworkOp,
RestApiJobStatistics restApiJobStatistics, String jobName) {
setProcessCount(curatorFrameworkOp, restApiJobStatistics, jobName);
setTimes(curatorFrameworkOp, restApiJobStatistics, jobName);
}
private void setProcessCount(CuratorRepository.CuratorFrameworkOp curatorFrameworkOp,
RestApiJobStatistics restApiJobStatistics, String jobName) {
String processCountPath = JobNodePath.getProcessCountPath(jobName);
String processCountStr = curatorFrameworkOp.getData(processCountPath);
if (processCountStr != null) {
try {
restApiJobStatistics.setProcessCount(Long.valueOf(processCountStr));
} catch (NumberFormatException e) {
log.error(e.getMessage(), e);
}
}
String errorCountPath = JobNodePath.getErrorCountPath(jobName);
String errorCountPathStr = curatorFrameworkOp.getData(errorCountPath);
if (errorCountPathStr != null) {
try {
restApiJobStatistics.setProcessErrorCount(Long.valueOf(errorCountPathStr));
} catch (NumberFormatException e) {
log.error(e.getMessage(), e);
}
}
}
private void setTimes(CuratorRepository.CuratorFrameworkOp curatorFrameworkOp,
RestApiJobStatistics restApiJobStatistics, String jobName) {
String executionNodePath = JobNodePath.getExecutionNodePath(jobName);
List items = curatorFrameworkOp.getChildren(executionNodePath);
if (items == null) {
return;
}
List lastBeginTimeList = new ArrayList<>();
List lastCompleteTimeList = new ArrayList<>();
List nextFireTimeList = new ArrayList<>();
int runningItemSize = 0;
for (String item : items) {
if (getRunningIP(item, jobName, curatorFrameworkOp) == null) {
continue;
}
++runningItemSize;
String lastBeginTime = curatorFrameworkOp
.getData(JobNodePath.getExecutionNodePath(jobName, item, "lastBeginTime"));
if (null != lastBeginTime) {
lastBeginTimeList.add(lastBeginTime);
}
String lastCompleteTime = curatorFrameworkOp
.getData(JobNodePath.getExecutionNodePath(jobName, item, "lastCompleteTime"));
if (null != lastCompleteTime) {
boolean isItemCompleted = curatorFrameworkOp
.checkExists(JobNodePath.getExecutionNodePath(jobName, item, "completed"));
boolean isItemRunning = curatorFrameworkOp
.checkExists(JobNodePath.getExecutionNodePath(jobName, item, "running"));
if (isItemCompleted && !isItemRunning) { // 如果作业分片已执行完毕,则添加该完成时间到集合中进行排序
lastCompleteTimeList.add(lastCompleteTime);
}
}
String nextFireTime = curatorFrameworkOp
.getData(JobNodePath.getExecutionNodePath(jobName, item, "nextFireTime"));
if (null != nextFireTime) {
nextFireTimeList.add(nextFireTime);
}
}
if (!CollectionUtils.isEmpty(lastBeginTimeList)) {
Collections.sort(lastBeginTimeList);
try {
restApiJobStatistics.setLastBeginTime(Long.valueOf(lastBeginTimeList.get(0))); // 所有分片中最近最早的开始时间
} catch (NumberFormatException e) {
log.error(e.getMessage(), e);
}
}
if (!CollectionUtils.isEmpty(lastCompleteTimeList)
&& lastCompleteTimeList.size() == runningItemSize) { // 所有分配都完成才显示最近最晚的完成时间
Collections.sort(lastCompleteTimeList);
try {
restApiJobStatistics.setLastCompleteTime(
Long.valueOf(lastCompleteTimeList.get(lastCompleteTimeList.size() - 1))); // 所有分片中最近最晚的完成时间
} catch (NumberFormatException e) {
log.error(e.getMessage(), e);
}
}
if (!CollectionUtils.isEmpty(nextFireTimeList)) {
Collections.sort(nextFireTimeList);
try {
restApiJobStatistics.setNextFireTime(Long.valueOf(nextFireTimeList.get(0))); // 所有分片中下次最早的开始时间
} catch (NumberFormatException e) {
log.error(e.getMessage(), e);
}
}
}
private String getRunningIP(String item, String jobName, CuratorRepository.CuratorFrameworkOp curatorFrameworkOp) {
String runningIp = null;
String serverNodePath = JobNodePath.getServerNodePath(jobName);
if (!curatorFrameworkOp.checkExists(serverNodePath)) {
return runningIp;
}
List servers = curatorFrameworkOp.getChildren(serverNodePath);
for (String server : servers) {
String sharding = curatorFrameworkOp.getData(JobNodePath.getServerNodePath(jobName, server, "sharding"));
String toFind = "";
if (Strings.isNullOrEmpty(sharding)) {
continue;
}
for (String itemKey : Splitter.on(',').split(sharding)) {
if (item.equals(itemKey)) {
toFind = itemKey;
break;
}
}
if (!Strings.isNullOrEmpty(toFind)) {
runningIp = server;
break;
}
}
return runningIp;
}
@Transactional(rollbackFor = Exception.class)
@Override
public void enableJob(final String namespace, final String jobName) throws SaturnJobConsoleException {
ReuseUtils
.reuse(namespace, jobName, registryCenterService, curatorRepository, new ReuseCallBackWithoutReturn() {
@Override
public void call(CuratorRepository.CuratorFrameworkOp curatorFrameworkOp)
throws SaturnJobConsoleException {
JobConfig4DB jobConfig = currentJobConfigService
.findConfigByNamespaceAndJobName(namespace, jobName);
if (jobConfig == null) {
throw new SaturnJobConsoleHttpException(HttpStatus.NOT_FOUND.value(),
"不能启用该作业(" + jobName + "),因为该作业不存在");
}
if (jobConfig.getEnabled()) {
throw new SaturnJobConsoleHttpException(HttpStatus.CREATED.value(),
"该作业(" + jobName + ")已经处于启用状态");
}
String enabledNodePath = JobNodePath.getConfigNodePath(jobName, "enabled");
long ctime = curatorFrameworkOp.getCtime(enabledNodePath);
long mtime = curatorFrameworkOp.getMtime(enabledNodePath);
checkUpdateStatusToEnableAllowed(ctime, mtime);
jobConfig.setEnabled(Boolean.TRUE);
jobConfig.setLastUpdateTime(new Date());
jobConfig.setLastUpdateBy("");
currentJobConfigService.updateByPrimaryKey(jobConfig);
curatorFrameworkOp.update(enabledNodePath, "true");
}
});
}
@Transactional(rollbackFor = Exception.class)
@Override
public void disableJob(final String namespace, final String jobName) throws SaturnJobConsoleException {
ReuseUtils
.reuse(namespace, jobName, registryCenterService, curatorRepository, new ReuseCallBackWithoutReturn() {
@Override
public void call(CuratorRepository.CuratorFrameworkOp curatorFrameworkOp)
throws SaturnJobConsoleException {
JobConfig4DB jobConfig = currentJobConfigService
.findConfigByNamespaceAndJobName(namespace, jobName);
if (jobConfig == null) {
throw new SaturnJobConsoleHttpException(HttpStatus.NOT_FOUND.value(),
"不能禁用该作业(" + jobName + "),因为该作业不存在");
}
if (!jobConfig.getEnabled()) {
throw new SaturnJobConsoleHttpException(HttpStatus.CREATED.value(),
"该作业(" + jobName + ")已经处于禁用状态");
}
String enabledNodePath = JobNodePath.getConfigNodePath(jobName, "enabled");
long mtime = curatorFrameworkOp.getMtime(enabledNodePath);
checkUpdateStatusToDisableAllowed(mtime);
jobConfig.setEnabled(Boolean.FALSE);
jobConfig.setLastUpdateTime(new Date());
jobConfig.setLastUpdateBy("");
currentJobConfigService.updateByPrimaryKey(jobConfig);
curatorFrameworkOp.update(enabledNodePath, "false");
}
});
}
@Override
public void updateJobCron(final String namespace, final String jobName, final String cron,
final Map customContext) throws SaturnJobConsoleException {
ReuseUtils
.reuse(namespace, jobName, registryCenterService, curatorRepository, new ReuseCallBackWithoutReturn() {
@Override
public void call(CuratorRepository.CuratorFrameworkOp curatorFrameworkOp)
throws SaturnJobConsoleException {
String cronNodePath = JobNodePath.getConfigNodePath(jobName, "cron");
long mtime = curatorFrameworkOp.getMtime(cronNodePath);
checkUpdateConfigAllowed(mtime);
String oldcronStr = curatorFrameworkOp.getData(JobNodePath.getConfigNodePath(jobName, "cron"));
if (!cron.equals(oldcronStr)) {
jobService.updateJobCron(namespace, jobName, cron, customContext, "");
}
}
});
}
private void checkUpdateConfigAllowed(long lastMtime) throws SaturnJobConsoleHttpException {
if (Math.abs(System.currentTimeMillis() - lastMtime) < STATUS_UPDATE_FORBIDDEN_INTERVAL_IN_MILL_SECONDS) {
String errMsg = "The update interval time cannot less than "
+ STATUS_UPDATE_FORBIDDEN_INTERVAL_IN_MILL_SECONDS / 1000 + " seconds";
log.warn(errMsg);
throw new SaturnJobConsoleHttpException(HttpStatus.FORBIDDEN.value(), errMsg);
}
}
@Override
public void runJobAtOnce(final String namespace, final String jobName, final Map triggeredData)
throws SaturnJobConsoleException {
ReuseUtils
.reuse(namespace, jobName, registryCenterService, curatorRepository, new ReuseCallBackWithoutReturn() {
@Override
public void call(CuratorRepository.CuratorFrameworkOp curatorFrameworkOp)
throws SaturnJobConsoleException {
JobStatus js = jobService.getJobStatus(namespace, jobName);
if (!JobStatus.READY.equals(js)) {
throw new SaturnJobConsoleHttpException(HttpStatus.BAD_REQUEST.value(),
String.format(JOB_STATUS_NOT_CORRECT_TEMPATE, JobStatus.READY.name()));
}
List jobServersStatus = jobService.getJobServersStatus(namespace, jobName);
if (CollectionUtils.isEmpty(jobServersStatus)) {
throw new SaturnJobConsoleHttpException(HttpStatus.BAD_REQUEST.value(), NO_EXECUTOR_FOUND);
}
boolean everExecute = false;
for (JobServerStatus jobServerStatus : jobServersStatus) {
if (ServerStatus.ONLINE.equals(jobServerStatus.getServerStatus())) {
everExecute = true;
String executorName = jobServerStatus.getExecutorName();
String path = JobNodePath.getRunOneTimePath(jobName, executorName);
if (curatorFrameworkOp.checkExists(path)) {
curatorFrameworkOp.delete(path);
}
String triggeredDataStr = gson.toJson(triggeredData);
curatorFrameworkOp.create(path, triggeredDataStr);
log.info("runAtOnce namespace:{}, jobName:{}, executorName:{}, triggeredData:{}",
namespace, jobName, executorName, triggeredDataStr);
}
}
if (!everExecute) {
throw new SaturnJobConsoleHttpException(HttpStatus.BAD_REQUEST.value(),
ALL_EXECUTORS_ARE_OFFLINE);
}
}
});
}
@Override
public void stopJobAtOnce(final String namespace, final String jobName) throws SaturnJobConsoleException {
ReuseUtils
.reuse(namespace, jobName, registryCenterService, curatorRepository, new ReuseCallBackWithoutReturn() {
@Override
public void call(CuratorRepository.CuratorFrameworkOp curatorFrameworkOp)
throws SaturnJobConsoleException {
// if job is already STOPPED then return
JobStatus js = jobService.getJobStatus(namespace, jobName);
if (JobStatus.STOPPED.equals(js)) {
log.debug("job is already stopped");
return;
}
// For other Job types where the status is neither STOPPING nor STOPPED, cannot be stopped at
// once
if (JobStatus.READY.equals(js) || JobStatus.RUNNING.equals(js)) {
throw new SaturnJobConsoleHttpException(HttpStatus.BAD_REQUEST.value(),
"job cannot be stopped while its status is READY or RUNNING");
}
List jobServerList = jobService.getJobServerList(namespace, jobName);
if (CollectionUtils.isEmpty(jobServerList)) {
throw new SaturnJobConsoleHttpException(HttpStatus.BAD_REQUEST.value(), NO_EXECUTOR_FOUND);
}
for (String executorName : jobServerList) {
String path = JobNodePath.getStopOneTimePath(jobName, executorName);
if (curatorFrameworkOp.checkExists(path)) {
curatorFrameworkOp.delete(path);
}
curatorFrameworkOp.create(path);
log.info("stopAtOnce namespace:{}, jobName:{}, executorName:{}", namespace, jobName,
executorName);
}
}
});
}
@Override
public void deleteJob(final String namespace, final String jobName) throws SaturnJobConsoleException {
ReuseUtils
.reuse(namespace, jobName, registryCenterService, curatorRepository, new ReuseCallBackWithoutReturn() {
@Override
public void call(CuratorRepository.CuratorFrameworkOp curatorFrameworkOp)
throws SaturnJobConsoleException {
JobStatus js = jobService.getJobStatus(namespace, jobName);
if (!JobStatus.STOPPED.equals(js)) {
throw new SaturnJobConsoleHttpException(HttpStatus.BAD_REQUEST.value(),
String.format(JOB_STATUS_NOT_CORRECT_TEMPATE, JobStatus.STOPPED.name()));
}
jobService.removeJob(namespace, jobName);
log.info("job:{} deletion done", jobName);
}
});
}
@Override
public void raiseAlarm(final String namespace, final String jobName, final String executorName,
final Integer shardItem, final AlarmInfo alarmInfo) throws SaturnJobConsoleException {
ReuseUtils
.reuse(namespace, jobName, registryCenterService, curatorRepository, new ReuseCallBackWithoutReturn() {
@Override
public void call(CuratorRepository.CuratorFrameworkOp curatorFrameworkOp)
throws SaturnJobConsoleException {
try {
// verify executor exist or not
if (!curatorFrameworkOp.checkExists(JobNodePath.getServerNodePath(jobName, executorName))) {
throw new SaturnJobConsoleHttpException(HttpStatus.NOT_FOUND.value(),
String.format("The executor {%s} does not exists.", executorName));
}
reportAlarmService.raise(namespace, jobName, executorName, shardItem, alarmInfo);
} catch (ReportAlarmException e) {
log.warn("ReportAlarmException: {}", e);
throw new SaturnJobConsoleHttpException(HttpStatus.INTERNAL_SERVER_ERROR.value(),
e.getMessage());
}
}
});
}
@Override
public void raiseExecutorRestartAlarm(final String namespace, final String executorName, final AlarmInfo alarmInfo)
throws SaturnJobConsoleException {
ReuseUtils.reuse(namespace, registryCenterService, curatorRepository, new ReuseCallBackWithoutReturn() {
@Override
public void call(CuratorRepository.CuratorFrameworkOp curatorFrameworkOp) throws SaturnJobConsoleException {
try {
String restartTime = obtainRestartTime(alarmInfo);
reportAlarmService.executorRestart(namespace, executorName, restartTime);
} catch (ReportAlarmException e) {
log.warn("ReportAlarmException: {}", e);
throw new SaturnJobConsoleHttpException(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage());
}
}
});
}
private String obtainRestartTime(AlarmInfo alarmInfo) {
String msg = alarmInfo.getMessage();
int idx = msg.indexOf(EXECUTOR_RESTART_TIME_PREFIX);
if (idx > 0) {
return msg.substring(idx + EXECUTOR_RESTART_TIME_PREFIX.length());
}
return "";
}
private void checkUpdateStatusToEnableAllowed(long ctime, long mtime) throws SaturnJobConsoleHttpException {
if (Math.abs(System.currentTimeMillis() - ctime)
< OPERATION_FORBIDDEN_INTERVAL_AFTER_CREATION_IN_MILL_SECONDS) {
String errMsg =
"Cannot enable the job until " + OPERATION_FORBIDDEN_INTERVAL_AFTER_CREATION_IN_MILL_SECONDS / 1000
+ " seconds after job creation!";
log.warn(errMsg);
throw new SaturnJobConsoleHttpException(HttpStatus.FORBIDDEN.value(), errMsg);
}
if (Math.abs(System.currentTimeMillis() - mtime) < STATUS_UPDATE_FORBIDDEN_INTERVAL_IN_MILL_SECONDS) {
String errMsg = "The update interval time cannot less than "
+ STATUS_UPDATE_FORBIDDEN_INTERVAL_IN_MILL_SECONDS / 1000 + " seconds";
log.warn(errMsg);
throw new SaturnJobConsoleHttpException(HttpStatus.FORBIDDEN.value(), errMsg);
}
}
private void checkUpdateStatusToDisableAllowed(long lastMtime) throws SaturnJobConsoleHttpException {
if (Math.abs(System.currentTimeMillis() - lastMtime) < STATUS_UPDATE_FORBIDDEN_INTERVAL_IN_MILL_SECONDS) {
String errMsg = "The update interval time cannot less than "
+ STATUS_UPDATE_FORBIDDEN_INTERVAL_IN_MILL_SECONDS / 1000 + " seconds";
log.warn(errMsg);
throw new SaturnJobConsoleHttpException(HttpStatus.FORBIDDEN.value(), errMsg);
}
}
@Override
public void updateJob(final String namespace, final String jobName, final JobConfig jobConfig)
throws SaturnJobConsoleException {
ReuseUtils
.reuse(namespace, jobName, registryCenterService, curatorRepository, new ReuseCallBackWithoutReturn() {
@Override
public void call(CuratorRepository.CuratorFrameworkOp curatorFrameworkOp)
throws SaturnJobConsoleException {
JobStatus js = jobService.getJobStatus(namespace, jobName);
if (!JobStatus.STOPPED.equals(js)) {
throw new SaturnJobConsoleHttpException(HttpStatus.BAD_REQUEST.value(),
String.format(JOB_STATUS_NOT_CORRECT_TEMPATE, JobStatus.STOPPED.name()));
}
jobService.updateJobConfig(namespace, jobConfig, "");
log.info("job {} update done", jobName);
}
});
}
@Override
public List runDownStream(final String namespace, final String jobName,
final Map triggeredData) throws SaturnJobConsoleException {
return ReuseUtils.reuse(namespace, jobName, registryCenterService, curatorRepository,
new ReuseCallBack>() {
@Override
public List call(CuratorRepository.CuratorFrameworkOp curatorFrameworkOp)
throws SaturnJobConsoleException {
JobConfig4DB jobConfig = currentJobConfigService
.findConfigByNamespaceAndJobName(namespace, jobName);
if (jobConfig == null) {
throw new SaturnJobConsoleHttpException(HttpStatus.NOT_FOUND.value(),
"不能触发该作业(" + jobName + ")的下游,因为该作业不存在");
}
List batchJobResultList = new ArrayList<>();
String downStream = jobConfig.getDownStream();
if (StringUtils.isBlank(downStream)) {
return batchJobResultList;
}
// Maybe should validate downStream, but it seems unnecessary, because it's validated when add/copy/import/update job
String[] split = downStream.split(",");
for (String childName : split) {
String childNameTrim = childName.trim();
if (childNameTrim.isEmpty()) {
continue;
}
BatchJobResult batchJobResult = new BatchJobResult();
batchJobResult.setJobName(childNameTrim);
try {
runJobAtOnce(namespace, childNameTrim, triggeredData);
batchJobResult.setSuccess(true);
} catch (SaturnJobConsoleException e) {
batchJobResult.setSuccess(false);
batchJobResult.setMessage(e.getMessage());
} finally {
batchJobResultList.add(batchJobResult);
}
}
return batchJobResultList;
}
});
}
@Override
public List getJobConfigList(String namespace) throws SaturnJobConsoleException {
return jobService.getUnSystemJobs(namespace);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy