Browse Source
* [Improvement-3369][api] Introduce resources, scheduler and taskinstance service interface for clear codepull/3/MERGE
16 changed files with 2250 additions and 1832 deletions
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,600 @@
|
||||
/* |
||||
* 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 |
||||
* |
||||
* 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 org.apache.dolphinscheduler.api.service.impl; |
||||
|
||||
import org.apache.dolphinscheduler.api.dto.ScheduleParam; |
||||
import org.apache.dolphinscheduler.api.enums.Status; |
||||
import org.apache.dolphinscheduler.api.exceptions.ServiceException; |
||||
import org.apache.dolphinscheduler.api.service.BaseService; |
||||
import org.apache.dolphinscheduler.api.service.ExecutorService; |
||||
import org.apache.dolphinscheduler.api.service.MonitorService; |
||||
import org.apache.dolphinscheduler.api.service.ProjectService; |
||||
import org.apache.dolphinscheduler.api.service.SchedulerService; |
||||
import org.apache.dolphinscheduler.api.utils.PageInfo; |
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.enums.FailureStrategy; |
||||
import org.apache.dolphinscheduler.common.enums.Priority; |
||||
import org.apache.dolphinscheduler.common.enums.ReleaseState; |
||||
import org.apache.dolphinscheduler.common.enums.UserType; |
||||
import org.apache.dolphinscheduler.common.enums.WarningType; |
||||
import org.apache.dolphinscheduler.common.model.Server; |
||||
import org.apache.dolphinscheduler.common.utils.DateUtils; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.common.utils.StringUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.ProcessDefinition; |
||||
import org.apache.dolphinscheduler.dao.entity.Project; |
||||
import org.apache.dolphinscheduler.dao.entity.Schedule; |
||||
import org.apache.dolphinscheduler.dao.entity.User; |
||||
import org.apache.dolphinscheduler.dao.mapper.ProcessDefinitionMapper; |
||||
import org.apache.dolphinscheduler.dao.mapper.ProjectMapper; |
||||
import org.apache.dolphinscheduler.dao.mapper.ScheduleMapper; |
||||
import org.apache.dolphinscheduler.service.process.ProcessService; |
||||
import org.apache.dolphinscheduler.service.quartz.ProcessScheduleJob; |
||||
import org.apache.dolphinscheduler.service.quartz.QuartzExecutors; |
||||
import org.apache.dolphinscheduler.service.quartz.cron.CronUtils; |
||||
|
||||
import java.text.ParseException; |
||||
import java.util.ArrayList; |
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import org.quartz.CronExpression; |
||||
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 com.baomidou.mybatisplus.core.metadata.IPage; |
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
||||
|
||||
/** |
||||
* scheduler service impl |
||||
*/ |
||||
@Service |
||||
public class SchedulerServiceImpl extends BaseService implements SchedulerService { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SchedulerServiceImpl.class); |
||||
|
||||
@Autowired |
||||
private ProjectService projectService; |
||||
|
||||
@Autowired |
||||
private ExecutorService executorService; |
||||
|
||||
@Autowired |
||||
private MonitorService monitorService; |
||||
|
||||
@Autowired |
||||
private ProcessService processService; |
||||
|
||||
@Autowired |
||||
private ScheduleMapper scheduleMapper; |
||||
|
||||
@Autowired |
||||
private ProjectMapper projectMapper; |
||||
|
||||
@Autowired |
||||
private ProcessDefinitionMapper processDefinitionMapper; |
||||
|
||||
/** |
||||
* save schedule |
||||
* |
||||
* @param loginUser login user |
||||
* @param projectName project name |
||||
* @param processDefineId process definition id |
||||
* @param schedule scheduler |
||||
* @param warningType warning type |
||||
* @param warningGroupId warning group id |
||||
* @param failureStrategy failure strategy |
||||
* @param processInstancePriority process instance priority |
||||
* @param workerGroup worker group |
||||
* @return create result code |
||||
*/ |
||||
@Transactional(rollbackFor = RuntimeException.class) |
||||
public Map<String, Object> insertSchedule(User loginUser, String projectName, |
||||
Integer processDefineId, |
||||
String schedule, |
||||
WarningType warningType, |
||||
int warningGroupId, |
||||
FailureStrategy failureStrategy, |
||||
Priority processInstancePriority, |
||||
String workerGroup) { |
||||
|
||||
Map<String, Object> result = new HashMap<>(); |
||||
|
||||
Project project = projectMapper.queryByName(projectName); |
||||
|
||||
// check project auth
|
||||
boolean hasProjectAndPerm = projectService.hasProjectAndPerm(loginUser, project, result); |
||||
if (!hasProjectAndPerm) { |
||||
return result; |
||||
} |
||||
|
||||
// check work flow define release state
|
||||
ProcessDefinition processDefinition = processService.findProcessDefineById(processDefineId); |
||||
result = executorService.checkProcessDefinitionValid(processDefinition, processDefineId); |
||||
if (result.get(Constants.STATUS) != Status.SUCCESS) { |
||||
return result; |
||||
} |
||||
|
||||
Schedule scheduleObj = new Schedule(); |
||||
Date now = new Date(); |
||||
|
||||
scheduleObj.setProjectName(projectName); |
||||
scheduleObj.setProcessDefinitionId(processDefinition.getId()); |
||||
scheduleObj.setProcessDefinitionName(processDefinition.getName()); |
||||
|
||||
ScheduleParam scheduleParam = JSONUtils.parseObject(schedule, ScheduleParam.class); |
||||
if (DateUtils.differSec(scheduleParam.getStartTime(), scheduleParam.getEndTime()) == 0) { |
||||
logger.warn("The start time must not be the same as the end"); |
||||
putMsg(result, Status.SCHEDULE_START_TIME_END_TIME_SAME); |
||||
return result; |
||||
} |
||||
scheduleObj.setStartTime(scheduleParam.getStartTime()); |
||||
scheduleObj.setEndTime(scheduleParam.getEndTime()); |
||||
if (!org.quartz.CronExpression.isValidExpression(scheduleParam.getCrontab())) { |
||||
logger.error("{} verify failure", scheduleParam.getCrontab()); |
||||
|
||||
putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, scheduleParam.getCrontab()); |
||||
return result; |
||||
} |
||||
scheduleObj.setCrontab(scheduleParam.getCrontab()); |
||||
scheduleObj.setWarningType(warningType); |
||||
scheduleObj.setWarningGroupId(warningGroupId); |
||||
scheduleObj.setFailureStrategy(failureStrategy); |
||||
scheduleObj.setCreateTime(now); |
||||
scheduleObj.setUpdateTime(now); |
||||
scheduleObj.setUserId(loginUser.getId()); |
||||
scheduleObj.setUserName(loginUser.getUserName()); |
||||
scheduleObj.setReleaseState(ReleaseState.OFFLINE); |
||||
scheduleObj.setProcessInstancePriority(processInstancePriority); |
||||
scheduleObj.setWorkerGroup(workerGroup); |
||||
scheduleMapper.insert(scheduleObj); |
||||
|
||||
/** |
||||
* updateProcessInstance receivers and cc by process definition id |
||||
*/ |
||||
processDefinition.setWarningGroupId(warningGroupId); |
||||
processDefinitionMapper.updateById(processDefinition); |
||||
|
||||
// return scheduler object with ID
|
||||
result.put(Constants.DATA_LIST, scheduleMapper.selectById(scheduleObj.getId())); |
||||
putMsg(result, Status.SUCCESS); |
||||
|
||||
result.put("scheduleId", scheduleObj.getId()); |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* updateProcessInstance schedule |
||||
* |
||||
* @param loginUser login user |
||||
* @param projectName project name |
||||
* @param id scheduler id |
||||
* @param scheduleExpression scheduler |
||||
* @param warningType warning type |
||||
* @param warningGroupId warning group id |
||||
* @param failureStrategy failure strategy |
||||
* @param workerGroup worker group |
||||
* @param processInstancePriority process instance priority |
||||
* @param scheduleStatus schedule status |
||||
* @return update result code |
||||
*/ |
||||
@Transactional(rollbackFor = RuntimeException.class) |
||||
public Map<String, Object> updateSchedule(User loginUser, |
||||
String projectName, |
||||
Integer id, |
||||
String scheduleExpression, |
||||
WarningType warningType, |
||||
int warningGroupId, |
||||
FailureStrategy failureStrategy, |
||||
ReleaseState scheduleStatus, |
||||
Priority processInstancePriority, |
||||
String workerGroup) { |
||||
Map<String, Object> result = new HashMap<>(); |
||||
|
||||
Project project = projectMapper.queryByName(projectName); |
||||
|
||||
// check project auth
|
||||
boolean hasProjectAndPerm = projectService.hasProjectAndPerm(loginUser, project, result); |
||||
if (!hasProjectAndPerm) { |
||||
return result; |
||||
} |
||||
|
||||
// check schedule exists
|
||||
Schedule schedule = scheduleMapper.selectById(id); |
||||
|
||||
if (schedule == null) { |
||||
putMsg(result, Status.SCHEDULE_CRON_NOT_EXISTS, id); |
||||
return result; |
||||
} |
||||
|
||||
ProcessDefinition processDefinition = processService.findProcessDefineById(schedule.getProcessDefinitionId()); |
||||
if (processDefinition == null) { |
||||
putMsg(result, Status.PROCESS_DEFINE_NOT_EXIST, schedule.getProcessDefinitionId()); |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* scheduling on-line status forbid modification |
||||
*/ |
||||
if (checkValid(result, schedule.getReleaseState() == ReleaseState.ONLINE, Status.SCHEDULE_CRON_ONLINE_FORBID_UPDATE)) { |
||||
return result; |
||||
} |
||||
|
||||
Date now = new Date(); |
||||
|
||||
// updateProcessInstance param
|
||||
if (StringUtils.isNotEmpty(scheduleExpression)) { |
||||
ScheduleParam scheduleParam = JSONUtils.parseObject(scheduleExpression, ScheduleParam.class); |
||||
if (DateUtils.differSec(scheduleParam.getStartTime(), scheduleParam.getEndTime()) == 0) { |
||||
logger.warn("The start time must not be the same as the end"); |
||||
putMsg(result, Status.SCHEDULE_START_TIME_END_TIME_SAME); |
||||
return result; |
||||
} |
||||
schedule.setStartTime(scheduleParam.getStartTime()); |
||||
schedule.setEndTime(scheduleParam.getEndTime()); |
||||
if (!org.quartz.CronExpression.isValidExpression(scheduleParam.getCrontab())) { |
||||
putMsg(result, Status.SCHEDULE_CRON_CHECK_FAILED, scheduleParam.getCrontab()); |
||||
return result; |
||||
} |
||||
schedule.setCrontab(scheduleParam.getCrontab()); |
||||
} |
||||
|
||||
if (warningType != null) { |
||||
schedule.setWarningType(warningType); |
||||
} |
||||
|
||||
schedule.setWarningGroupId(warningGroupId); |
||||
|
||||
if (failureStrategy != null) { |
||||
schedule.setFailureStrategy(failureStrategy); |
||||
} |
||||
|
||||
if (scheduleStatus != null) { |
||||
schedule.setReleaseState(scheduleStatus); |
||||
} |
||||
schedule.setWorkerGroup(workerGroup); |
||||
schedule.setUpdateTime(now); |
||||
schedule.setProcessInstancePriority(processInstancePriority); |
||||
scheduleMapper.updateById(schedule); |
||||
|
||||
/** |
||||
* updateProcessInstance recipients and cc by process definition ID |
||||
*/ |
||||
processDefinition.setWarningGroupId(warningGroupId); |
||||
|
||||
processDefinitionMapper.updateById(processDefinition); |
||||
|
||||
putMsg(result, Status.SUCCESS); |
||||
return result; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* set schedule online or offline |
||||
* |
||||
* @param loginUser login user |
||||
* @param projectName project name |
||||
* @param id scheduler id |
||||
* @param scheduleStatus schedule status |
||||
* @return publish result code |
||||
*/ |
||||
@Transactional(rollbackFor = RuntimeException.class) |
||||
public Map<String, Object> setScheduleState(User loginUser, |
||||
String projectName, |
||||
Integer id, |
||||
ReleaseState scheduleStatus) { |
||||
Map<String, Object> result = new HashMap<>(); |
||||
|
||||
Project project = projectMapper.queryByName(projectName); |
||||
// check project auth
|
||||
boolean hasProjectAndPerm = projectService.hasProjectAndPerm(loginUser, project, result); |
||||
if (!hasProjectAndPerm) { |
||||
return result; |
||||
} |
||||
|
||||
// check schedule exists
|
||||
Schedule scheduleObj = scheduleMapper.selectById(id); |
||||
|
||||
if (scheduleObj == null) { |
||||
putMsg(result, Status.SCHEDULE_CRON_NOT_EXISTS, id); |
||||
return result; |
||||
} |
||||
// check schedule release state
|
||||
if (scheduleObj.getReleaseState() == scheduleStatus) { |
||||
logger.info("schedule release is already {},needn't to change schedule id: {} from {} to {}", |
||||
scheduleObj.getReleaseState(), scheduleObj.getId(), scheduleObj.getReleaseState(), scheduleStatus); |
||||
putMsg(result, Status.SCHEDULE_CRON_REALEASE_NEED_NOT_CHANGE, scheduleStatus); |
||||
return result; |
||||
} |
||||
ProcessDefinition processDefinition = processService.findProcessDefineById(scheduleObj.getProcessDefinitionId()); |
||||
if (processDefinition == null) { |
||||
putMsg(result, Status.PROCESS_DEFINE_NOT_EXIST, scheduleObj.getProcessDefinitionId()); |
||||
return result; |
||||
} |
||||
|
||||
if (scheduleStatus == ReleaseState.ONLINE) { |
||||
// check process definition release state
|
||||
if (processDefinition.getReleaseState() != ReleaseState.ONLINE) { |
||||
logger.info("not release process definition id: {} , name : {}", |
||||
processDefinition.getId(), processDefinition.getName()); |
||||
putMsg(result, Status.PROCESS_DEFINE_NOT_RELEASE, processDefinition.getName()); |
||||
return result; |
||||
} |
||||
// check sub process definition release state
|
||||
List<Integer> subProcessDefineIds = new ArrayList<>(); |
||||
processService.recurseFindSubProcessId(scheduleObj.getProcessDefinitionId(), subProcessDefineIds); |
||||
Integer[] idArray = subProcessDefineIds.toArray(new Integer[subProcessDefineIds.size()]); |
||||
if (!subProcessDefineIds.isEmpty()) { |
||||
List<ProcessDefinition> subProcessDefinitionList = |
||||
processDefinitionMapper.queryDefinitionListByIdList(idArray); |
||||
if (subProcessDefinitionList != null && !subProcessDefinitionList.isEmpty()) { |
||||
for (ProcessDefinition subProcessDefinition : subProcessDefinitionList) { |
||||
/** |
||||
* if there is no online process, exit directly |
||||
*/ |
||||
if (subProcessDefinition.getReleaseState() != ReleaseState.ONLINE) { |
||||
logger.info("not release process definition id: {} , name : {}", |
||||
subProcessDefinition.getId(), subProcessDefinition.getName()); |
||||
putMsg(result, Status.PROCESS_DEFINE_NOT_RELEASE, subProcessDefinition.getId()); |
||||
return result; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
// check master server exists
|
||||
List<Server> masterServers = monitorService.getServerListFromZK(true); |
||||
|
||||
if (masterServers.isEmpty()) { |
||||
putMsg(result, Status.MASTER_NOT_EXISTS); |
||||
return result; |
||||
} |
||||
|
||||
// set status
|
||||
scheduleObj.setReleaseState(scheduleStatus); |
||||
|
||||
scheduleMapper.updateById(scheduleObj); |
||||
|
||||
try { |
||||
switch (scheduleStatus) { |
||||
case ONLINE: |
||||
logger.info("Call master client set schedule online, project id: {}, flow id: {},host: {}", project.getId(), processDefinition.getId(), masterServers); |
||||
setSchedule(project.getId(), scheduleObj); |
||||
break; |
||||
case OFFLINE: |
||||
logger.info("Call master client set schedule offline, project id: {}, flow id: {},host: {}", project.getId(), processDefinition.getId(), masterServers); |
||||
deleteSchedule(project.getId(), id); |
||||
break; |
||||
default: |
||||
putMsg(result, Status.SCHEDULE_STATUS_UNKNOWN, scheduleStatus.toString()); |
||||
return result; |
||||
} |
||||
} catch (Exception e) { |
||||
result.put(Constants.MSG, scheduleStatus == ReleaseState.ONLINE ? "set online failure" : "set offline failure"); |
||||
throw new ServiceException(result.get(Constants.MSG).toString()); |
||||
} |
||||
|
||||
putMsg(result, Status.SUCCESS); |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* query schedule |
||||
* |
||||
* @param loginUser login user |
||||
* @param projectName project name |
||||
* @param processDefineId process definition id |
||||
* @param pageNo page number |
||||
* @param pageSize page size |
||||
* @param searchVal search value |
||||
* @return schedule list page |
||||
*/ |
||||
public Map<String, Object> querySchedule(User loginUser, String projectName, Integer processDefineId, String searchVal, Integer pageNo, Integer pageSize) { |
||||
|
||||
HashMap<String, Object> result = new HashMap<>(); |
||||
|
||||
Project project = projectMapper.queryByName(projectName); |
||||
|
||||
// check project auth
|
||||
boolean hasProjectAndPerm = projectService.hasProjectAndPerm(loginUser, project, result); |
||||
if (!hasProjectAndPerm) { |
||||
return result; |
||||
} |
||||
|
||||
ProcessDefinition processDefinition = processService.findProcessDefineById(processDefineId); |
||||
if (processDefinition == null) { |
||||
putMsg(result, Status.PROCESS_DEFINE_NOT_EXIST, processDefineId); |
||||
return result; |
||||
} |
||||
Page<Schedule> page = new Page<>(pageNo, pageSize); |
||||
IPage<Schedule> scheduleIPage = scheduleMapper.queryByProcessDefineIdPaging( |
||||
page, processDefineId, searchVal |
||||
); |
||||
|
||||
PageInfo<Schedule> pageInfo = new PageInfo<>(pageNo, pageSize); |
||||
pageInfo.setTotalCount((int) scheduleIPage.getTotal()); |
||||
pageInfo.setLists(scheduleIPage.getRecords()); |
||||
result.put(Constants.DATA_LIST, pageInfo); |
||||
putMsg(result, Status.SUCCESS); |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* query schedule list |
||||
* |
||||
* @param loginUser login user |
||||
* @param projectName project name |
||||
* @return schedule list |
||||
*/ |
||||
public Map<String, Object> queryScheduleList(User loginUser, String projectName) { |
||||
Map<String, Object> result = new HashMap<>(); |
||||
Project project = projectMapper.queryByName(projectName); |
||||
|
||||
// check project auth
|
||||
boolean hasProjectAndPerm = projectService.hasProjectAndPerm(loginUser, project, result); |
||||
if (!hasProjectAndPerm) { |
||||
return result; |
||||
} |
||||
|
||||
List<Schedule> schedules = scheduleMapper.querySchedulerListByProjectName(projectName); |
||||
|
||||
result.put(Constants.DATA_LIST, schedules); |
||||
putMsg(result, Status.SUCCESS); |
||||
|
||||
return result; |
||||
} |
||||
|
||||
public void setSchedule(int projectId, Schedule schedule) { |
||||
int scheduleId = schedule.getId(); |
||||
logger.info("set schedule, project id: {}, scheduleId: {}", projectId, scheduleId); |
||||
|
||||
Date startDate = schedule.getStartTime(); |
||||
Date endDate = schedule.getEndTime(); |
||||
|
||||
String jobName = QuartzExecutors.buildJobName(scheduleId); |
||||
String jobGroupName = QuartzExecutors.buildJobGroupName(projectId); |
||||
|
||||
Map<String, Object> dataMap = QuartzExecutors.buildDataMap(projectId, scheduleId, schedule); |
||||
|
||||
QuartzExecutors.getInstance().addJob(ProcessScheduleJob.class, jobName, jobGroupName, startDate, endDate, |
||||
schedule.getCrontab(), dataMap); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* delete schedule |
||||
* |
||||
* @param projectId project id |
||||
* @param scheduleId schedule id |
||||
* @throws RuntimeException runtime exception |
||||
*/ |
||||
public void deleteSchedule(int projectId, int scheduleId) { |
||||
logger.info("delete schedules of project id:{}, schedule id:{}", projectId, scheduleId); |
||||
|
||||
String jobName = QuartzExecutors.buildJobName(scheduleId); |
||||
String jobGroupName = QuartzExecutors.buildJobGroupName(projectId); |
||||
|
||||
if (!QuartzExecutors.getInstance().deleteJob(jobName, jobGroupName)) { |
||||
logger.warn("set offline failure:projectId:{},scheduleId:{}", projectId, scheduleId); |
||||
throw new ServiceException("set offline failure"); |
||||
} |
||||
|
||||
} |
||||
|
||||
/** |
||||
* check valid |
||||
* |
||||
* @param result result |
||||
* @param bool bool |
||||
* @param status status |
||||
* @return check result code |
||||
*/ |
||||
private boolean checkValid(Map<String, Object> result, boolean bool, Status status) { |
||||
// timeout is valid
|
||||
if (bool) { |
||||
putMsg(result, status); |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* delete schedule by id |
||||
* |
||||
* @param loginUser login user |
||||
* @param projectName project name |
||||
* @param scheduleId scheule id |
||||
* @return delete result code |
||||
*/ |
||||
public Map<String, Object> deleteScheduleById(User loginUser, String projectName, Integer scheduleId) { |
||||
|
||||
Map<String, Object> result = new HashMap<>(); |
||||
Project project = projectMapper.queryByName(projectName); |
||||
|
||||
Map<String, Object> checkResult = projectService.checkProjectAndAuth(loginUser, project, projectName); |
||||
Status resultEnum = (Status) checkResult.get(Constants.STATUS); |
||||
if (resultEnum != Status.SUCCESS) { |
||||
return checkResult; |
||||
} |
||||
|
||||
Schedule schedule = scheduleMapper.selectById(scheduleId); |
||||
|
||||
if (schedule == null) { |
||||
putMsg(result, Status.SCHEDULE_CRON_NOT_EXISTS, scheduleId); |
||||
return result; |
||||
} |
||||
|
||||
// Determine if the login user is the owner of the schedule
|
||||
if (loginUser.getId() != schedule.getUserId() |
||||
&& loginUser.getUserType() != UserType.ADMIN_USER) { |
||||
putMsg(result, Status.USER_NO_OPERATION_PERM); |
||||
return result; |
||||
} |
||||
|
||||
// check schedule is already online
|
||||
if (schedule.getReleaseState() == ReleaseState.ONLINE) { |
||||
putMsg(result, Status.SCHEDULE_CRON_STATE_ONLINE, schedule.getId()); |
||||
return result; |
||||
} |
||||
|
||||
int delete = scheduleMapper.deleteById(scheduleId); |
||||
|
||||
if (delete > 0) { |
||||
putMsg(result, Status.SUCCESS); |
||||
} else { |
||||
putMsg(result, Status.DELETE_SCHEDULE_CRON_BY_ID_ERROR); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* preview schedule |
||||
* |
||||
* @param loginUser login user |
||||
* @param projectName project name |
||||
* @param schedule schedule expression |
||||
* @return the next five fire time |
||||
*/ |
||||
public Map<String, Object> previewSchedule(User loginUser, String projectName, String schedule) { |
||||
Map<String, Object> result = new HashMap<>(); |
||||
CronExpression cronExpression; |
||||
ScheduleParam scheduleParam = JSONUtils.parseObject(schedule, ScheduleParam.class); |
||||
Date now = new Date(); |
||||
|
||||
Date startTime = now.after(scheduleParam.getStartTime()) ? now : scheduleParam.getStartTime(); |
||||
Date endTime = scheduleParam.getEndTime(); |
||||
try { |
||||
cronExpression = CronUtils.parse2CronExpression(scheduleParam.getCrontab()); |
||||
} catch (ParseException e) { |
||||
logger.error(e.getMessage(), e); |
||||
putMsg(result, Status.PARSE_TO_CRON_EXPRESSION_ERROR); |
||||
return result; |
||||
} |
||||
List<Date> selfFireDateList = CronUtils.getSelfFireDateList(startTime, endTime, cronExpression, Constants.PREVIEW_SCHEDULE_EXECUTE_COUNT); |
||||
result.put(Constants.DATA_LIST, selfFireDateList.stream().map(DateUtils::dateToString)); |
||||
putMsg(result, Status.SUCCESS); |
||||
return result; |
||||
} |
||||
} |
@ -0,0 +1,208 @@
|
||||
/* |
||||
* 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 |
||||
* |
||||
* 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 org.apache.dolphinscheduler.api.service.impl; |
||||
|
||||
import org.apache.dolphinscheduler.api.enums.Status; |
||||
import org.apache.dolphinscheduler.api.service.BaseService; |
||||
import org.apache.dolphinscheduler.api.service.ProcessInstanceService; |
||||
import org.apache.dolphinscheduler.api.service.ProjectService; |
||||
import org.apache.dolphinscheduler.api.service.TaskInstanceService; |
||||
import org.apache.dolphinscheduler.api.service.UsersService; |
||||
import org.apache.dolphinscheduler.api.utils.PageInfo; |
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.enums.ExecutionStatus; |
||||
import org.apache.dolphinscheduler.common.utils.CollectionUtils; |
||||
import org.apache.dolphinscheduler.common.utils.DateUtils; |
||||
import org.apache.dolphinscheduler.common.utils.StringUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.Project; |
||||
import org.apache.dolphinscheduler.dao.entity.TaskInstance; |
||||
import org.apache.dolphinscheduler.dao.entity.User; |
||||
import org.apache.dolphinscheduler.dao.mapper.ProjectMapper; |
||||
import org.apache.dolphinscheduler.dao.mapper.TaskInstanceMapper; |
||||
import org.apache.dolphinscheduler.service.process.ProcessService; |
||||
|
||||
import java.text.MessageFormat; |
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.HashSet; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage; |
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
||||
|
||||
/** |
||||
* task instance service impl |
||||
*/ |
||||
@Service |
||||
public class TaskInstanceServiceImpl extends BaseService implements TaskInstanceService { |
||||
|
||||
@Autowired |
||||
ProjectMapper projectMapper; |
||||
|
||||
@Autowired |
||||
ProjectService projectService; |
||||
|
||||
@Autowired |
||||
ProcessService processService; |
||||
|
||||
@Autowired |
||||
TaskInstanceMapper taskInstanceMapper; |
||||
|
||||
@Autowired |
||||
ProcessInstanceService processInstanceService; |
||||
|
||||
@Autowired |
||||
UsersService usersService; |
||||
|
||||
/** |
||||
* query task list by project, process instance, task name, task start time, task end time, task status, keyword paging |
||||
* |
||||
* @param loginUser login user |
||||
* @param projectName project name |
||||
* @param processInstanceId process instance id |
||||
* @param searchVal search value |
||||
* @param taskName task name |
||||
* @param stateType state type |
||||
* @param host host |
||||
* @param startDate start time |
||||
* @param endDate end time |
||||
* @param pageNo page number |
||||
* @param pageSize page size |
||||
* @return task list page |
||||
*/ |
||||
public Map<String, Object> queryTaskListPaging(User loginUser, String projectName, |
||||
Integer processInstanceId, String processInstanceName, String taskName, String executorName, String startDate, |
||||
String endDate, String searchVal, ExecutionStatus stateType, String host, |
||||
Integer pageNo, Integer pageSize) { |
||||
Map<String, Object> result = new HashMap<>(); |
||||
Project project = projectMapper.queryByName(projectName); |
||||
|
||||
Map<String, Object> checkResult = projectService.checkProjectAndAuth(loginUser, project, projectName); |
||||
Status status = (Status) checkResult.get(Constants.STATUS); |
||||
if (status != Status.SUCCESS) { |
||||
return checkResult; |
||||
} |
||||
|
||||
int[] statusArray = null; |
||||
if (stateType != null) { |
||||
statusArray = new int[]{stateType.ordinal()}; |
||||
} |
||||
|
||||
Date start = null; |
||||
Date end = null; |
||||
if (StringUtils.isNotEmpty(startDate)) { |
||||
start = DateUtils.getScheduleDate(startDate); |
||||
if (start == null) { |
||||
return generateInvalidParamRes(result, "startDate"); |
||||
} |
||||
} |
||||
if (StringUtils.isNotEmpty(endDate)) { |
||||
end = DateUtils.getScheduleDate(endDate); |
||||
if (end == null) { |
||||
return generateInvalidParamRes(result, "endDate"); |
||||
} |
||||
} |
||||
|
||||
Page<TaskInstance> page = new Page<>(pageNo, pageSize); |
||||
PageInfo<Map<String, Object>> pageInfo = new PageInfo<>(pageNo, pageSize); |
||||
int executorId = usersService.getUserIdByName(executorName); |
||||
|
||||
IPage<TaskInstance> taskInstanceIPage = taskInstanceMapper.queryTaskInstanceListPaging( |
||||
page, project.getId(), processInstanceId, processInstanceName, searchVal, taskName, executorId, statusArray, host, start, end |
||||
); |
||||
Set<String> exclusionSet = new HashSet<>(); |
||||
exclusionSet.add(Constants.CLASS); |
||||
exclusionSet.add("taskJson"); |
||||
List<TaskInstance> taskInstanceList = taskInstanceIPage.getRecords(); |
||||
|
||||
for (TaskInstance taskInstance : taskInstanceList) { |
||||
taskInstance.setDuration(DateUtils.format2Duration(taskInstance.getStartTime(), taskInstance.getEndTime())); |
||||
User executor = usersService.queryUser(taskInstance.getExecutorId()); |
||||
if (null != executor) { |
||||
taskInstance.setExecutorName(executor.getUserName()); |
||||
} |
||||
} |
||||
pageInfo.setTotalCount((int) taskInstanceIPage.getTotal()); |
||||
pageInfo.setLists(CollectionUtils.getListByExclusion(taskInstanceIPage.getRecords(), exclusionSet)); |
||||
result.put(Constants.DATA_LIST, pageInfo); |
||||
putMsg(result, Status.SUCCESS); |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* change one task instance's state from failure to forced success |
||||
* |
||||
* @param loginUser login user |
||||
* @param projectName project name |
||||
* @param taskInstanceId task instance id |
||||
* @return the result code and msg |
||||
*/ |
||||
public Map<String, Object> forceTaskSuccess(User loginUser, String projectName, Integer taskInstanceId) { |
||||
Map<String, Object> result = new HashMap<>(); |
||||
Project project = projectMapper.queryByName(projectName); |
||||
|
||||
// check user auth
|
||||
Map<String, Object> checkResult = projectService.checkProjectAndAuth(loginUser, project, projectName); |
||||
Status status = (Status) checkResult.get(Constants.STATUS); |
||||
if (status != Status.SUCCESS) { |
||||
return checkResult; |
||||
} |
||||
|
||||
// check whether the task instance can be found
|
||||
TaskInstance task = taskInstanceMapper.selectById(taskInstanceId); |
||||
if (task == null) { |
||||
putMsg(result, Status.TASK_INSTANCE_NOT_FOUND); |
||||
return result; |
||||
} |
||||
|
||||
// check whether the task instance state type is failure
|
||||
if (!task.getState().typeIsFailure()) { |
||||
putMsg(result, Status.TASK_INSTANCE_STATE_OPERATION_ERROR, taskInstanceId, task.getState().toString()); |
||||
return result; |
||||
} |
||||
|
||||
// change the state of the task instance
|
||||
task.setState(ExecutionStatus.FORCED_SUCCESS); |
||||
int changedNum = taskInstanceMapper.updateById(task); |
||||
if (changedNum > 0) { |
||||
putMsg(result, Status.SUCCESS); |
||||
} else { |
||||
putMsg(result, Status.FORCE_TASK_SUCCESS_ERROR); |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/*** |
||||
* generate {@link org.apache.dolphinscheduler.api.enums.Status#REQUEST_PARAMS_NOT_VALID_ERROR} res with param name |
||||
* @param result exist result map |
||||
* @param params invalid params name |
||||
* @return update result map |
||||
*/ |
||||
private Map<String, Object> generateInvalidParamRes(Map<String, Object> result, String params) { |
||||
result.put(Constants.STATUS, Status.REQUEST_PARAMS_NOT_VALID_ERROR); |
||||
result.put(Constants.MSG, MessageFormat.format(Status.REQUEST_PARAMS_NOT_VALID_ERROR.getMsg(), params)); |
||||
return result; |
||||
} |
||||
} |
Loading…
Reference in new issue