/** * 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.console.controller; import com.google.common.base.Strings; import com.vip.saturn.job.console.domain.*; import com.vip.saturn.job.console.exception.SaturnJobConsoleException; import com.vip.saturn.job.console.service.JobDimensionService; import com.vip.saturn.job.console.service.JobOperationService; import com.vip.saturn.job.console.utils.CronExpression; import com.vip.saturn.job.console.utils.SaturnConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.sql.Time; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; @RestController @RequestMapping("job") public class JobController extends AbstractController { protected static Logger LOGGER = LoggerFactory.getLogger(JobController.class); @Resource private JobDimensionService jobDimensionService; @Resource private JobOperationService jobOperationService; @RequestMapping(value = "jobs", method = RequestMethod.GET) public Collection<JobBriefInfo> getAllJobsBriefInfo(final ModelMap model, HttpServletRequest request) { return jobDimensionService.getAllJobsBriefInfo(null,null); } @RequestMapping(value = "settings", method = RequestMethod.GET) public JobSettings getJobSettings(final String jobName, final Long historyId, final ModelMap model, HttpServletRequest request) throws Exception { model.put("jobName", jobName); model.put("jobStatus", jobDimensionService.getJobStatus(jobName)); model.put("isJobEnabled", jobDimensionService.getJobStatus(jobName)); return jobDimensionService.getJobSettings(jobName, getActivatedConfigInSession(request.getSession())); } @RequestMapping(value = "checkAndForecastCron", method = RequestMethod.POST) public RequestResult checkAndForecastCron(final String timeZone, final String cron, HttpServletRequest request) { RequestResult result = new RequestResult(); if(timeZone == null || timeZone.trim().isEmpty()) { result.setSuccess(false); result.setMessage("timeZone cannot be null or empty"); return result; } if(cron == null || cron.trim().isEmpty()) { result.setSuccess(false); result.setMessage("cron cannot be null or empty"); return result; } String timeZoneTrim = timeZone.trim(); String cronTrim = cron.trim(); if(!SaturnConstants.TIME_ZONE_IDS.contains(timeZoneTrim)) { result.setSuccess(false); result.setMessage("timeZone is not available"); return result; } try { TimeZone tz = TimeZone.getTimeZone(timeZoneTrim); DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); dateFormat.setTimeZone(tz); CronExpression cronExpression = new CronExpression(cronTrim); cronExpression.setTimeZone(tz); Map<String, String> obj = new HashMap<>(); obj.put("timeZone", timeZoneTrim); StringBuilder sb = new StringBuilder(100); Date now = new Date(); for (int i = 0; i < 10; i++) { Date next = cronExpression.getNextValidTimeAfter(now); if (next != null) { sb.append(dateFormat.format(next)).append("<br>"); now = next; } } if (sb.length() == 0) { obj.put("times", "Cron maybe describe the past time, the job will never be executed"); } else { if (sb.toString().split("<br>") != null && sb.toString().split("<br>").length >= 10) { sb.append("......"); } obj.put("times", sb.toString()); } result.setSuccess(true); result.setObj(obj); } catch (ParseException e) { result.setSuccess(false); result.setMessage(e.toString()); return result; } return result; } @RequestMapping(value = "tasksMigrateEnabled", method = RequestMethod.GET) public RequestResult tasksMigrateEnabled(final String jobName, HttpServletRequest request) { RequestResult requestResult = new RequestResult(); try { JobMigrateInfo jobMigrateInfo = jobDimensionService.getJobMigrateInfo(jobName); requestResult.setSuccess(true); requestResult.setObj(jobMigrateInfo); } catch (Exception e) { requestResult.setSuccess(false); requestResult.setMessage(e.getMessage()); } return requestResult; } @RequestMapping(value = "batchTasksMigrateEnabled", method = RequestMethod.GET) public RequestResult batchTasksMigrateEnabled(HttpServletRequest request) { RequestResult requestResult = new RequestResult(); try { JobMigrateInfo jobMigrateInfo = jobDimensionService.getAllJobMigrateInfo(); requestResult.setSuccess(true); requestResult.setObj(jobMigrateInfo); } catch (Exception e) { requestResult.setSuccess(false); requestResult.setMessage(e.getMessage()); } return requestResult; } @RequestMapping(value = "batchMigrateJobNewTask", method = RequestMethod.POST) public RequestResult batchMigrateJobNewTask(final String jobNames, final String newTask, HttpServletRequest request) { RequestResult requestResult = new RequestResult(); try { if (jobNames == null) { throw new SaturnJobConsoleException("The jobNames cannot be null"); } if (newTask == null) { throw new SaturnJobConsoleException("The new task cannot be null"); } if (jobNames.trim().length() == 0) { throw new SaturnJobConsoleException("The jobNames cannot be empty string"); } if (newTask.trim().length() == 0) { throw new SaturnJobConsoleException("The new task cannot be empty string"); } jobDimensionService.batchMigrateJobNewTask(jobNames.trim(), newTask.trim()); requestResult.setSuccess(true); } catch (Exception e) { requestResult.setSuccess(false); requestResult.setMessage(e.getMessage()); } return requestResult; } @RequestMapping(value = "migrateJobNewTask", method = RequestMethod.POST) public RequestResult migrateJobNewTask(final String jobName, final String newTask, HttpServletRequest request) { RequestResult requestResult = new RequestResult(); try { if (jobName == null) { throw new SaturnJobConsoleException("The jobName cannot be null"); } if (newTask == null) { throw new SaturnJobConsoleException("The new task cannot be null"); } if (jobName.trim().length() == 0) { throw new SaturnJobConsoleException("The jobName cannot be empty string"); } if (newTask.trim().length() == 0) { throw new SaturnJobConsoleException("The new task cannot be empty string"); } jobDimensionService.migrateJobNewTask(jobName.trim(), newTask.trim()); requestResult.setSuccess(true); } catch (Exception e) { requestResult.setSuccess(false); requestResult.setMessage(e.getMessage()); } return requestResult; } @RequestMapping(value = "settings", method = RequestMethod.POST) public RequestResult updateJobSettings(final JobSettings jobSettings,HttpServletRequest request) { RequestResult result = new RequestResult(); if (!JobStatus.STOPPED.equals(jobDimensionService.getJobStatus(jobSettings.getJobName()))) { result.setSuccess(false); result.setMessage("The job is not stopped, cannot update it's settings"); return result; } JobBriefInfo.JobType jobType = JobBriefInfo.JobType.getJobType(jobSettings.getJobType()); if(jobType == JobBriefInfo.JobType.JAVA_JOB || jobType == JobBriefInfo.JobType.SHELL_JOB) { String cron = jobSettings.getCron(); if (cron != null && !cron.trim().isEmpty()) { try { CronExpression.validateExpression(cron.trim()); } catch (ParseException e) { result.setSuccess(false); result.setMessage("Cron expression is not valid"); result.setObj(jobDimensionService.getJobSettings(jobSettings.getJobName(), getActivatedConfigInSession(request.getSession()))); return result; } } else { result.setSuccess(false); result.setMessage("The cron cannot be null or empty for cron-job"); result.setObj(jobDimensionService.getJobSettings(jobSettings.getJobName(), getActivatedConfigInSession(request.getSession()))); return result; } } if(jobSettings.getJobMode() != null && jobSettings.getJobMode().startsWith(JobMode.SYSTEM_PREFIX)) { result.setSuccess(false); result.setMessage("The jobMode cannot be start with " + JobMode.SYSTEM_PREFIX); result.setObj(jobDimensionService.getJobSettings(jobSettings.getJobName(), getActivatedConfigInSession(request.getSession()))); return result; } String returnMsg = jobDimensionService.updateJobSettings(jobSettings, getActivatedConfigInSession(request.getSession())); if (Strings.isNullOrEmpty(returnMsg)) { result.setSuccess(true); result.setMessage("update success"); result.setObj(jobSettings); } else { result.setSuccess(false); result.setMessage(returnMsg); result.setObj(jobDimensionService.getJobSettings(jobSettings.getJobName(), getActivatedConfigInSession(request.getSession()))); } return result; } @RequestMapping(value = "servers", method = RequestMethod.GET) public Collection<JobServer> getServers(final JobServer jobServer, HttpServletRequest request) { return jobDimensionService.getServers(jobServer.getJobName()); } @RequestMapping(value = "execution", method = RequestMethod.GET) public Collection<ExecutionInfo> getExecutionInfo(final JobSettings config) { return jobDimensionService.getExecutionInfo(config.getJobName()); } /** * 获取作业分片执行日志信息 * @param config 请求ExecutionInfo对象 * @return ExecutionInfo对象 */ @RequestMapping(value = "logs", method = RequestMethod.GET) public ExecutionInfo getLogInfo(final ExecutionInfo config) { ExecutionInfo info = jobDimensionService.getExecutionJobLog(config.getJobName(), config.getItem()); return info; } /** * 获取所有的executor作为优先候选列表 */ @RequestMapping(value = "getAllExecutors", method = RequestMethod.GET) public String getAllExecutors() { return jobDimensionService.getAllExecutors(null); } @RequestMapping(value = "getJobNextFireTime", method = RequestMethod.GET) public String getJobNextFireTime(String jobName) { Long calculateJobNextTime = jobDimensionService.calculateJobNextTime(jobName); String formatTimeByJobTimeZone = jobDimensionService.formatTimeByJobTimeZone(jobName, calculateJobNextTime); return formatTimeByJobTimeZone; } /** * 获取所有作业的分组列表 */ @RequestMapping(value = "getAllJobGroups", method = RequestMethod.GET) public List<String> getAllJobGroups() { return jobDimensionService.getAllJobGroups(); } }