/**
* Copyright 2016 benjobs
* <p>
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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 org.opencron.server.service;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.opencron.common.job.Opencron;
import org.opencron.server.dao.QueryDao;
import org.opencron.server.domain.Job;
import org.opencron.server.domain.User;
import org.opencron.server.domain.Agent;
import org.opencron.server.job.OpencronTools;
import org.opencron.server.tag.PageBean;
import static org.opencron.common.job.Opencron.*;
import org.opencron.common.utils.CommonUtils;
import org.opencron.server.vo.JobVo;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpSession;
import static org.opencron.common.utils.CommonUtils.notEmpty;
@Service
@Transactional
public class JobService {
@Autowired
private QueryDao queryDao;
@Autowired
private AgentService agentService;
@Autowired
private UserService userService;
@Autowired
private SchedulerService schedulerService;
private Logger logger = LoggerFactory.getLogger(JobService.class);
public Job getJob(Long jobId) {
return queryDao.get(Job.class, jobId);
}
/**
* 获取将要执行的任务
*
* @return
*/
public List<JobVo> getJobVo(ExecType execType, CronType cronType) {
String sql = "SELECT T.*,D.name AS agentName,D.port,D.ip,D.password FROM T_JOB AS T " +
"LEFT JOIN T_AGENT AS D " +
"ON T.agentId = D.agentId " +
"WHERE IFNULL(T.flowNum,0)=0 " +
"AND cronType=? " +
"AND execType = ? " +
"AND T.deleted=0";
List<JobVo> jobs = queryDao.sqlQuery(JobVo.class, sql, cronType.getType(), execType.getStatus());
queryJobMore(jobs);
return jobs;
}
public List<JobVo> getJobVoByAgentId(Agent agent, ExecType execType, CronType cronType) {
String sql = "SELECT T.*,D.name AS agentName,D.port,D.ip,D.password FROM T_JOB AS T " +
"INNER JOIN T_AGENT D " +
"ON T.agentId = D.agentId " +
"WHERE IFNULL(T.flowNum,0)=0 " +
"AND cronType=? " +
"AND execType = ? " +
"AND T.deleted=0 " +
"AND D.agentId=? ";
List<JobVo> jobs = queryDao.sqlQuery(JobVo.class, sql, cronType.getType(), execType.getStatus(), agent.getAgentId());
queryJobMore(jobs);
return jobs;
}
private void queryJobMore(List<JobVo> jobs) {
if (CommonUtils.notEmpty(jobs)) {
for (JobVo job : jobs) {
job.setAgent(agentService.getAgent(job.getAgentId()));
queryChildren(job);
queryJobUser(job);
}
}
}
public List<Job> getJobsByJobType(HttpSession session, JobType jobType) {
String sql = "SELECT * FROM T_JOB WHERE deleted=0 AND jobType=?";
if (JobType.FLOW.equals(jobType)) {
sql += " AND flowNum=0";
}
if (!OpencronTools.isPermission(session)) {
User user = OpencronTools.getUser(session);
sql += " AND userId = " + user.getUserId() + " AND agentId IN (" + user.getAgentIds() + ")";
}
return queryDao.sqlQuery(Job.class, sql, jobType.getCode());
}
public List<JobVo> getCrontabJob() {
logger.info("[opencron] init quartzJob...");
return getJobVo(Opencron.ExecType.AUTO, Opencron.CronType.CRONTAB);
}
public List<Job> getAll() {
List<Job> jobs = OpencronTools.CACHE.get(OpencronTools.CACHED_JOB_ID, List.class);
if (CommonUtils.isEmpty(jobs)) {
flushJob();
}
return OpencronTools.CACHE.get(OpencronTools.CACHED_JOB_ID, List.class);
}
private synchronized void flushJob() {
OpencronTools.CACHE.put(OpencronTools.CACHED_JOB_ID, queryDao.sqlQuery(Job.class, "SELECT * FROM T_JOB WHERE deleted=0"));
}
public PageBean<JobVo> getJobVos(HttpSession session, PageBean pageBean, JobVo job) {
String sql = "SELECT T.*,D.name AS agentName,D.port,D.ip,D.password,U.userName AS operateUname " +
"FROM T_JOB AS T " +
"LEFT JOIN T_AGENT AS D " +
"ON T.agentId = D.agentId " +
"LEFT JOIN T_USER AS U " +
"ON T.userId = U.userId " +
"WHERE IFNULL(flowNum,0)=0 " +
"AND T.deleted=0 ";
if (job != null) {
if (notEmpty(job.getAgentId())) {
sql += " AND T.agentId=" + job.getAgentId();
}
if (notEmpty(job.getCronType())) {
sql += " AND T.cronType=" + job.getCronType();
}
if (notEmpty(job.getJobType())) {
sql += " AND T.jobType=" + job.getJobType();
}
if (notEmpty(job.getExecType())) {
sql += " AND T.execType=" + job.getExecType();
}
if (notEmpty(job.getRedo())) {
sql += " AND T.redo=" + job.getRedo();
}
if (!OpencronTools.isPermission(session)) {
User user = OpencronTools.getUser(session);
sql += " AND T.userId = " + user.getUserId() + " AND T.agentId IN (" + user.getAgentIds() + ")";
}
}
pageBean = queryDao.getPageBySql(pageBean, JobVo.class, sql);
List<JobVo> parentJobs = pageBean.getResult();
for (JobVo parentJob : parentJobs) {
queryChildren(parentJob);
}
pageBean.setResult(parentJobs);
return pageBean;
}
private List<JobVo> queryChildren(JobVo job) {
if (job.getJobType().equals(JobType.FLOW.getCode())) {
String sql = "SELECT T.*,D.name AS agentName,D.port,D.ip,D.password,U.userName AS operateUname FROM T_JOB AS T " +
"LEFT JOIN T_AGENT AS D " +
"ON T.agentId = D.agentId " +
"LEFT JOIN T_USER AS U " +
"ON T.userId = U.userId " +
"WHERE T.deleted=0 " +
"AND T.flowId = ? " +
"AND T.flowNum>0 " +
"ORDER BY T.flowNum ASC";
List<JobVo> childJobs = queryDao.sqlQuery(JobVo.class, sql, job.getFlowId());
if (CommonUtils.notEmpty(childJobs)) {
for (JobVo jobVo : childJobs) {
jobVo.setAgent(agentService.getAgent(jobVo.getAgentId()));
}
}
job.setChildren(childJobs);
return childJobs;
}
return Collections.emptyList();
}
public Job merge(Job job) {
Job saveJob = (Job) queryDao.merge(job);
flushJob();
return saveJob;
}
public JobVo getJobVoById(Long id) {
String sql = "SELECT T.*,D.name AS agentName,D.port,D.ip,D.password,U.username AS operateUname " +
" FROM T_JOB AS T " +
"LEFT JOIN T_AGENT AS D " +
"ON T.agentId = D.agentId " +
"LEFT JOIN T_USER AS U " +
"ON T.userId = U.userId " +
"WHERE T.jobId =?";
JobVo job = queryDao.sqlUniqueQuery(JobVo.class, sql, id);
if (job == null) {
return null;
}
queryJobMore(Arrays.asList(job));
return job;
}
private void queryJobUser(JobVo job) {
if (job != null && job.getUserId() != null) {
User user = userService.getUserById(job.getUserId());
job.setUser(user);
}
}
public List<JobVo> getJobByAgentId(Long agentId) {
String sql = "SELECT T.*,D.name AS agentName,D.port,D.ip,D.password,U.userName AS operateUname FROM T_JOB AS T " +
"LEFT JOIN T_USER AS U " +
"ON T.userId = U.userId " +
"LEFT JOIN T_AGENT D " +
"ON T.agentId = D.agentId " +
"WHERE T.agentId =?";
return queryDao.sqlQuery(JobVo.class, sql, agentId);
}
public boolean existsName(Long jobId, Long agentId, String name) {
String sql = "SELECT COUNT(1) FROM T_JOB WHERE agentId=? AND deleted=0 AND jobName=? ";
if (notEmpty(jobId)) {
sql += " AND jobId != " + jobId + " AND flowId != " + jobId;
}
return (queryDao.getCountBySql(sql, agentId, name)) > 0L;
}
public String checkDelete(Long id) {
Job job = getJob(id);
if (job == null) {
return "error";
}
//该任务是否正在执行中?
String sql = "SELECT COUNT(1) FROM T_RECORD WHERE jobId = ? AND `status`=?";
Long count = queryDao.getCountBySql(sql, id, RunStatus.RUNNING.getStatus());
if (count > 0) {
return "false";
}
//流程任务则检查任务流是否在运行中...
if (job.getJobType() == JobType.FLOW.getCode()) {
sql = "SELECT COUNT(1) FROM T_RECORD AS R INNER JOIN (" +
" SELECT J.jobId FROM T_JOB AS J INNER JOIN T_JOB AS F" +
" ON J.flowId = F.flowId" +
" WHERE f.jobId = ?" +
" ) AS J" +
" on R.jobId = J.jobId" +
" and R.status=?";
count = queryDao.getCountBySql(sql, id, RunStatus.RUNNING.getStatus());
if (count > 0) {
return "false";
}
}
return "true";
}
@Transactional(rollbackFor = Exception.class)
public void delete(Long jobId) throws SchedulerException {
Job job = getJob(jobId);
if (job != null) {
//单一任务,直接执行删除
String sql = "UPDATE T_JOB SET deleted=1 WHERE ";
if (job.getJobType().equals(JobType.SINGLETON.getCode())) {
sql += " jobId=" + jobId;
}
if (job.getJobType().equals(JobType.FLOW.getCode())) {
if (job.getFlowNum() == 0) {
//顶层流程任务,则删除一组
sql += " flowId=" + job.getFlowId();
} else {
//其中一个子流程任务,则删除单个
sql += " jobId=" + jobId;
}
}
queryDao.createSQLQuery(sql).executeUpdate();
schedulerService.syncJobTigger(jobId, null);
flushJob();
}
}
public void saveFlowJob(Job job, List<Job> children) throws SchedulerException {
job.setLastChild(false);
job.setUpdateTime(new Date());
job.setFlowNum(0);//顶层sort是0
/**
* 保存最顶层的父级任务
*/
if (job.getJobId() != null) {
merge(job);
/**
* 当前作业已有的子作业
*/
JobVo jobVo = new JobVo();
jobVo.setJobType(JobType.FLOW.getCode());
jobVo.setFlowId(job.getFlowId());
/**
* 取差集..
*/
List<JobVo> hasChildren = queryChildren(jobVo);
//数据库里已经存在的子集合..
top:
for (JobVo hasChild : hasChildren) {
//当前页面提交过来的子集合...
for (Job child : children) {
if (child.getJobId() != null && child.getJobId().equals(hasChild.getJobId())) {
continue top;
}
}
/**
* 已有的子作业被删除的,则做删除操作...
*/
delete(hasChild.getJobId());
}
} else {
Job job1 = merge(job);
job1.setFlowId(job1.getJobId());//flowId
merge(job1);
job.setJobId(job1.getJobId());
}
for (int i = 0; i < children.size(); i++) {
Job child = children.get(i);
/**
* 子作业的流程编号都为顶层父任务的jobId
*/
child.setFlowId(job.getJobId());
child.setUserId(job.getUserId());
child.setUpdateTime(new Date());
child.setJobType(JobType.FLOW.getCode());
child.setFlowNum(i + 1);
child.setLastChild(child.getFlowNum() == children.size());
child.setWarning(job.getWarning());
child.setMobiles(job.getMobiles());
child.setEmailAddress(job.getEmailAddress());
merge(child);
}
}
public boolean checkJobOwner(HttpSession session, Long userId) {
return OpencronTools.isPermission(session) || userId.equals(OpencronTools.getUserId(session));
}
}