Unverified Commit 7806c06d authored by 金鑫's avatar 金鑫 Committed by GitHub

[Feature][admin,scheduler] Integrate Apache DolphinScheduler to create task definition (#1024)

* 添加dolphinscheduler配置

* 添加第三方海豚调度

* 添加第三方海豚调度,遗漏对象

* 第三方海豚调度,代码格式化

* 第三方海豚调度,Controller

* 初始化海豚调度项目,修改添加调度逻辑

* Update cdcsource_statements.md

cdcsource增加支持多目标库同步功能。

* 目前存在的已知问题 1.dlink与海豚调度关联关系是根据 通过工作流定义和任务定义关联 2.海豚调度添加修改任务定义存在主键冲突bug 3.海豚调度添加修改任务定义,存在工作流定义与任务定义关联关系会断开关联关系 目前临时解决方式是 第一个任务时间戳更新备注,非第一个任务定义必选前置任务和更新备注

* 代码格式化

* 代码格式化,统一log

* Token拦截器修改

* 集成海豚调试前端

* 代理地址还原

* 格式化代码

* 去掉问题依赖

* 海豚调试推送,新增超时告警、超时策略

* 海豚调度,非DINKY类型报错

* 海豚调度,前置任务回显问题

* 海豚前置任务回显

* Add dolphin description in dolphinscheduler information modal

* 海豚调度,代码格式化以及推送备注添加

* fixed bug

* 还原代码
Co-authored-by: 's avatar郑文豪 <1103846001@qq.com>
Co-authored-by: 's avatar金鑫 <jinyanhui@huansi.net>
Co-authored-by: ZhangZifeng <>
parent 94ef0ec9
...@@ -201,6 +201,12 @@ ...@@ -201,6 +201,12 @@
<artifactId>dlink-client-hadoop</artifactId> <artifactId>dlink-client-hadoop</artifactId>
<scope>${scope.runtime}</scope> <scope>${scope.runtime}</scope>
</dependency> </dependency>
<dependency>
<groupId>com.dlink</groupId>
<artifactId>dlink-scheduler</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
......
...@@ -38,8 +38,9 @@ public class SaTokenConfigure implements WebMvcConfigurer { ...@@ -38,8 +38,9 @@ public class SaTokenConfigure implements WebMvcConfigurer {
public void addInterceptors(InterceptorRegistry registry) { public void addInterceptors(InterceptorRegistry registry) {
// 注册Sa-Token的路由拦截器 // 注册Sa-Token的路由拦截器
registry.addInterceptor(new SaRouteInterceptor()) registry.addInterceptor(new SaRouteInterceptor())
.addPathPatterns("/api/**") .addPathPatterns("/api/**")
.excludePathPatterns("/api/login") .excludePathPatterns("/api/login")
.excludePathPatterns("/openapi/**"); .excludePathPatterns("/openapi/**");
} }
} }
...@@ -22,13 +22,23 @@ package com.dlink.exception; ...@@ -22,13 +22,23 @@ package com.dlink.exception;
import com.dlink.common.result.Result; import com.dlink.common.result.Result;
import com.dlink.model.CodeEnum; import com.dlink.model.CodeEnum;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.context.request.ServletRequestAttributes;
...@@ -59,9 +69,29 @@ public class WebExceptionHandler { ...@@ -59,9 +69,29 @@ public class WebExceptionHandler {
return Result.notLogin("该用户未登录!"); return Result.notLogin("该用户未登录!");
} }
@ResponseStatus(HttpStatus.BAD_REQUEST) //设置状态码为 400
@ExceptionHandler({MethodArgumentNotValidException.class})
public Result<String> paramExceptionHandler(MethodArgumentNotValidException e) {
BindingResult exceptions = e.getBindingResult();
// 判断异常中是否有错误信息,如果存在就使用异常中的消息,否则使用默认消息
if (exceptions.hasErrors()) {
List<ObjectError> errors = exceptions.getAllErrors();
if (!errors.isEmpty()) {
// 这里列出了全部错误参数,按正常逻辑,只需要第一条错误即可
FieldError fieldError = (FieldError) errors.get(0);
if (StringUtils.isNotBlank(fieldError.getDefaultMessage())) {
return Result.failed(String.format("字段:%s, %s", fieldError.getField(), fieldError.getDefaultMessage()));
}
return Result.failed(String.format("字段:%s,不合法的值:%s", fieldError.getField(), fieldError.getRejectedValue()));
}
}
return Result.failed("请求参数错误");
}
@ExceptionHandler @ExceptionHandler
public Result unknownException(Exception e) { public Result unknownException(Exception e) {
logger.error("ERROR:", e); logger.error("ERROR:", e);
return Result.failed(e.getMessage()); return Result.failed(e.getMessage());
} }
} }
...@@ -23,6 +23,9 @@ import com.dlink.daemon.task.DaemonFactory; ...@@ -23,6 +23,9 @@ import com.dlink.daemon.task.DaemonFactory;
import com.dlink.daemon.task.DaemonTaskConfig; import com.dlink.daemon.task.DaemonTaskConfig;
import com.dlink.job.FlinkJobTask; import com.dlink.job.FlinkJobTask;
import com.dlink.model.JobInstance; import com.dlink.model.JobInstance;
import com.dlink.scheduler.client.ProjectClient;
import com.dlink.scheduler.exception.SchedulerException;
import com.dlink.scheduler.model.Project;
import com.dlink.service.JobInstanceService; import com.dlink.service.JobInstanceService;
import com.dlink.service.SysConfigService; import com.dlink.service.SysConfigService;
import com.dlink.service.TaskService; import com.dlink.service.TaskService;
...@@ -49,7 +52,8 @@ import org.springframework.stereotype.Component; ...@@ -49,7 +52,8 @@ import org.springframework.stereotype.Component;
public class SystemInit implements ApplicationRunner { public class SystemInit implements ApplicationRunner {
private static final Logger log = LoggerFactory.getLogger(SystemInit.class); private static final Logger log = LoggerFactory.getLogger(SystemInit.class);
@Autowired
private ProjectClient projectClient;
@Autowired @Autowired
private SysConfigService sysConfigService; private SysConfigService sysConfigService;
@Autowired @Autowired
...@@ -57,6 +61,8 @@ public class SystemInit implements ApplicationRunner { ...@@ -57,6 +61,8 @@ public class SystemInit implements ApplicationRunner {
@Autowired @Autowired
private TaskService taskService; private TaskService taskService;
private static Project project;
@Override @Override
public void run(ApplicationArguments args) throws Exception { public void run(ApplicationArguments args) throws Exception {
sysConfigService.initSysConfig(); sysConfigService.initSysConfig();
...@@ -68,5 +74,20 @@ public class SystemInit implements ApplicationRunner { ...@@ -68,5 +74,20 @@ public class SystemInit implements ApplicationRunner {
} }
log.info("启动的任务数量:" + configList.size()); log.info("启动的任务数量:" + configList.size());
DaemonFactory.start(configList); DaemonFactory.start(configList);
try {
project = projectClient.getDinkyProject();
if (project == null) {
project = projectClient.createDinkyProject();
}
} catch (Exception e) {
log.error("海豚调度异常: {}", e);
}
}
public static Project getProject() {
if (project == null) {
throw new SchedulerException("请完善海豚调度配置,重启dlink");
}
return project;
} }
} }
...@@ -74,3 +74,14 @@ sa-token: ...@@ -74,3 +74,14 @@ sa-token:
knife4j: knife4j:
enable: true enable: true
dinky:
# dinky 地址
url: http://127.0.0.1:8888
dolphinscheduler:
# dolphinscheduler 地址
url: http://127.0.0.1:12345/dolphinscheduler
# dolphinscheduler 生成的token
token: 466cb6f6455b1b8689fff770746e2e79
# dolphinscheduler 中指定的项目名不区分大小写
project-name: dinky
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>dlink</artifactId>
<groupId>com.dlink</groupId>
<version>0.6.7</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dlink-scheduler</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
/*
*
* 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 com.dlink.scheduler.client;
import com.dlink.scheduler.constant.Constants;
import com.dlink.scheduler.model.DagData;
import com.dlink.scheduler.model.ProcessDefinition;
import com.dlink.scheduler.result.PageInfo;
import com.dlink.scheduler.result.Result;
import com.dlink.scheduler.utils.MyJSONUtil;
import com.dlink.scheduler.utils.ParamUtil;
import com.dlink.scheduler.utils.ReadFileUtil;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONObject;
/**
* 工作流定义
*
* @author 郑文豪
*/
@Component
public class ProcessClient {
private static final Logger logger = LoggerFactory.getLogger(TaskClient.class);
@Value("${dinky.dolphinscheduler.url}")
private String url;
@Value("${dinky.dolphinscheduler.token}")
private String tokenKey;
/**
* 查询工作流定义
*
* @param projectCode 项目编号
* @param processName 工作流定义名
* @return {@link List<ProcessDefinition>}
* @author 郑文豪
* @date 2022/9/7 16:59
*/
public List<ProcessDefinition> getProcessDefinition(Long projectCode, String processName) {
Map<String, Object> map = new HashMap<>();
map.put("projectCode", projectCode);
String format = StrUtil.format(url + "/projects/{projectCode}/process-definition", map);
String content = HttpRequest.get(format)
.header(Constants.TOKEN, tokenKey)
.form(ParamUtil.getPageParams(processName))
.timeout(5000)
.execute().body();
PageInfo<JSONObject> data = MyJSONUtil.toPageBean(content);
List<ProcessDefinition> lists = new ArrayList<>();
if (data == null || data.getTotalList() == null) {
return lists;
}
for (JSONObject jsonObject : data.getTotalList()) {
lists.add(MyJSONUtil.toBean(jsonObject, ProcessDefinition.class));
}
return lists;
}
/**
* 查询工作流定义
*
* @param projectCode 项目编号
* @param processName 工作流定义名
* @return {@link ProcessDefinition}
* @author 郑文豪
* @date 2022/9/7 16:59
*/
public ProcessDefinition getProcessDefinitionInfo(Long projectCode, String processName) {
List<ProcessDefinition> lists = getProcessDefinition(projectCode, processName);
for (ProcessDefinition list : lists) {
if (list.getName().equalsIgnoreCase(processName)) {
return list;
}
}
return null;
}
/**
* 根据编号获取
*
* @param projectCode 项目编号
* @param processCode 任务编号
* @return {@link DagData}
* @author 郑文豪
* @date 2022/9/13 14:33
*/
public DagData getProcessDefinitionInfo(Long projectCode, Long processCode) {
Map<String, Object> map = new HashMap<>();
map.put("projectCode", projectCode);
map.put("code", processCode);
String format = StrUtil.format(url + "/projects/{projectCode}/process-definition/{code}", map);
String content = HttpRequest.get(format)
.header(Constants.TOKEN, tokenKey)
.timeout(5000)
.execute().body();
return MyJSONUtil.verifyResult(MyJSONUtil.toBean(content, new TypeReference<Result<DagData>>() {
}));
}
/**
* 创建工作流定义
*
* @param projectCode 项目编号
* @param processName 工作流定义名称
* @return {@link ProcessDefinition}
* @author 郑文豪
* @date 2022/9/7 17:00
*/
public ProcessDefinition createProcessDefinition(Long projectCode, String processName, Long taskCode, String taskDefinitionJson) {
Map<String, Object> map = new HashMap<>();
map.put("projectCode", projectCode);
String format = StrUtil.format(url + "/projects/{projectCode}/process-definition", map);
Map<String, Object> taskMap = new HashMap<>();
taskMap.put("code", taskCode);
String taskRelationJson = ReadFileUtil.taskRelation(taskMap);
Map<String, Object> params = new HashMap<>();
params.put("name", processName);
params.put("description", "系统添加");
params.put("tenantCode", "default");
params.put("taskRelationJson", taskRelationJson);
params.put("taskDefinitionJson", taskDefinitionJson);
params.put("executionType", "PARALLEL");
String content = HttpRequest.post(format)
.header(Constants.TOKEN, tokenKey)
.form(params)
.timeout(5000)
.execute().body();
return MyJSONUtil.verifyResult(MyJSONUtil.toBean(content, new TypeReference<Result<ProcessDefinition>>() {
}));
}
}
/*
*
* 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 com.dlink.scheduler.client;
import com.dlink.scheduler.constant.Constants;
import com.dlink.scheduler.model.Project;
import com.dlink.scheduler.result.Result;
import com.dlink.scheduler.utils.MyJSONUtil;
import com.dlink.scheduler.utils.ParamUtil;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.http.HttpRequest;
/**
* 项目
*
* @author 郑文豪
*/
@Component
public class ProjectClient {
private static final Logger logger = LoggerFactory.getLogger(TaskClient.class);
@Value("${dinky.dolphinscheduler.url}")
private String url;
@Value("${dinky.dolphinscheduler.token}")
private String tokenKey;
@Value("${dinky.dolphinscheduler.project-name}")
private String dinkyProjectName;
/**
* 创建项目
*
* @return {@link Project}
* @author 郑文豪
* @date 2022/9/7 16:57
*/
public Project createDinkyProject() {
Map<String, Object> map = new HashMap<>();
map.put("projectName", dinkyProjectName);
map.put("description", "自动创建");
String content = HttpRequest.post(url + "/projects")
.header(Constants.TOKEN, tokenKey)
.form(map)
.timeout(5000)
.execute().body();
return MyJSONUtil.verifyResult(MyJSONUtil.toBean(content, new TypeReference<Result<Project>>() {
}));
}
/**
* 查询项目
*
* @return {@link Project}
* @author 郑文豪
* @date 2022/9/7 16:57
*/
public Project getDinkyProject() {
String content = HttpRequest.get(url + "/projects")
.header(Constants.TOKEN, tokenKey)
.form(ParamUtil.getPageParams(dinkyProjectName))
.timeout(5000)
.execute().body();
return MyJSONUtil.toPageBeanAndFindByName(content, dinkyProjectName, Project.class);
}
}
/*
*
* 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 com.dlink.scheduler.client;
import com.dlink.scheduler.constant.Constants;
import com.dlink.scheduler.exception.SchedulerException;
import com.dlink.scheduler.model.TaskDefinition;
import com.dlink.scheduler.model.TaskDefinitionLog;
import com.dlink.scheduler.model.TaskMainInfo;
import com.dlink.scheduler.result.PageInfo;
import com.dlink.scheduler.result.Result;
import com.dlink.scheduler.utils.MyJSONUtil;
import com.dlink.scheduler.utils.ParamUtil;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONObject;
/**
* 任务定义
*
* @author 郑文豪
*/
@Component
public class TaskClient {
private static final Logger logger = LoggerFactory.getLogger(TaskClient.class);
@Value("${dinky.dolphinscheduler.url}")
private String url;
@Value("${dinky.dolphinscheduler.token}")
private String tokenKey;
/**
* 查询任务定义
*
* @param projectCode 项目编号
* @param processName 工作流定义名称
* @param taskName 任务定义名称
* @return {@link TaskMainInfo}
* @author 郑文豪
* @date 2022/9/7 17:16
*/
public TaskMainInfo getTaskMainInfo(Long projectCode, String processName, String taskName) {
List<TaskMainInfo> lists = getTaskMainInfos(projectCode, processName, taskName);
for (TaskMainInfo list : lists) {
if (list.getTaskName().equalsIgnoreCase(taskName)) {
return list;
}
}
return null;
}
/**
* 查询任务定义集合
*
* @param projectCode 项目编号
* @param processName 工作流定义名称
* @param taskName 任务定义名称
* @return {@link List<TaskMainInfo>}
* @author 郑文豪
* @date 2022/9/7 17:16
*/
public List<TaskMainInfo> getTaskMainInfos(Long projectCode, String processName, String taskName) {
Map<String, Object> map = new HashMap<>();
map.put("projectCode", projectCode);
String format = StrUtil.format(url + "/projects/{projectCode}/task-definition", map);
Map<String, Object> pageParams = ParamUtil.getPageParams();
pageParams.put("searchTaskName", taskName);
pageParams.put("searchWorkflowName", processName);
pageParams.put("taskType", "DINKY");
String content = HttpRequest.get(format)
.header(Constants.TOKEN, tokenKey)
.form(pageParams)
.timeout(5000)
.execute().body();
PageInfo<JSONObject> data = MyJSONUtil.toPageBean(content);
List<TaskMainInfo> lists = new ArrayList<>();
if (data == null || data.getTotalList() == null) {
return lists;
}
for (JSONObject jsonObject : data.getTotalList()) {
if (processName.equalsIgnoreCase(jsonObject.getStr("processDefinitionName"))) {
lists.add(MyJSONUtil.toBean(jsonObject, TaskMainInfo.class));
}
}
return lists;
}
/**
* 根据编号查询
*
* @param projectCode 项目编号
* @param taskCode 任务编号
* @return {@link TaskDefinition}
* @author 郑文豪
* @date 2022/9/13 10:52
*/
public TaskDefinition getTaskDefinition(Long projectCode, Long taskCode) {
Map<String, Object> map = new HashMap<>();
map.put("projectCode", projectCode);
map.put("code", taskCode);
String format = StrUtil.format(url + "/projects/{projectCode}/task-definition/{code}", map);
String content = HttpRequest.get(format)
.header(Constants.TOKEN, tokenKey)
.timeout(5000)
.execute().body();
return MyJSONUtil.verifyResult(MyJSONUtil.toBean(content, new TypeReference<Result<TaskDefinition>>() {
}));
}
/**
* 创建任务定义
*
* @param projectCode 项目编号
* @param processCode 工作流定义编号
* @return {@link TaskDefinitionLog}
* @author 郑文豪
* @date 2022/9/7 17:05
*/
public TaskDefinitionLog createTaskDefinition(Long projectCode, Long processCode, String upstreamCodes, String taskDefinitionJsonObj) {
Map<String, Object> map = new HashMap<>();
map.put("projectCode", projectCode);
String format = StrUtil.format(url + "/projects/{projectCode}/task-definition/save-single", map);
Map<String, Object> pageParams = new HashMap<>();
pageParams.put("processDefinitionCode", processCode);
if (StringUtils.isNotBlank(upstreamCodes)) {
pageParams.put("upstreamCodes", upstreamCodes);
}
pageParams.put("taskDefinitionJsonObj", taskDefinitionJsonObj);
String content = HttpRequest.post(format)
.header(Constants.TOKEN, tokenKey)
.form(pageParams)
.timeout(5000)
.execute().body();
return MyJSONUtil.verifyResult(MyJSONUtil.toBean(content, new TypeReference<Result<TaskDefinitionLog>>() {
}));
}
/**
* 修改任务定义
*
* @param projectCode 项目编号
* @param taskCode 任务定义编号
* @param taskDefinitionJsonObj 修改参数
* @return {@link Long}
* @author 郑文豪
* @date 2022/9/13 8:59
*/
public Long updateTaskDefinition(long projectCode, long taskCode, String upstreamCodes, String taskDefinitionJsonObj) {
Map<String, Object> map = new HashMap<>();
map.put("projectCode", projectCode);
map.put("code", taskCode);
String format = StrUtil.format(url + "/projects/{projectCode}/task-definition/{code}/with-upstream", map);
Map<String, Object> params = new HashMap<>();
params.put("upstreamCodes", upstreamCodes);
params.put("taskDefinitionJsonObj", taskDefinitionJsonObj);
String content = HttpRequest.put(format)
.header(Constants.TOKEN, tokenKey)
.form(params)
.timeout(5000)
.execute().body();
return MyJSONUtil.verifyResult(MyJSONUtil.toBean(content, new TypeReference<Result<Long>>() {
}));
}
/**
* 生成任务定义编号
*
* @param projectCode 项目编号
* @param genNum 生成个数
* @return {@link List}
* @author 郑文豪
* @date 2022/9/8 18:00
*/
public List<Long> genTaskCodes(Long projectCode, int genNum) {
Map<String, Object> map = new HashMap<>();
map.put("projectCode", projectCode);
String format = StrUtil.format(url + "/projects/{projectCode}/task-definition/gen-task-codes", map);
Map<String, Object> params = new HashMap<>();
params.put("genNum", genNum);
String content = HttpRequest.get(format)
.header(Constants.TOKEN, tokenKey)
.form(params)
.timeout(5000)
.execute().body();
return MyJSONUtil.verifyResult(MyJSONUtil.toBean(content, new TypeReference<Result<List<Long>>>() {
}));
}
/**
* 生成一个任务定义编号
*
* @param projectCode 项目编号
* @return {@link Long}
* @author 郑文豪
* @date 2022/9/8 18:02
*/
public Long genTaskCode(Long projectCode) {
List<Long> codes = genTaskCodes(projectCode, 1);
if (codes == null || codes.isEmpty()) {
throw new SchedulerException("生成任务定义编号失败");
}
return codes.get(0);
}
}
/*
*
* 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 com.dlink.scheduler.constant;
/**
* @author 郑文豪
*/
public class Constants {
public static String TOKEN = "token";
/**
* comma ,
*/
public static final String COMMA = ",";
}
/*
*
* 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 com.dlink.scheduler.enums;
import java.util.HashMap;
import java.util.Map;
/**
* condition type
*/
public enum ConditionType {
/**
* 0 none
* 1 judge
* 2 delay
*/
NONE(0, "none"),
JUDGE(1, "judge"),
DELAY(2, "delay");
ConditionType(int code, String desc) {
this.code = code;
this.desc = desc;
}
private final int code;
private final String desc;
public int getCode() {
return code;
}
public String getDesc() {
return desc;
}
private static final Map<String, ConditionType> CONDITION_TYPE_MAP = new HashMap<>();
static {
for (ConditionType conditionType : ConditionType.values()) {
CONDITION_TYPE_MAP.put(conditionType.desc, conditionType);
}
}
public static ConditionType of(String desc) {
if (CONDITION_TYPE_MAP.containsKey(desc)) {
return CONDITION_TYPE_MAP.get(desc);
}
throw new IllegalArgumentException("invalid type : " + desc);
}
}
/*
*
* 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 com.dlink.scheduler.enums;
/**
* data types in user define parameter
*/
public enum DataType {
/**
* 0 string
* 1 integer
* 2 long
* 3 float
* 4 double
* 5 date, "YYYY-MM-DD"
* 6 time, "HH:MM:SS"
* 7 time stamp
* 8 Boolean
* 9 list <String>
*/
VARCHAR, INTEGER, LONG, FLOAT, DOUBLE, DATE, TIME, TIMESTAMP, BOOLEAN, LIST
}
/*
*
* 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 com.dlink.scheduler.enums;
/**
* parameter of stored procedure
*/
public enum Direct {
/**
* 0 in; 1 out;
*/
IN, OUT
}
/*
*
* 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 com.dlink.scheduler.enums;
/**
* have_script
* have_file
* can_retry
* have_arr_variables
* have_map_variables
* have_alert
*/
public enum Flag {
/**
* 0 no
* 1 yes
*/
NO(0, "no"),
YES(1, "yes");
Flag(int code, String descp) {
this.code = code;
this.descp = descp;
}
private final int code;
private final String descp;
public int getCode() {
return code;
}
public String getDescp() {
return descp;
}
}
/*
*
* 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 com.dlink.scheduler.enums;
/**
* define process and task priority
*/
public enum Priority {
/**
* 0 highest priority
* 1 higher priority
* 2 medium priority
* 3 lower priority
* 4 lowest priority
*/
HIGHEST(0, "highest"),
HIGH(1, "high"),
MEDIUM(2, "medium"),
LOW(3, "low"),
LOWEST(4, "lowest");
Priority(int code, String descp) {
this.code = code;
this.descp = descp;
}
private final int code;
private final String descp;
public int getCode() {
return code;
}
public String getDescp() {
return descp;
}
}
/*
*
* 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 com.dlink.scheduler.enums;
import java.util.HashMap;
public enum ProcessExecutionTypeEnum {
PARALLEL(0, "parallel"),
SERIAL_WAIT(1, "serial wait"),
SERIAL_DISCARD(2, "serial discard"),
SERIAL_PRIORITY(3, "serial priority");
ProcessExecutionTypeEnum(int code, String descp) {
this.code = code;
this.descp = descp;
}
private final int code;
private final String descp;
private static HashMap<Integer, ProcessExecutionTypeEnum> EXECUTION_STATUS_MAP = new HashMap<>();
static {
for (ProcessExecutionTypeEnum executionType : ProcessExecutionTypeEnum.values()) {
EXECUTION_STATUS_MAP.put(executionType.code, executionType);
}
}
public boolean typeIsSerial() {
return this != PARALLEL;
}
public boolean typeIsSerialWait() {
return this == SERIAL_WAIT;
}
public boolean typeIsSerialDiscard() {
return this == SERIAL_DISCARD;
}
public boolean typeIsSerialPriority() {
return this == SERIAL_PRIORITY;
}
public int getCode() {
return code;
}
public String getDescp() {
return descp;
}
public static ProcessExecutionTypeEnum of(int executionType) {
if (EXECUTION_STATUS_MAP.containsKey(executionType)) {
return EXECUTION_STATUS_MAP.get(executionType);
}
throw new IllegalArgumentException("invalid status : " + executionType);
}
}
/*
*
* 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 com.dlink.scheduler.enums;
/**
* process define release state
*/
public enum ReleaseState {
/**
* 0 offline
* 1 online
*/
OFFLINE(0, "offline"),
ONLINE(1, "online");
ReleaseState(int code, String descp) {
this.code = code;
this.descp = descp;
}
private final int code;
private final String descp;
public static ReleaseState getEnum(int value) {
for (ReleaseState e : ReleaseState.values()) {
if (e.ordinal() == value) {
return e;
}
}
//For values out of enum scope
return null;
}
public int getCode() {
return code;
}
public String getDescp() {
return descp;
}
}
/*
*
* 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 com.dlink.scheduler.enums;
/**
* task execute type
*/
public enum TaskExecuteType {
/**
* 0 batch
* 1 stream
*/
BATCH(0, "batch"),
STREAM(1, "stream");
TaskExecuteType(int code, String desc) {
this.code = code;
this.desc = desc;
}
private final int code;
private final String desc;
public int getCode() {
return code;
}
public String getDesc() {
return desc;
}
}
/*
*
* 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 com.dlink.scheduler.enums;
/**
* task timeout strategy
*/
public enum TaskTimeoutStrategy {
/**
* 0 warn
* 1 failed
* 2 warn+failed
*/
WARN(0, "warn"),
FAILED(1, "failed"),
WARNFAILED(2, "warnfailed");
TaskTimeoutStrategy(int code, String descp) {
this.code = code;
this.descp = descp;
}
private final int code;
private final String descp;
public int getCode() {
return code;
}
public String getDescp() {
return descp;
}
public static TaskTimeoutStrategy of(int status) {
for (TaskTimeoutStrategy es : values()) {
if (es.getCode() == status) {
return es;
}
}
throw new IllegalArgumentException("invalid status : " + status);
}
}
/*
*
* 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 com.dlink.scheduler.enums;
/**
* timeout flag
*/
public enum TimeoutFlag {
/**
* 0 close
* 1 open
*/
CLOSE(0, "close"),
OPEN(1, "open");
TimeoutFlag(int code, String desc) {
this.code = code;
this.desc = desc;
}
private final int code;
private final String desc;
public int getCode() {
return code;
}
public String getDesc() {
return desc;
}
}
/*
*
* 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 com.dlink.scheduler.exception;
/**
* @author 郑文豪
*/
public class SchedulerException extends RuntimeException {
public SchedulerException(String message) {
super(message);
}
}
/*
*
* 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 com.dlink.scheduler.model;
import java.util.List;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* DagData
*/
@Data
public class DagData {
@ApiModelProperty(value = "工作流程定义")
private ProcessDefinition processDefinition;
@ApiModelProperty(value = "工作流程定义,任务定义关联 关联关系集合")
private List<ProcessTaskRelation> processTaskRelationList;
@ApiModelProperty(value = "任务定义关联集合")
private List<TaskDefinition> taskDefinitionList;
}
/*
*
* 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 com.dlink.scheduler.model;
import java.util.List;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author 郑文豪
*/
@Data
public class DlinkTaskParams {
@ApiModelProperty(value = "自定义参数")
private List<Property> localParams;
@ApiModelProperty(value = "dlink地址")
private String address;
@ApiModelProperty(value = "dlink任务id", required = true)
private String taskId;
}
/*
*
* 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 com.dlink.scheduler.model;
import com.dlink.scheduler.enums.Flag;
import com.dlink.scheduler.enums.ProcessExecutionTypeEnum;
import com.dlink.scheduler.enums.ReleaseState;
import java.util.Date;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* process definition
*/
@Data
public class ProcessDefinition {
@ApiModelProperty(value = "id")
private Integer id;
@ApiModelProperty(value = "编号")
private Long code;
@ApiModelProperty(value = "名称")
private String name;
@ApiModelProperty(value = "版本号")
private Integer version;
@ApiModelProperty(value = "发布状态 online/offline")
private ReleaseState releaseState;
@ApiModelProperty(value = "项目编号")
private Long projectCode;
@ApiModelProperty(value = "描述")
private String description;
@ApiModelProperty(value = "用户自定义参数")
private String globalParams;
@ApiModelProperty(value = "用户自定义参数列表")
private List<Property> globalParamList;
@ApiModelProperty(value = "用户自定义参数映射")
private Map<String, String> globalParamMap;
@ApiModelProperty(value = "创建时间")
@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@ApiModelProperty(value = "更新时间")
@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
@ApiModelProperty(value = "是否生效 yes/no")
private Flag flag;
@ApiModelProperty(value = "创建人id")
private Integer userId;
@ApiModelProperty(value = "创建人名称")
private String userName;
@ApiModelProperty(value = "项目名称")
private String projectName;
@ApiModelProperty(value = "位置")
private String locations;
@ApiModelProperty(value = "计划发布状态 online/offline")
private ReleaseState scheduleReleaseState;
@ApiModelProperty(value = "超时告警(分钟)")
private Integer timeout;
@ApiModelProperty(value = "租户id")
private Integer tenantId;
@ApiModelProperty(value = "租户编号")
private String tenantCode;
@ApiModelProperty(value = "修改用户名")
private String modifyBy;
@ApiModelProperty(value = "告警分组id")
private Integer warningGroupId;
@ApiModelProperty(value = "执行类型")
private ProcessExecutionTypeEnum executionType;
}
/*
*
* 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 com.dlink.scheduler.model;
import com.dlink.scheduler.enums.ConditionType;
import java.util.Date;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class ProcessTaskRelation {
@ApiModelProperty(value = "id")
private Integer id;
@ApiModelProperty(value = "名称")
private String name;
@ApiModelProperty(value = "工作流定义")
private int processDefinitionVersion;
@ApiModelProperty(value = "项目编号")
private long projectCode;
@ApiModelProperty(value = "工作流定义编号")
private long processDefinitionCode;
@ApiModelProperty(value = "前置任务编号")
private long preTaskCode;
@ApiModelProperty(value = "前置任务版本")
private int preTaskVersion;
@ApiModelProperty(value = "发布任务编号")
private long postTaskCode;
@ApiModelProperty(value = "发布任务版本")
private int postTaskVersion;
@ApiModelProperty(value = "条件类型")
private ConditionType conditionType;
@ApiModelProperty(value = "条件参数")
private String conditionParams;
@ApiModelProperty(value = "创建时间")
private Date createTime;
@ApiModelProperty(value = "更新时间")
private Date updateTime;
}
/*
*
* 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 com.dlink.scheduler.model;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* project
*/
@Data
public class Project {
@ApiModelProperty(value = "id")
private Integer id;
@ApiModelProperty(value = "用户id")
private Integer userId;
@ApiModelProperty(value = "用户名")
private String userName;
@ApiModelProperty(value = "项目编号")
private Long code;
@ApiModelProperty(value = "项目名")
private String name;
@ApiModelProperty(value = "描述")
private String description;
@ApiModelProperty(value = "创建时间")
@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@ApiModelProperty(value = "修改时间")
@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
@ApiModelProperty(value = "许可")
private Integer perm;
@ApiModelProperty(value = "过程定义数")
private Integer defCount;
@ApiModelProperty(value = "流程实例运行计数")
private Integer instRunningCount;
}
/*
*
* 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 com.dlink.scheduler.model;
import com.dlink.scheduler.enums.DataType;
import com.dlink.scheduler.enums.Direct;
import java.io.Serializable;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class Property implements Serializable {
private static final long serialVersionUID = -4045513703397452451L;
@ApiModelProperty(value = "key")
private String prop;
/**
* input/output
*/
private Direct direct;
/**
* data type
*/
private DataType type;
@ApiModelProperty(value = "value")
private String value;
}
/*
*
* 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 com.dlink.scheduler.model;
import com.dlink.scheduler.enums.Flag;
import com.dlink.scheduler.enums.Priority;
import com.dlink.scheduler.enums.TaskExecuteType;
import com.dlink.scheduler.enums.TaskTimeoutStrategy;
import com.dlink.scheduler.enums.TimeoutFlag;
import java.util.Date;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* task definition
*/
@Data
public class TaskDefinition {
@ApiModelProperty(value = "id")
private Integer id;
@ApiModelProperty(value = "编号")
private Long code;
@ApiModelProperty(value = "名称")
private String name;
@ApiModelProperty(value = "版本号")
private Integer version;
@ApiModelProperty(value = "描述")
private String description;
@ApiModelProperty(value = "项目编号")
private Long projectCode;
@ApiModelProperty(value = "创建人")
private Integer userId;
@ApiModelProperty(value = "任务类型")
private String taskType;
@ApiModelProperty(value = "任务参数")
private String taskParams;
@ApiModelProperty(value = "任务参数列表")
private List<Property> taskParamList;
@ApiModelProperty(value = "任务参数映射")
private Map<String, String> taskParamMap;
@ApiModelProperty(value = "运行标志 yes 正常/no 禁止执行")
private Flag flag;
@ApiModelProperty(value = "优先级")
private Priority taskPriority;
@ApiModelProperty(value = "创建用户名")
private String userName;
@ApiModelProperty(value = "项目名称")
private String projectName;
@ApiModelProperty(value = "worker分组")
private String workerGroup;
@ApiModelProperty(value = "环境编号")
private Long environmentCode;
@ApiModelProperty(value = "重试次数")
private Integer failRetryTimes;
@ApiModelProperty(value = "重试间隔")
private Integer failRetryInterval;
@ApiModelProperty(value = "超时标识")
private TimeoutFlag timeoutFlag;
@ApiModelProperty(value = "超时通知策略")
private TaskTimeoutStrategy timeoutNotifyStrategy;
@ApiModelProperty(value = "超时时间(分钟)")
private Integer timeout;
@ApiModelProperty(value = "延迟执行时间")
private Integer delayTime;
@ApiModelProperty(value = "资源ids")
private String resourceIds;
@ApiModelProperty(value = "创建时间")
@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@ApiModelProperty(value = "更新时间")
@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
@ApiModelProperty(value = "更新人")
private String modifyBy;
@ApiModelProperty(value = "任务组id")
private Integer taskGroupId;
@ApiModelProperty(value = "任务组id")
private Integer taskGroupPriority;
@ApiModelProperty(value = "cpu 配额")
private Integer cpuQuota;
@ApiModelProperty(value = "最大内存")
private Integer memoryMax;
@ApiModelProperty(value = "执行类型")
private TaskExecuteType taskExecuteType;
@ApiModelProperty(value = "工作流编号")
private Long processDefinitionCode;
@ApiModelProperty(value = "工作流编号")
private Integer processDefinitionVersion;
@ApiModelProperty(value = "工作流名")
private String processDefinitionName;
@ApiModelProperty(value = "前置任务集合")
private Map<Long, String> upstreamTaskMap;
}
/*
*
* 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 com.dlink.scheduler.model;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* task definition log
*/
@Data
public class TaskDefinitionLog extends TaskDefinition {
@ApiModelProperty(value = "操作人")
private Integer operator;
@ApiModelProperty(value = "操作时间")
@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date operateTime;
}
/*
*
* 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 com.dlink.scheduler.model;
import com.dlink.scheduler.enums.ReleaseState;
import java.util.Date;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* task main info
*/
@Data
public class TaskMainInfo {
@ApiModelProperty(value = "id")
private Long id;
@ApiModelProperty(value = "任务名")
private String taskName;
@ApiModelProperty(value = "任务编号")
private Long taskCode;
@ApiModelProperty(value = "任务版本")
private Integer taskVersion;
@ApiModelProperty(value = "任务类型")
private String taskType;
@ApiModelProperty(value = "创建时间")
@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date taskCreateTime;
@ApiModelProperty(value = "更新时间")
@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date taskUpdateTime;
@ApiModelProperty(value = "工作流编号")
private Long processDefinitionCode;
@ApiModelProperty(value = "工作流编号")
private Integer processDefinitionVersion;
@ApiModelProperty(value = "工作流名")
private String processDefinitionName;
@ApiModelProperty(value = "状态")
private ReleaseState processReleaseState;
@ApiModelProperty(value = "前置任务集合")
private Map<Long, String> upstreamTaskMap;
@ApiModelProperty(value = "前置任务编号")
private Long upstreamTaskCode;
@ApiModelProperty(value = "前置名")
private String upstreamTaskName;
}
/*
*
* 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 com.dlink.scheduler.model;
import com.dlink.scheduler.enums.Flag;
import com.dlink.scheduler.enums.Priority;
import com.dlink.scheduler.enums.TaskExecuteType;
import com.dlink.scheduler.enums.TaskTimeoutStrategy;
import com.dlink.scheduler.enums.TimeoutFlag;
import javax.validation.constraints.NotNull;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class TaskRequest {
@ApiModelProperty(value = "编号")
private Long code;
@ApiModelProperty(value = "名称")
private String name;
@ApiModelProperty(value = "描述")
private String description;
@ApiModelProperty(value = "环境编号")
private Long environmentCode;
@ApiModelProperty(value = "延迟执行时间")
private Integer delayTime;
@ApiModelProperty(value = "重试间隔")
private Integer failRetryInterval;
@ApiModelProperty(value = "重试次数")
private Integer failRetryTimes;
@ApiModelProperty(value = "运行标志 yes 正常/no 禁止执行")
private Flag flag;
@ApiModelProperty(value = "任务参数 默认DINKY参数")
private String taskParams;
@NotNull
@ApiModelProperty(value = "优先级")
private Priority taskPriority;
@ApiModelProperty(value = "任务类型 默认DINKY")
private String taskType = "DINKY";
@ApiModelProperty(value = "超时时间(分钟)")
private Integer timeout;
@ApiModelProperty(value = "超时告警")
private TimeoutFlag timeoutFlag;
@ApiModelProperty(value = "超时通知策略")
private TaskTimeoutStrategy timeoutNotifyStrategy;
@ApiModelProperty(value = "worker分组 默认default")
private String workerGroup = "default";
@ApiModelProperty(value = "cpu 配额 默认-1")
private Integer cpuQuota = -1;
@ApiModelProperty(value = "最大内存 默认-1")
private Integer memoryMax = -1;
@ApiModelProperty(value = "执行类型 默认BATCH")
private TaskExecuteType taskExecuteType = TaskExecuteType.BATCH;
}
/*
*
* 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 com.dlink.scheduler.result;
import java.util.List;
import lombok.Data;
/**
* page info
*
* @param <T> model
*/
@Data
public class PageInfo<T> {
/**
* totalList
*/
private List<T> totalList;
/**
* total
*/
private Integer total = 0;
/**
* total Page
*/
private Integer totalPage;
/**
* page size
*/
private Integer pageSize = 20;
/**
* current page
*/
private Integer currentPage = 0;
/**
* pageNo
*/
private Integer pageNo;
}
/*
*
* 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 com.dlink.scheduler.result;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@Data
@Slf4j
public class Result<T> {
/**
* status
*/
private Integer code;
/**
* message
*/
private String msg;
/**
* data
*/
private T data;
private Boolean success;
private Boolean failed;
}
/*
*
* 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 com.dlink.scheduler.utils;
import com.dlink.scheduler.exception.SchedulerException;
import com.dlink.scheduler.result.PageInfo;
import com.dlink.scheduler.result.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
/**
* @author 郑文豪
*/
public class MyJSONUtil {
private static final Logger logger = LoggerFactory.getLogger(MyJSONUtil.class);
public static <T> T toBean(String content, TypeReference<T> typeReference) {
try {
return JSONUtil.toBean(content, typeReference, true);
} catch (Exception e) {
logger.error("json转换异常 json:{},异常信息:{}", content, e.getMessage(), e);
throw new SchedulerException("数据转换异常");
}
}
public static <T> T toBean(JSONObject content, Class<T> beanClass) {
try {
return JSONUtil.toBean(content, beanClass);
} catch (Exception e) {
logger.error("json转换异常 json:{},异常信息:{}", content, e.getMessage(), e);
throw new SchedulerException("数据转换异常");
}
}
public static <T> T toBean(String content, Class<T> beanClass) {
try {
return JSONUtil.toBean(content, beanClass);
} catch (Exception e) {
logger.error("json转换异常 json:{},异常信息:{}", content, e.getMessage(), e);
throw new SchedulerException("数据转换异常");
}
}
public static <T> T verifyResult(Result<T> result) {
if (result.getFailed()) {
throw new SchedulerException(result.getMsg());
}
return result.getData();
}
/**
* json字符串转分页对象
*
* @param content json字符串
* @return {@link PageInfo}
* @author 郑文豪
* @date 2022/9/8 9:29
*/
public static PageInfo<JSONObject> toPageBean(String content) {
return verifyResult(MyJSONUtil.toBean(content,
new TypeReference<Result<PageInfo<JSONObject>>>() {
}));
}
/**
* json字符串转分页对象,根据名称精确查找
*
* @param content json字符串
* @param name 名称
* @param beanClass 要转换的class
* @return {@link T}
* @author 郑文豪
* @date 2022/9/8 9:27
*/
public static <T> T toPageBeanAndFindByName(String content, String name, Class<T> beanClass) {
PageInfo<JSONObject> data = toPageBean(content);
if (data == null || data.getTotalList() == null) {
return null;
}
for (JSONObject jsonObject : data.getTotalList()) {
if (name.equalsIgnoreCase(jsonObject.getStr("name"))) {
return toBean(jsonObject, beanClass);
}
}
return null;
}
}
/*
*
* 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 com.dlink.scheduler.utils;
import java.util.HashMap;
import java.util.Map;
/**
* @author 郑文豪
*/
public class ParamUtil {
/**
* 封装分页查询
*
* @return {@link Map}
* @author 郑文豪
* @date 2022/9/7 16:57
*/
public static Map<String, Object> getPageParams() {
Map<String, Object> params = new HashMap<>();
params.put("pageNo", 1);
params.put("pageSize", Integer.MAX_VALUE);
return params;
}
/**
* 封装分页查询
*
* @param name 查询条件
* @return {@link Map}
* @author 郑文豪
* @date 2022/9/7 16:58
*/
public static Map<String, Object> getPageParams(String name) {
Map<String, Object> params = getPageParams();
params.put("searchVal", name);
return params;
}
}
/*
*
* 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 com.dlink.scheduler.utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
/**
* @author 郑文豪
*/
public class ReadFileUtil {
private static final Logger logger = LoggerFactory.getLogger(ReadFileUtil.class);
public static String taskDefinition(Map<String, Object> maps) {
InputStream in = ReadFileUtil.class.getResourceAsStream("/json/taskDefinition.json");
String readFile = readFile(in);
if (maps == null || maps.isEmpty()) {
return readFile;
}
return StrUtil.format(readFile, maps);
}
public static String taskRelation(Map<String, Object> maps) {
InputStream in = ReadFileUtil.class.getResourceAsStream("/json/taskRelation.json");
String readFile = readFile(in);
if (maps == null || maps.isEmpty()) {
return readFile;
}
return StrUtil.format(readFile, maps);
}
public static String createTaskDefinition(Map<String, Object> maps) {
InputStream in = ReadFileUtil.class.getResourceAsStream("/json/createTaskDefinition.json");
String readFile = readFile(in);
if (maps == null || maps.isEmpty()) {
return readFile;
}
return StrUtil.format(readFile, maps);
}
/**
* 读取文件
*/
public static String readFile(InputStream inputStream) {
try {
BufferedReader reader = IoUtil.getUtf8Reader(inputStream);
int ch;
StringBuilder sb = new StringBuilder();
while ((ch = reader.read()) != -1) {
sb.append((char) ch);
}
IoUtil.close(reader);
return sb.toString();
} catch (IOException e) {
logger.error(e.getMessage(), e);
return null;
}
}
}
[
{
"name": "",
"preTaskCode": 0,
"preTaskVersion": 0,
"postTaskCode": {code},
"postTaskVersion": 0,
"conditionType": "NONE",
"conditionParams": {}
}
]
/*
*
* 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.
*
*/
import type {FormInstance} from 'antd/es/form';
import {Button, Form, InputNumber, message, Select, Switch, Checkbox, Row, Col} from "antd";
import {StateType} from "@/pages/DataStudio/model";
import {connect} from "umi";
import React, {useState, useEffect} from "react";
import {
createTaskDefinition,
getTaskMainInfos,
updateTaskDefinition
} from "@/pages/DataStudio/service";
import {CODE} from "@/components/Common/crud";
import TextArea from "antd/es/input/TextArea";
const DolphinPush = (props: any) => {
const {data, taskCur, handleDolphinModalVisible} = props;
const [options, setOptions] = useState([]);
const formRef = React.createRef<FormInstance>();
const [processCode, setProcessCode] = useState("");
const CheckboxGroup = Checkbox.Group;
const layout = {
labelCol: {span: 6},
wrapperCol: {span: 18},
};
useEffect(() => {
options.length = 0;
taskMainInfos();
setFormValue();
}, [taskCur])
//前置任务数据集合
const taskMainInfos = () => {
if (taskCur) {
const res = getTaskMainInfos(taskCur.task.id);
res.then((result) => {
if (result.code == CODE.SUCCESS) {
setOptions(result.datas.map((item: { taskName: any; taskCode: any; }) => ({
label: item.taskName,
value: item.taskCode
})
))
} else {
message.error(`获取海豚任务定义集合失败,原因:\n${result.msg}`);
}
})
}
};
//赋值数据
const setFormValue = () => {
//是否已有数据
if (data) {
// debugger
setProcessCode(data.processDefinitionCode)
setTimeoutFlagHidden(data.timeoutFlag === 'OPEN');
let tns = []
if (data.timeoutNotifyStrategy === "WARNFAILED") {
tns = ['WARN', 'FAILED']
} else {
// debugger
tns = data.timeoutNotifyStrategy ? data.timeoutNotifyStrategy.split(',') : []
}
// debugger
//前置任务勾选
let upstreamCodesTem = [];
for (let key in data.upstreamTaskMap) {
upstreamCodesTem.push(parseInt(key))
}
formRef.current.setFieldsValue({
upstreamCodes: upstreamCodesTem,
taskPriority: data.taskPriority,
failRetryTimes: data.failRetryTimes,
description: data.description,
failRetryInterval: data.failRetryInterval,
delayTime: data.delayTime,
timeout: data.timeout,
flag: data.flag === 'YES',
timeoutFlag: data.timeoutFlag === 'OPEN',
timeoutNotifyStrategy: tns
});
} else {
formRef.current.setFieldsValue({
flag: true,
taskPriority: 'MEDIUM',
timeoutFlag: false,
});
}
};
//表单提交,添加/更新海豚任务
const onFinish = (values: any) => {
// console.log(values);
values.flag === true ? values.flag = 'YES' : values.flag = 'NO';
values.upstreamCodes ? values.upstreamCodes = values.upstreamCodes.toString() : "";
values.processCode = processCode;
if (values.timeoutFlag === false) {
values.timeoutFlag = 'CLOSE'
values.timeoutNotifyStrategy = null;
values.timeout = 0;
} else {
values.timeoutFlag = 'OPEN'
values.timeout = 1;
if (values.timeoutNotifyStrategy && values.timeoutNotifyStrategy.length > 1) {
values.timeoutNotifyStrategy = "WARNFAILED";
} else if (values.timeoutNotifyStrategy && values.timeoutNotifyStrategy.length === 1) {
values.timeoutNotifyStrategy = values.timeoutNotifyStrategy[0]
} else {
message.error(`超时策略必须选一个`);
return
}
}
if (!data) {
const res = createTaskDefinition(taskCur.task.id, values.upstreamCodes, values);
res.then((result) => {
if (result.code == CODE.SUCCESS) {
handleDolphinModalVisible(false);
} else {
message.error(`创建任务失败,原因:\n${result.msg}`);
}
})
} else {
const res = updateTaskDefinition(data.processDefinitionCode, data.projectCode, data.code, values.upstreamCodes, values);
res.then((result) => {
if (result.code == CODE.SUCCESS) {
handleDolphinModalVisible(false);
} else {
message.error(`创建任务失败,原因:\n${result.msg}`);
}
})
}
};
const [timeoutFlagHidden, setTimeoutFlagHidden] = useState<boolean>(false);
function onSwitchChange(checked: boolean) {
setTimeoutFlagHidden(checked);
formRef.current.setFieldsValue({
timeout: 1
});
}
return (
<Form {...layout} ref={formRef} name="control-hooks" onFinish={onFinish}>
<Form.Item name={['upstreamCodes']} style={{marginBottom: 10}} label="前置任务">
<Select mode='multiple' style={{width: '100%'}} options={options} placeholder='选择前置任务'
maxTagCount='responsive'/>
</Form.Item>
<Form.Item name={['taskPriority']} style={{marginBottom: 10}} label="优先级">
<Select style={{width: 180}}>
<Option value="HIGH">HIGH</Option>
<Option value="HIGHEST">HIGHEST</Option>
<Option value="LOW">LOW</Option>
<Option value="LOWEST">LOWEST</Option>
<Option value="MEDIUM">MEDIUM</Option>
</Select>
</Form.Item>
<Form.Item name={['failRetryTimes']} style={{marginBottom: 10}} label="失败重试次数">
<InputNumber min={0} max={99} style={{width: 180}}/>
</Form.Item>
<Form.Item name={['failRetryInterval']} style={{marginBottom: 10}} label="失败重试间隔(分钟)">
<InputNumber min={0} style={{width: 180}}/>
</Form.Item>
<Form.Item name={['delayTime']} style={{marginBottom: 10}} label="延时执行时间(分钟)">
<InputNumber min={0} style={{width: 180}}/>
</Form.Item>
<Form.Item name={['timeoutFlag']} style={{marginBottom: 10}} label="超时告警" valuePropName="checked">
<Switch checkedChildren="OPEN" unCheckedChildren="CLOSE" onChange={onSwitchChange}/>
</Form.Item>
<Form.Item name={['timeoutNotifyStrategy']} style={{marginBottom: 10}} hidden={!timeoutFlagHidden} label="超时策略">
<CheckboxGroup>
<Row>
<Col span={12}>
<Checkbox value="WARN">超时警告</Checkbox>
</Col>
<Col span={12}>
<Checkbox value="FAILED">超时失败</Checkbox>
</Col>
</Row>
</CheckboxGroup>
</Form.Item>
<Form.Item name={['timeout']} style={{marginBottom: 10}} hidden={!timeoutFlagHidden} label="超时告警时长(分钟)">
<InputNumber min={1} value={30} style={{width: 180}}/>
</Form.Item>
<Form.Item name={['flag']} style={{marginBottom: 10}} label="运行标志" valuePropName="checked">
<Switch checkedChildren="YES" unCheckedChildren="NO"/>
</Form.Item>
<Form.Item name={['description']} style={{marginBottom: 10}} label="备注">
<TextArea rows={3} placeholder="备注信息" maxLength={250}/>
</Form.Item>
<Form.Item wrapperCol={{offset: 8, span: 16}}>
<Button type="primary" htmlType="submit">
保存
</Button>
</Form.Item>
</Form>
);
}
export default connect(({Studio}: { Studio: StateType }) => ({
current: Studio.current,
currentSession: Studio.currentSession,
}))(DolphinPush);
...@@ -24,7 +24,7 @@ import { ...@@ -24,7 +24,7 @@ import {
PauseCircleTwoTone, CarryOutTwoTone, DeleteTwoTone, PlayCircleTwoTone, CameraTwoTone, SnippetsTwoTone, PauseCircleTwoTone, CarryOutTwoTone, DeleteTwoTone, PlayCircleTwoTone, CameraTwoTone, SnippetsTwoTone,
FileAddTwoTone, FolderOpenTwoTone, SafetyCertificateTwoTone, SaveTwoTone, FlagTwoTone, CodeTwoTone, FileAddTwoTone, FolderOpenTwoTone, SafetyCertificateTwoTone, SaveTwoTone, FlagTwoTone, CodeTwoTone,
EnvironmentOutlined, SmileOutlined, RocketTwoTone, QuestionCircleTwoTone, MessageOutlined, ClusterOutlined EnvironmentOutlined, SmileOutlined, RocketTwoTone, QuestionCircleTwoTone, MessageOutlined, ClusterOutlined
, EditTwoTone, RestTwoTone, ShrinkOutlined, ApiTwoTone , EditTwoTone, RestTwoTone, ShrinkOutlined, ApiTwoTone, SendOutlined
} from "@ant-design/icons"; } from "@ant-design/icons";
import Space from "antd/es/space"; import Space from "antd/es/space";
import Divider from "antd/es/divider"; import Divider from "antd/es/divider";
...@@ -33,7 +33,7 @@ import Breadcrumb from "antd/es/breadcrumb/Breadcrumb"; ...@@ -33,7 +33,7 @@ import Breadcrumb from "antd/es/breadcrumb/Breadcrumb";
import {StateType} from "@/pages/DataStudio/model"; import {StateType} from "@/pages/DataStudio/model";
import {connect} from "umi"; import {connect} from "umi";
import {CODE, postDataArray} from "@/components/Common/crud"; import {CODE, postDataArray} from "@/components/Common/crud";
import {executeSql, getJobPlan} from "@/pages/DataStudio/service"; import {executeSql, getJobPlan, getTaskDefinition} from "@/pages/DataStudio/service";
import TaskAPI from "@/pages/API/TaskAPI"; import TaskAPI from "@/pages/API/TaskAPI";
import StudioHelp from "./StudioHelp"; import StudioHelp from "./StudioHelp";
import StudioGraph from "./StudioGraph"; import StudioGraph from "./StudioGraph";
...@@ -45,7 +45,7 @@ import { ...@@ -45,7 +45,7 @@ import {
showCluster, showCluster,
showTables showTables
} from "@/components/Studio/StudioEvent/DDL"; } from "@/components/Studio/StudioEvent/DDL";
import React, {useCallback, useEffect, useState} from "react"; import React, {useCallback, useEffect, useState, useRef} from "react";
import StudioExplain from "../StudioConsole/StudioExplain"; import StudioExplain from "../StudioConsole/StudioExplain";
import { import {
DIALECT, DIALECT,
...@@ -62,6 +62,7 @@ import SqlExport from "@/pages/DataStudio/SqlExport"; ...@@ -62,6 +62,7 @@ import SqlExport from "@/pages/DataStudio/SqlExport";
import {Dispatch} from "@@/plugin-dva/connect"; import {Dispatch} from "@@/plugin-dva/connect";
import StudioTabs from "@/components/Studio/StudioTabs"; import StudioTabs from "@/components/Studio/StudioTabs";
import {isDeletedTask, JOB_LIFE_CYCLE} from "@/components/Common/JobLifeCycle"; import {isDeletedTask, JOB_LIFE_CYCLE} from "@/components/Common/JobLifeCycle";
import DolphinPush from "@/components/Studio/StudioMenu/DolphinPush";
const menu = ( const menu = (
<Menu> <Menu>
...@@ -76,8 +77,10 @@ const StudioMenu = (props: any) => { ...@@ -76,8 +77,10 @@ const StudioMenu = (props: any) => {
const [modalVisible, handleModalVisible] = useState<boolean>(false); const [modalVisible, handleModalVisible] = useState<boolean>(false);
const [exportModalVisible, handleExportModalVisible] = useState<boolean>(false); const [exportModalVisible, handleExportModalVisible] = useState<boolean>(false);
const [graphModalVisible, handleGraphModalVisible] = useState<boolean>(false); const [graphModalVisible, handleGraphModalVisible] = useState<boolean>(false);
const [dolphinModalVisible, handleDolphinModalVisible] = useState<boolean>(false);
// const [editModalVisible, handleEditModalVisible] = useState<boolean>(false); // const [editModalVisible, handleEditModalVisible] = useState<boolean>(false);
const [graphData, setGraphData] = useState(); const [graphData, setGraphData] = useState();
const [dolphinData, setDolphinData] = useState();
const onKeyDown = useCallback((e) => { const onKeyDown = useCallback((e) => {
if (e.keyCode === 83 && (e.ctrlKey === true || e.metaKey)) { if (e.keyCode === 83 && (e.ctrlKey === true || e.metaKey)) {
...@@ -228,6 +231,20 @@ const StudioMenu = (props: any) => { ...@@ -228,6 +231,20 @@ const StudioMenu = (props: any) => {
}) })
}; };
//获取当前task关联的海豚数据
const viewDolphinCon = () => {
const res = getTaskDefinition(current.task.id);
res.then((result) => {
if (result.code == CODE.SUCCESS) {
setDolphinData(result.datas);
} else {
message.error(`获取海豚数据失败,原因:\n${result.msg}`);
setDolphinData(undefined);
}
handleDolphinModalVisible(true);
})
};
const buildGraphData = (data) => { const buildGraphData = (data) => {
let edges = []; let edges = [];
for (let i in data.nodes) { for (let i in data.nodes) {
...@@ -618,6 +635,15 @@ const StudioMenu = (props: any) => { ...@@ -618,6 +635,15 @@ const StudioMenu = (props: any) => {
/> />
</Tooltip> </Tooltip>
</>)} </>)}
{isShowSubmitBtn() && (<>
<Tooltip title="推送到海豚调度">
<Button
type="text" style={{color: '#248FFF'}}
icon={<SendOutlined/>}
onClick={viewDolphinCon}
/>
</Tooltip>
</>)}
{isShowCancelTaskBtn() && {isShowCancelTaskBtn() &&
<Tooltip title="停止"> <Tooltip title="停止">
<Button <Button
...@@ -715,6 +741,17 @@ const StudioMenu = (props: any) => { ...@@ -715,6 +741,17 @@ const StudioMenu = (props: any) => {
> >
<StudioGraph data={graphData}/> <StudioGraph data={graphData}/>
</Modal> </Modal>
<Modal
width={700}
bodyStyle={{padding: '32px 40px 48px'}}
destroyOnClose
title="推送到海豚调度"
visible={dolphinModalVisible}
onCancel={() => handleDolphinModalVisible(false)}
footer={[]}
>
<DolphinPush data={dolphinData} taskCur={current} handleDolphinModalVisible={handleDolphinModalVisible}/>
</Modal>
{current?.task ? {current?.task ?
<ModalForm <ModalForm
title={`${current.task.alias} 的 ${current.task.dialect} 导出`} title={`${current.task.alias} 的 ${current.task.dialect} 导出`}
......
...@@ -110,3 +110,53 @@ export async function getMSSchemaInfo(params: StudioMetaStoreParam) { ...@@ -110,3 +110,53 @@ export async function getMSSchemaInfo(params: StudioMetaStoreParam) {
}, },
}); });
} }
//海豚 获取任务定义
export async function getTaskDefinition(dinkyTaskId: string) {
return request<API.Result>('/api/scheduler/task', {
method: 'GET',
params: {
dinkyTaskId,
},
});
}
//海豚 获取任务定义集合
export async function getTaskMainInfos(dinkyTaskId: string) {
return request<API.Result>('/api/scheduler/upstream/tasks', {
method: 'GET',
params: {
dinkyTaskId,
},
});
}
//海豚 创建任务定义
export async function createTaskDefinition(dinkyTaskId: string, upstreamCodes: string, params: object) {
return request<API.Result>('/api/scheduler/task', {
method: 'POST',
params: {
dinkyTaskId,
upstreamCodes
},
data: {
...params,
},
});
}
//海豚 更新任务定义
export async function updateTaskDefinition(processCode: string, projectCode: string, taskCode: string, upstreamCodes: string, params: object) {
return request<API.Result>('/api/scheduler/task', {
method: 'PUT',
params: {
processCode,
projectCode,
taskCode,
upstreamCodes
},
data: {
...params,
},
});
}
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
<module>dlink-extends</module> <module>dlink-extends</module>
<module>dlink-alert</module> <module>dlink-alert</module>
<module>dlink-daemon</module> <module>dlink-daemon</module>
<module>dlink-scheduler</module>
<module>dlink-core</module> <module>dlink-core</module>
<module>dlink-app</module> <module>dlink-app</module>
<module>dlink-web</module> <module>dlink-web</module>
...@@ -447,6 +448,11 @@ ...@@ -447,6 +448,11 @@
<artifactId>javax.mail</artifactId> <artifactId>javax.mail</artifactId>
<version>${javax.mail}</version> <version>${javax.mail}</version>
</dependency> </dependency>
<dependency>
<groupId>com.dlink</groupId>
<artifactId>dlink-scheduler</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment