Browse Source

Merge remote-tracking branch 'upstream/dev-20190415' into dev-20190415

pull/2/head
dailidong 5 years ago
parent
commit
0022392715
  1. 6
      docs/zh_CN/前端部署文档.md
  2. 22
      docs/zh_CN/后端部署文档.md
  3. 2
      escheduler-alert/pom.xml
  4. 2
      escheduler-api/pom.xml
  5. 5
      escheduler-api/src/main/java/cn/escheduler/api/controller/ExecutorController.java
  6. 6
      escheduler-api/src/main/java/cn/escheduler/api/service/DataAnalysisService.java
  7. 19
      escheduler-api/src/main/java/cn/escheduler/api/service/ExecutorService.java
  8. 10
      escheduler-api/src/main/java/cn/escheduler/api/service/ProcessDefinitionService.java
  9. 19
      escheduler-api/src/main/java/cn/escheduler/api/service/ProcessInstanceService.java
  10. 2
      escheduler-api/src/main/java/cn/escheduler/api/service/TenantService.java
  11. 42
      escheduler-api/src/test/java/cn/escheduler/api/HttpClientTest.java
  12. 20
      escheduler-api/src/test/java/cn/escheduler/api/controller/ExecutorControllerTest.java
  13. 2
      escheduler-common/pom.xml
  14. 5
      escheduler-common/src/main/java/cn/escheduler/common/Constants.java
  15. 27
      escheduler-common/src/main/java/cn/escheduler/common/task/sql/SqlParameters.java
  16. 2
      escheduler-dao/pom.xml
  17. 54
      escheduler-dao/readme.txt
  18. 35
      escheduler-dao/src/main/java/cn/escheduler/dao/AlertDao.java
  19. 1
      escheduler-dao/src/main/java/cn/escheduler/dao/ProcessDao.java
  20. 4
      escheduler-dao/src/main/java/cn/escheduler/dao/datasource/ConnectionFactory.java
  21. 5
      escheduler-dao/src/main/java/cn/escheduler/dao/mapper/ProcessDefinitionMapper.java
  22. 4
      escheduler-dao/src/main/java/cn/escheduler/dao/mapper/ProcessDefinitionMapperProvider.java
  23. 11
      escheduler-dao/src/main/java/cn/escheduler/dao/mapper/ProcessInstanceMapper.java
  24. 2
      escheduler-dao/src/main/java/cn/escheduler/dao/mapper/ProcessInstanceMapperProvider.java
  25. 10
      escheduler-dao/src/main/java/cn/escheduler/dao/model/ProcessData.java
  26. 15
      escheduler-dao/src/main/java/cn/escheduler/dao/model/ProcessDefinition.java
  27. 15
      escheduler-dao/src/main/java/cn/escheduler/dao/model/ProcessInstance.java
  28. 31
      escheduler-dao/src/main/java/cn/escheduler/dao/upgrade/EschedulerManager.java
  29. 57
      escheduler-dao/src/main/java/cn/escheduler/dao/upgrade/UpgradeDao.java
  30. 1
      escheduler-dao/src/main/java/cn/escheduler/dao/upgrade/shell/CreateEscheduler.java
  31. 2
      escheduler-dao/src/main/java/cn/escheduler/dao/upgrade/shell/UpgradeEscheduler.java
  32. 6
      escheduler-dao/src/main/resources/dao/data_source.properties
  33. 2
      escheduler-rpc/pom.xml
  34. 2
      escheduler-server/pom.xml
  35. 32
      escheduler-server/src/main/java/cn/escheduler/server/master/runner/MasterExecThread.java
  36. 58
      escheduler-server/src/main/java/cn/escheduler/server/utils/AlertManager.java
  37. 7
      escheduler-server/src/main/java/cn/escheduler/server/worker/task/sql/SqlTask.java
  38. 4
      escheduler-server/src/test/java/cn/escheduler/server/master/AlertManagerTest.java
  39. 14
      escheduler-ui/dist/css/home/index.0212fa5.css
  40. 14
      escheduler-ui/dist/css/login/index.6083d91.css
  41. 4
      escheduler-ui/dist/index.html
  42. 2
      escheduler-ui/dist/js/0.8ca091c.js
  43. 1
      escheduler-ui/dist/js/0.8ca091c.js.map
  44. 2
      escheduler-ui/dist/js/0.bf0a1e2.js
  45. 1
      escheduler-ui/dist/js/0.bf0a1e2.js.map
  46. 2
      escheduler-ui/dist/js/1.3ff7adc.js
  47. 1
      escheduler-ui/dist/js/1.3ff7adc.js.map
  48. 2
      escheduler-ui/dist/js/1.bdb0cc7.js
  49. 1
      escheduler-ui/dist/js/1.bdb0cc7.js.map
  50. 2
      escheduler-ui/dist/js/10.73c0240.js
  51. 1
      escheduler-ui/dist/js/10.73c0240.js.map
  52. 2
      escheduler-ui/dist/js/10.90da74f.js
  53. 1
      escheduler-ui/dist/js/10.90da74f.js.map
  54. 2
      escheduler-ui/dist/js/11.078cbab.js
  55. 1
      escheduler-ui/dist/js/11.078cbab.js.map
  56. 2
      escheduler-ui/dist/js/11.ca8ac79.js
  57. 1
      escheduler-ui/dist/js/11.ca8ac79.js.map
  58. 2
      escheduler-ui/dist/js/12.864692a.js
  59. 1
      escheduler-ui/dist/js/12.864692a.js.map
  60. 2
      escheduler-ui/dist/js/12.b6fb265.js
  61. 1
      escheduler-ui/dist/js/12.b6fb265.js.map
  62. 2
      escheduler-ui/dist/js/13.7e1b794.js
  63. 1
      escheduler-ui/dist/js/13.7e1b794.js.map
  64. 2
      escheduler-ui/dist/js/13.a8f5ee9.js
  65. 1
      escheduler-ui/dist/js/13.a8f5ee9.js.map
  66. 2
      escheduler-ui/dist/js/14.10001b2.js
  67. 1
      escheduler-ui/dist/js/14.10001b2.js.map
  68. 2
      escheduler-ui/dist/js/14.22fa282.js
  69. 1
      escheduler-ui/dist/js/14.22fa282.js.map
  70. 2
      escheduler-ui/dist/js/15.9119d76.js
  71. 1
      escheduler-ui/dist/js/15.9119d76.js.map
  72. 2
      escheduler-ui/dist/js/15.eea1d19.js
  73. 1
      escheduler-ui/dist/js/15.eea1d19.js.map
  74. 2
      escheduler-ui/dist/js/16.648c64b.js
  75. 1
      escheduler-ui/dist/js/16.648c64b.js.map
  76. 2
      escheduler-ui/dist/js/16.fd660eb.js
  77. 1
      escheduler-ui/dist/js/16.fd660eb.js.map
  78. 2
      escheduler-ui/dist/js/17.4aef6ba.js
  79. 1
      escheduler-ui/dist/js/17.4aef6ba.js.map
  80. 9
      escheduler-ui/dist/js/17.6761755.js
  81. 1
      escheduler-ui/dist/js/17.6761755.js.map
  82. 2
      escheduler-ui/dist/js/18.3bc2e58.js
  83. 1
      escheduler-ui/dist/js/18.3bc2e58.js.map
  84. 2
      escheduler-ui/dist/js/18.b14d7b0.js
  85. 1
      escheduler-ui/dist/js/18.b14d7b0.js.map
  86. 2
      escheduler-ui/dist/js/19.35e5748.js
  87. 1
      escheduler-ui/dist/js/19.35e5748.js.map
  88. 2
      escheduler-ui/dist/js/19.5ce986e.js
  89. 1
      escheduler-ui/dist/js/19.5ce986e.js.map
  90. 2
      escheduler-ui/dist/js/2.3b16c4b.js
  91. 1
      escheduler-ui/dist/js/2.3b16c4b.js.map
  92. 2
      escheduler-ui/dist/js/2.d6885e7.js
  93. 1
      escheduler-ui/dist/js/2.d6885e7.js.map
  94. 2
      escheduler-ui/dist/js/20.15ed1ee.js
  95. 1
      escheduler-ui/dist/js/20.15ed1ee.js.map
  96. 2
      escheduler-ui/dist/js/20.65383c2.js
  97. 1
      escheduler-ui/dist/js/20.65383c2.js.map
  98. 2
      escheduler-ui/dist/js/21.c62cd9a.js
  99. 1
      escheduler-ui/dist/js/21.c62cd9a.js.map
  100. 2
      escheduler-ui/dist/js/21.cc0a847.js
  101. Some files were not shown because too many files have changed in this diff Show More

6
docs/zh_CN/前端部署文档.md

@ -5,9 +5,9 @@
## 1、准备工作
#### 下载安装包
目前最新安装包版本是1.0.1,下载地址: [码云下载](https://gitee.com/easyscheduler/EasyScheduler/attach_files/)
目前最新安装包版本是1.0.2,下载地址: [码云下载](https://gitee.com/easyscheduler/EasyScheduler/attach_files/)
下载escheduler-ui-1.0.1.tar.gz后,解压后会产生dist目录,进入dist目录
下载escheduler-ui-1.0.2.tar.gz后,解压后会产生dist目录,进入dist目录
> cd dist
@ -98,4 +98,4 @@ systemctl restart nginx
```
# 更改上传大小
client_max_body_size 1024m
```
```

22
docs/zh_CN/后端部署文档.md

@ -4,7 +4,7 @@
## 1、准备工作
目前最新安装包版本是1.0.1,下载地址: [码云下载](https://gitee.com/easyscheduler/EasyScheduler/attach_files/) ,下载escheduler-backend-1.0.1.tar.gz后,解压后会产生escheduler-backend-1.0.1目录(后面简称escheduler-backend)
目前最新安装包版本是1.0.2,下载地址: [码云下载](https://gitee.com/easyscheduler/EasyScheduler/attach_files/) ,下载escheduler-backend-1.0.2.tar.gz(后端简称escheduler-backend),escheduler-ui-1.0.2.tar.gz(前端简称escheduler-ui)
#### 准备一: 基础软件安装(必装项请自行安装)
@ -57,7 +57,7 @@ escheduler ALL=(ALL) NOPASSWD: NOPASSWD: ALL
flush privileges;
```
* 创建表和导入基础数据
* 1.0.0和1.0.1版本创建表和导入基础数据
说明:在escheduler-backend/sql/escheduler.sql和quartz.sql
```sql
@ -66,6 +66,12 @@ escheduler ALL=(ALL) NOPASSWD: NOPASSWD: ALL
mysql -h {host} -u {user} -p{password} -D {db} < quartz.sql
```
* 1.0.2版本创建表和导入基础数据
```
sh ./script/create_escheduler.sh
```
#### 准备五: 修改部署目录权限及运行参数
我们先来大体了解下解压后escheduler-backend目录下的文件(夹)的作用
@ -83,7 +89,7 @@ install.sh : 一键部署脚本
`sudo chown -R deployUser:deployUser escheduler-backend`
- 修改conf/env/目录下的`escheduler_env.py`, `.escheduler_env.sh` 两个文件中的环境变量
- 修改conf/env/目录下的 `.escheduler_env.sh` 环境变量
- 修改部署参数(根据自己服务器及业务情况):
@ -130,7 +136,7 @@ install.sh : 一键部署脚本
### 2.2 编译源码来部署
将源码包release版本1.0.1下载后,解压进入根目录
将源码包release版本1.0.2下载后,解压进入根目录
* 执行编译命令:
@ -185,4 +191,10 @@ sh ./bin/escheduler-daemon.sh stop logger-server
```
sh ./bin/escheduler-daemon.sh start alert-server
sh ./bin/escheduler-daemon.sh stop alert-server
```
```
## 3、数据库升级
数据库升级是在1.0.2版本增加的功能,执行以下命令即可自动升级数据库
```
sh ./script/upgrade_escheduler.sh
```

2
escheduler-alert/pom.xml

@ -4,7 +4,7 @@
<parent>
<groupId>cn.analysys</groupId>
<artifactId>escheduler</artifactId>
<version>1.0.1-SNAPSHOT</version>
<version>1.0.2-SNAPSHOT</version>
</parent>
<artifactId>escheduler-alert</artifactId>
<packaging>jar</packaging>

2
escheduler-api/pom.xml

@ -3,7 +3,7 @@
<parent>
<groupId>cn.analysys</groupId>
<artifactId>escheduler</artifactId>
<version>1.0.1-SNAPSHOT</version>
<version>1.0.2-SNAPSHOT</version>
</parent>
<artifactId>escheduler-api</artifactId>
<packaging>jar</packaging>

5
escheduler-api/src/main/java/cn/escheduler/api/controller/ExecutorController.java

@ -149,10 +149,11 @@ public class ExecutorController extends BaseController {
@GetMapping(value = "/get-receiver-cc")
@ResponseStatus(HttpStatus.OK)
public Result getReceiverCc(@RequestAttribute(value = Constants.SESSION_USER) User loginUser,
@RequestParam(value = "processDefinitionId") int processDefinitionId){
@RequestParam(value = "processDefinitionId",required = false) Integer processDefinitionId,
@RequestParam(value = "processInstanceId",required = false) Integer processInstanceId) {
logger.info("login user {}, get process definition receiver and cc", loginUser.getUserName());
try {
Map<String, Object> result = execService.getReceiverCc(processDefinitionId);
Map<String, Object> result = execService.getReceiverCc(processDefinitionId,processInstanceId);
return returnDataList(result);
} catch (Exception e) {
logger.error(QUERY_RECIPIENTS_AND_COPYERS_BY_PROCESS_DEFINITION_ERROR.getMsg(),e);

6
escheduler-api/src/main/java/cn/escheduler/api/service/DataAnalysisService.java

@ -357,7 +357,7 @@ public class DataAnalysisService {
i = 0;
for (String taskKillStr : tasksKillList){
if (StringUtils.isNotEmpty(taskKillStr)){
String[] splits = taskKillStr.split("_");
String[] splits = taskKillStr.split("-");
if (splits.length == 2){
tasksKillIds[i++]=Integer.parseInt(splits[1]);
}
@ -370,8 +370,8 @@ public class DataAnalysisService {
taskQueueCount = taskInstanceMapper.countTask(loginUser.getId(),loginUser.getUserType(),projectId, tasksQueueIds);
}
if (tasksQueueIds.length != 0){
taskKillCount = taskInstanceMapper.countTask(loginUser.getId(),loginUser.getUserType(),projectId, tasksQueueIds);
if (tasksKillIds.length != 0){
taskKillCount = taskInstanceMapper.countTask(loginUser.getId(),loginUser.getUserType(),projectId, tasksKillIds);
}

19
escheduler-api/src/main/java/cn/escheduler/api/service/ExecutorService.java

@ -361,18 +361,29 @@ public class ExecutorService extends BaseService{
}
/**
* query recipients and copyers by process definition id
* query recipients and copyers by process definition id or processInstanceId
*
* @param processDefineId
* @return
*/
public Map<String, Object> getReceiverCc(int processDefineId) {
public Map<String, Object> getReceiverCc(Integer processDefineId,Integer processInstanceId) {
Map<String, Object> result = new HashMap<>();
logger.info("processInstanceId {}",processInstanceId);
if(processDefineId == null && processInstanceId == null){
throw new RuntimeException("You must set values for parameters processDefineId or processInstanceId");
}
if(processDefineId == null && processInstanceId != null) {
ProcessInstance processInstance = processInstanceMapper.queryById(processInstanceId);
if (processInstance == null) {
throw new RuntimeException("processInstanceId is not exists");
}
processDefineId = processInstance.getProcessDefinitionId();
}
ProcessDefinition processDefinition = processDefinitionMapper.queryByDefineId(processDefineId);
if (processDefinition == null){
throw new RuntimeException("processDefineId is not exists");
throw new RuntimeException(String.format("processDefineId %d is not exists",processDefineId));
}
String receivers = processDefinition.getReceivers();
String receiversCc = processDefinition.getReceiversCc();
Map<String,String> dataMap = new HashMap<>();

10
escheduler-api/src/main/java/cn/escheduler/api/service/ProcessDefinitionService.java

@ -114,7 +114,7 @@ public class ProcessDefinitionService extends BaseDAGService {
ProcessData processData = JSONUtils.parseObject(processDefinitionJson, ProcessData.class);
Map<String, Object> checkProcessJson = checkProcessNodeList(processData, processDefinitionJson);
if (checkProcessJson.get(Constants.STATUS) != Status.SUCCESS) {
return result;
return checkProcessJson;
}
processDefine.setName(name);
@ -125,6 +125,7 @@ public class ProcessDefinitionService extends BaseDAGService {
processDefine.setDesc(desc);
processDefine.setLocations(locations);
processDefine.setConnects(connects);
processDefine.setTimeout(processData.getTimeout());
//custom global params
List<Property> globalParamsList = processData.getGlobalParams();
@ -262,7 +263,7 @@ public class ProcessDefinitionService extends BaseDAGService {
ProcessData processData = JSONUtils.parseObject(processDefinitionJson, ProcessData.class);
Map<String, Object> checkProcessJson = checkProcessNodeList(processData, processDefinitionJson);
if ((checkProcessJson.get(Constants.STATUS) != Status.SUCCESS)) {
return result;
return checkProcessJson;
}
ProcessDefinition processDefinition = processDao.findProcessDefineById(id);
if (processDefinition == null) {
@ -288,6 +289,7 @@ public class ProcessDefinitionService extends BaseDAGService {
processDefine.setDesc(desc);
processDefine.setLocations(locations);
processDefine.setConnects(connects);
processDefine.setTimeout(processData.getTimeout());
//custom global params
List<Property> globalParamsList = processData.getGlobalParams();
@ -717,7 +719,9 @@ public class ProcessDefinitionService extends BaseDAGService {
List<String> preTasks = JSONUtils.toList(taskNodeResponse.getPreTasks(),String.class);
if (CollectionUtils.isNotEmpty(preTasks)) {
for (String preTask : preTasks) {
graph.addEdge(preTask, taskNodeResponse.getName());
if (!graph.addEdge(preTask, taskNodeResponse.getName())) {
return true;
}
}
}
}

19
escheduler-api/src/main/java/cn/escheduler/api/service/ProcessInstanceService.java

@ -346,7 +346,8 @@ public class ProcessInstanceService extends BaseDAGService {
//check process instance status
if (!processInstance.getState().typeIsFinished()) {
putMsg(result, Status.PROCESS_INSTANCE_STATE_OPERATION_ERROR, "update");
putMsg(result, Status.PROCESS_INSTANCE_STATE_OPERATION_ERROR,
processInstance.getName(), processInstance.getState().toString(), "update");
return result;
}
Date schedule = null;
@ -355,8 +356,12 @@ public class ProcessInstanceService extends BaseDAGService {
} else {
schedule = processInstance.getScheduleTime();
}
processInstance.setScheduleTime(schedule);
processInstance.setLocations(locations);
processInstance.setConnects(connects);
String globalParams = null;
String originDefParams = null;
int timeout = processInstance.getTimeout();
if (StringUtils.isNotEmpty(processInstanceJson)) {
ProcessData processData = JSONUtils.parseObject(processInstanceJson, ProcessData.class);
//check workflow json is valid
@ -370,9 +375,14 @@ public class ProcessInstanceService extends BaseDAGService {
Map<String, String> globalParamMap = globalParamList.stream().collect(Collectors.toMap(Property::getProp, Property::getValue));
globalParams = ParameterUtils.curingGlobalParams(globalParamMap, globalParamList,
processInstance.getCmdTypeIfComplement(), schedule);
}
int update = processDao.updateProcessInstance(processInstanceId, processInstanceJson,
globalParams, schedule, flag, locations, connects);
timeout = processData.getTimeout();
processInstance.setTimeout(timeout);
processInstance.setProcessInstanceJson(processInstanceJson);
processInstance.setGlobalParams(globalParams);
}
// int update = processDao.updateProcessInstance(processInstanceId, processInstanceJson,
// globalParams, schedule, flag, locations, connects);
int update = processDao.updateProcessInstance(processInstance);
int updateDefine = 1;
if (syncDefine && StringUtils.isNotEmpty(processInstanceJson)) {
ProcessDefinition processDefinition = processDao.findProcessDefineById(processInstance.getProcessDefinitionId());
@ -380,6 +390,7 @@ public class ProcessInstanceService extends BaseDAGService {
processDefinition.setGlobalParams(originDefParams);
processDefinition.setLocations(locations);
processDefinition.setConnects(connects);
processDefinition.setTimeout(timeout);
updateDefine = processDefineMapper.update(processDefinition);
}
if (update > 0 && updateDefine > 0) {

2
escheduler-api/src/main/java/cn/escheduler/api/service/TenantService.java

@ -80,7 +80,7 @@ public class TenantService extends BaseService{
Tenant tenant = new Tenant();
Date now = new Date();
if (!tenantCode.matches("^[0-9a-zA-Z_.]{1,}$") || tenantCode.startsWith("-")){
if (!tenantCode.matches("^[0-9a-zA-Z_.-]{1,}$") || tenantCode.startsWith("-") || tenantCode.startsWith(".")){
putMsg(result, Status.VERIFY_TENANT_CODE_ERROR);
return result;
}

42
escheduler-api/src/test/java/cn/escheduler/api/HttpClientTest.java

@ -34,26 +34,19 @@ import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HttpClientTest {
private static final Logger logger = LoggerFactory.getLogger(HttpClientTest.class);
public static void main(String[] args) throws Exception {
// doGETParamPathVariableAndChinese();
// doGETParam();
// doPOSTParam();
String md5 = EncryptionUtils.getMd5(String.valueOf(System.currentTimeMillis()) + "张三");
System.out.println(md5);
System.out.println(md5.length());
}
public static void doPOSTParam()throws Exception{
// create Httpclient
@Test
public void doPOSTParam()throws Exception{
// create HttpClient
CloseableHttpClient httpclient = HttpClients.createDefault();
// 创建http POST请求
// create http post request
HttpPost httpPost = new HttpPost("http://127.0.0.1:12345/escheduler/projects/create");
httpPost.setHeader("token", "123");
// set parameters
@ -83,23 +76,24 @@ public class HttpClientTest {
}
/**
*
* do get param path variables chinese
* @throws Exception
*/
public static void doGETParamPathVariableAndChinese()throws Exception{
@Test
public void doGETParamPathVariableAndChinese()throws Exception{
// create HttpClient
CloseableHttpClient httpclient = HttpClients.createDefault();
List<NameValuePair> parameters = new ArrayList<NameValuePair>();
// parameters.add(new BasicNameValuePair("pageSize", "10"));
// parameters.add(new BasicNameValuePair("pageSize", "10"));
// define the parameters of the request
URI uri = new URIBuilder("http://127.0.0.1:12345/escheduler/projects/%E5%85%A8%E9%83%A8%E6%B5%81%E7%A8%8B%E6%B5%8B%E8%AF%95/process/list")
URI uri = new URIBuilder("http://192.168.220.247:12345/escheduler/projects/%E5%85%A8%E9%83%A8%E6%B5%81%E7%A8%8B%E6%B5%8B%E8%AF%95/process/list")
.build();
// create http GET request
HttpGet httpGet = new HttpGet(uri);
httpGet.setHeader("token","123");
httpGet.setHeader("token","10f5625a2a1cbf9aa710653796c5d764");
//response object
CloseableHttpResponse response = null;
try {
@ -122,23 +116,27 @@ public class HttpClientTest {
/**
*
* do get param
* @throws Exception
*/
public static void doGETParam()throws Exception{
@Test
public void doGETParam()throws Exception{
// create HttpClient
CloseableHttpClient httpclient = HttpClients.createDefault();
List<NameValuePair> parameters = new ArrayList<NameValuePair>();
parameters.add(new BasicNameValuePair("processInstanceId", "41415"));
parameters.add(new BasicNameValuePair("startDate", "2018-04-22 19:30:08"));
parameters.add(new BasicNameValuePair("endDate", "2028-04-22 19:30:08"));
parameters.add(new BasicNameValuePair("projectId", "0"));
// define the parameters of the request
URI uri = new URIBuilder("http://127.0.0.1:12345/escheduler/projects/%E5%85%A8%E9%83%A8%E6%B5%81%E7%A8%8B%E6%B5%8B%E8%AF%95/instance/view-variables")
URI uri = new URIBuilder("http://192.168.220.247:12345/escheduler/projects/analysis/queue-count")
.setParameters(parameters)
.build();
// create http GET request
HttpGet httpGet = new HttpGet(uri);
httpGet.setHeader("token","123");
httpGet.setHeader("token","2aef24c052c212fab9eec78848c2258b");
//response object
CloseableHttpResponse response = null;
try {

20
escheduler-api/src/test/java/cn/escheduler/api/controller/ExecutorControllerTest.java

@ -32,8 +32,11 @@ import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ -66,4 +69,21 @@ public class ExecutorControllerTest {
Assert.assertEquals(Status.SUCCESS.getCode(),result.getCode().intValue());
logger.info(mvcResult.getResponse().getContentAsString());
}
@Test
public void getReceiverCc() throws Exception {
MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>();
//paramsMap.add("processDefinitionId","4");
paramsMap.add("processInstanceId","13");
//paramsMap.add("processInstanceId","13");
MvcResult mvcResult = mockMvc.perform(get("/projects/{projectName}/executors/get-receiver-cc","li_sql_test")
.header("sessionId", "e79b3353-e227-4680-88c0-544194e64025")
.params(paramsMap))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
.andReturn();
Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class);
Assert.assertEquals(Status.SUCCESS.getCode(),result.getCode().intValue());
logger.info(mvcResult.getResponse().getContentAsString());
}
}

2
escheduler-common/pom.xml

@ -4,7 +4,7 @@
<parent>
<artifactId>escheduler</artifactId>
<groupId>cn.analysys</groupId>
<version>1.0.1-SNAPSHOT</version>
<version>1.0.2-SNAPSHOT</version>
</parent>
<artifactId>escheduler-common</artifactId>
<name>escheduler-common</name>

5
escheduler-common/src/main/java/cn/escheduler/common/Constants.java

@ -331,6 +331,11 @@ public final class Constants {
*/
public static final int MAX_TASK_TIMEOUT = 24 * 3600;
/**
* max task timeout
*/
public static final int MAX_PROCESS_TIMEOUT = Integer.MAX_VALUE;
/**
* heartbeat threads number

27
escheduler-common/src/main/java/cn/escheduler/common/task/sql/SqlParameters.java

@ -65,6 +65,16 @@ public class SqlParameters extends AbstractParameters {
*/
private String connParams;
/**
* receivers
*/
private String receivers;
/**
* receivers cc
*/
private String receiversCc;
public String getType() {
return type;
}
@ -121,6 +131,21 @@ public class SqlParameters extends AbstractParameters {
this.connParams = connParams;
}
public String getReceivers() {
return receivers;
}
public void setReceivers(String receivers) {
this.receivers = receivers;
}
public String getReceiversCc() {
return receiversCc;
}
public void setReceiversCc(String receiversCc) {
this.receiversCc = receiversCc;
}
@Override
public boolean checkParameters() {
@ -142,6 +167,8 @@ public class SqlParameters extends AbstractParameters {
", udfs='" + udfs + '\'' +
", showType='" + showType + '\'' +
", connParams='" + connParams + '\'' +
", receivers='" + receivers + '\'' +
", receiversCc='" + receiversCc + '\'' +
'}';
}
}

2
escheduler-dao/pom.xml

@ -4,7 +4,7 @@
<parent>
<groupId>cn.analysys</groupId>
<artifactId>escheduler</artifactId>
<version>1.0.1-SNAPSHOT</version>
<version>1.0.2-SNAPSHOT</version>
</parent>
<artifactId>escheduler-dao</artifactId>
<name>escheduler-dao</name>

54
escheduler-dao/readme.txt

@ -1,54 +0,0 @@
-- 用户指定队列
alter table t_escheduler_user add queue varchar(64);
-- 访问token
CREATE TABLE `t_escheduler_access_token` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_id` int(11) DEFAULT NULL COMMENT '用户id',
`token` varchar(64) DEFAULT NULL COMMENT 'token令牌',
`expire_time` datetime DEFAULT NULL COMMENT 'token有效结束时间',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
CREATE TABLE `t_escheduler_error_command` (
`id` int(11) NOT NULL COMMENT '主键',
`command_type` tinyint(4) NULL DEFAULT NULL COMMENT '命令类型:0 启动工作流,1 从当前节点开始执行,2 恢复被容错的工作流,3 恢复暂停流程,4 从失败节点开始执行,5 补数,6 调度,7 重跑,8 暂停,9 停止,10 恢复等待线程',
`executor_id` int(11) NULL DEFAULT NULL COMMENT '命令执行者',
`process_definition_id` int(11) NULL DEFAULT NULL COMMENT '流程定义id',
`command_param` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '命令的参数(json格式)',
`task_depend_type` tinyint(4) NULL DEFAULT NULL COMMENT '节点依赖类型',
`failure_strategy` tinyint(4) NULL DEFAULT 0 COMMENT '失败策略:0结束,1继续',
`warning_type` tinyint(4) NULL DEFAULT 0 COMMENT '告警类型',
`warning_group_id` int(11) NULL DEFAULT NULL COMMENT '告警组',
`schedule_time` datetime(0) NULL DEFAULT NULL COMMENT '预期运行时间',
`start_time` datetime(0) NULL DEFAULT NULL COMMENT '开始时间',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
`dependence` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '依赖字段',
`process_instance_priority` int(11) NULL DEFAULT NULL COMMENT '流程实例优先级:0 Highest,1 High,2 Medium,3 Low,4 Lowest',
`message` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '执行信息',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
CREATE TABLE `t_escheduler_worker_group` (
`id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` varchar(256) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL COMMENT '组名称',
`ip_list` varchar(256) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL COMMENT 'worker地址列表',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
ALTER TABLE `t_escheduler_task_instance`
ADD COLUMN `worker_group_id` int(11) NULL DEFAULT -1 COMMENT '任务指定运行的worker分组' AFTER `task_instance_priority`;
ALTER TABLE `t_escheduler_command`
ADD COLUMN `worker_group_id` int(11) NULL DEFAULT -1 COMMENT '任务指定运行的worker分组' NULL AFTER `process_instance_priority`;
ALTER TABLE `t_escheduler_error_command`
ADD COLUMN `worker_group_id` int(11) NULL DEFAULT -1 COMMENT '任务指定运行的worker分组' NULL AFTER `process_instance_priority`;
ALTER TABLE `t_escheduler_schedules`
ADD COLUMN `worker_group_id` int(11) NULL DEFAULT -1 COMMENT '任务指定运行的worker分组' NULL AFTER `process_instance_priority`;

35
escheduler-dao/src/main/java/cn/escheduler/dao/AlertDao.java

@ -23,6 +23,8 @@ import cn.escheduler.dao.datasource.ConnectionFactory;
import cn.escheduler.dao.mapper.AlertMapper;
import cn.escheduler.dao.mapper.UserAlertGroupMapper;
import cn.escheduler.dao.model.Alert;
import cn.escheduler.dao.model.ProcessDefinition;
import cn.escheduler.dao.model.ProcessInstance;
import cn.escheduler.dao.model.User;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
@ -83,8 +85,9 @@ public class AlertDao extends AbstractBaseDao {
*/
public void sendServerStopedAlert(int alertgroupId,String host,String serverType){
Alert alert = new Alert();
String content = String.format("[{'type':'%s','host':'%s','event':'服务挂掉','警告级别':'严重'}]",serverType,host);
alert.setTitle("容错告警");
String content = String.format("[{'type':'%s','host':'%s','event':'server down','warning level':'serious'}]",
serverType, host);
alert.setTitle("Fault tolerance warning");
alert.setShowType(ShowType.TABLE);
alert.setContent(content);
alert.setAlertType(AlertType.EMAIL);
@ -94,6 +97,34 @@ public class AlertDao extends AbstractBaseDao {
alertMapper.insert(alert);
}
/**
* process time out alert
* @param processInstance
* @param processDefinition
*/
public void sendProcessTimeoutAlert(ProcessInstance processInstance, ProcessDefinition processDefinition){
int alertgroupId = processInstance.getWarningGroupId();
String receivers = processDefinition.getReceivers();
String receiversCc = processDefinition.getReceiversCc();
Alert alert = new Alert();
String content = String.format("[{'id':'%d','name':'%s','event':'timeout','warnLevel':'middle'}]",
processInstance.getId(), processInstance.getName());
alert.setTitle("Process Timeout Warn");
alert.setShowType(ShowType.TABLE);
alert.setContent(content);
alert.setAlertType(AlertType.EMAIL);
alert.setAlertGroupId(alertgroupId);
if (StringUtils.isNotEmpty(receivers)) {
alert.setReceivers(receivers);
}
if (StringUtils.isNotEmpty(receiversCc)) {
alert.setReceiversCc(receiversCc);
}
alert.setCreateTime(new Date());
alert.setUpdateTime(new Date());
alertMapper.insert(alert);
}
/**
* task timeout warn
*/

1
escheduler-dao/src/main/java/cn/escheduler/dao/ProcessDao.java

@ -482,6 +482,7 @@ public class ProcessDao extends AbstractBaseDao {
// set process instance priority
processInstance.setProcessInstancePriority(command.getProcessInstancePriority());
processInstance.setWorkerGroupId(command.getWorkerGroupId());
processInstance.setTimeout(processDefinition.getTimeout());
return processInstance;
}

4
escheduler-dao/src/main/java/cn/escheduler/dao/datasource/ConnectionFactory.java

@ -63,14 +63,14 @@ public class ConnectionFactory {
druidDataSource.setTestOnReturn(getBoolean(Constants.SPRING_DATASOURCE_TEST_ON_RETURN));
druidDataSource.setKeepAlive(getBoolean(Constants.SPRING_DATASOURCE_KEEP_ALIVE));
//just for development
if (CommonUtils.isDevelopMode()) {
/*if (CommonUtils.isDevelopMode()) {
//Configure filters that are intercepted by monitoring statistics, and SQL can not be counted after removing them.'wall'is used for firewall
try {
druidDataSource.setFilters("stat,wall,log4j");
} catch (SQLException e) {
logger.error(e.getMessage(), e);
}
}
}*/
druidDataSource.setMinIdle(getInt(Constants.SPRING_DATASOURCE_MIN_IDLE));
druidDataSource.setMaxActive(getInt(Constants.SPRING_DATASOURCE_MAX_ACTIVE));

5
escheduler-dao/src/main/java/cn/escheduler/dao/mapper/ProcessDefinitionMapper.java

@ -94,6 +94,7 @@ public interface ProcessDefinitionMapper {
@Result(property = "locations", column = "locations", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "connects", column = "connects", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "projectName", column = "project_name", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "timeout", column = "timeout", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "receivers", column = "receivers", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "receiversCc", column = "receivers_cc", javaType = String.class, jdbcType = JdbcType.VARCHAR)
@ -121,6 +122,7 @@ public interface ProcessDefinitionMapper {
@Result(property = "userName", column = "user_name", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "locations", column = "locations", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "connects", column = "connects", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "timeout", column = "timeout", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "projectName", column = "project_name", javaType = String.class, jdbcType = JdbcType.VARCHAR)
})
@SelectProvider(type = ProcessDefinitionMapperProvider.class, method = "queryByDefineName")
@ -157,6 +159,7 @@ public interface ProcessDefinitionMapper {
@Result(property = "updateTime", column = "update_time", javaType = Timestamp.class, jdbcType = JdbcType.DATE),
@Result(property = "flag", column = "flag", typeHandler = EnumOrdinalTypeHandler.class, javaType = Flag.class, jdbcType = JdbcType.TINYINT),
@Result(property = "userName", column = "user_name", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "timeout", column = "timeout", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "projectName", column = "project_name", javaType = String.class, jdbcType = JdbcType.VARCHAR)
})
@SelectProvider(type = ProcessDefinitionMapperProvider.class, method = "queryAllDefinitionList")
@ -183,6 +186,7 @@ public interface ProcessDefinitionMapper {
@Result(property = "flag", column = "flag", typeHandler = EnumOrdinalTypeHandler.class, javaType = Flag.class, jdbcType = JdbcType.TINYINT),
@Result(property = "userName", column = "user_name", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "scheduleReleaseState", column = "schedule_release_state", typeHandler = EnumOrdinalTypeHandler.class, javaType = ReleaseState.class, jdbcType = JdbcType.TINYINT),
@Result(property = "timeout", column = "timeout", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "projectName", column = "project_name", javaType = String.class, jdbcType = JdbcType.VARCHAR)
})
@SelectProvider(type = ProcessDefinitionMapperProvider.class, method = "queryDefineListPaging")
@ -211,6 +215,7 @@ public interface ProcessDefinitionMapper {
@Result(property = "locations", column = "locations", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "connects", column = "connects", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "userName", column = "user_name", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "timeout", column = "timeout", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "projectName", column = "project_name", javaType = String.class, jdbcType = JdbcType.VARCHAR)
})
@SelectProvider(type = ProcessDefinitionMapperProvider.class, method = "queryDefinitionListByIdList")

4
escheduler-dao/src/main/java/cn/escheduler/dao/mapper/ProcessDefinitionMapperProvider.java

@ -55,6 +55,7 @@ public class ProcessDefinitionMapperProvider {
VALUES("`connects`", "#{processDefinition.connects}");
VALUES("`create_time`", "#{processDefinition.createTime}");
VALUES("`update_time`", "#{processDefinition.updateTime}");
VALUES("`timeout`", "#{processDefinition.timeout}");
VALUES("`flag`", EnumFieldUtil.genFieldStr("processDefinition.flag", ReleaseState.class));
VALUES("`user_id`", "#{processDefinition.userId}");
@ -100,6 +101,7 @@ public class ProcessDefinitionMapperProvider {
SET("`global_params`=#{processDefinition.globalParams}");
SET("`create_time`=#{processDefinition.createTime}");
SET("`update_time`=#{processDefinition.updateTime}");
SET("`timeout`=#{processDefinition.timeout}");
SET("`flag`="+EnumFieldUtil.genFieldStr("processDefinition.flag", Flag.class));
SET("`user_id`=#{processDefinition.userId}");
@ -173,7 +175,7 @@ public class ProcessDefinitionMapperProvider {
*/
public String queryDefineListPaging(Map<String, Object> parameter) {
return new SQL() {{
SELECT("td.id,td.name,td.version,td.release_state,td.project_id,td.user_id,td.`desc`,td.create_time,td.update_time,td.flag,td.global_params,td.receivers,td.receivers_cc,sc.schedule_release_state");
SELECT("td.*,sc.schedule_release_state");
FROM(TABLE_NAME + " td");
LEFT_OUTER_JOIN(" (select process_definition_id,release_state as schedule_release_state from `t_escheduler_schedules` " +
"group by `process_definition_id`,`release_state`) sc on sc.process_definition_id = td.id");

11
escheduler-dao/src/main/java/cn/escheduler/dao/mapper/ProcessInstanceMapper.java

@ -95,6 +95,7 @@ public interface ProcessInstanceMapper {
@Result(property = "duration", column = "duration", javaType = Long.class, jdbcType = JdbcType.BIGINT),
@Result(property = "tenantCode", column = "tenant_code", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "workerGroupId", column = "worker_group_id", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "timeout", column = "timeout", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "processInstancePriority", column = "process_instance_priority", javaType = Priority.class, typeHandler = EnumOrdinalTypeHandler.class, jdbcType = JdbcType.TINYINT)
})
@SelectProvider(type = ProcessInstanceMapperProvider.class, method = "queryDetailById")
@ -133,6 +134,7 @@ public interface ProcessInstanceMapper {
@Result(property = "historyCmd", column = "history_cmd", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "dependenceScheduleTimes", column = "dependence_schedule_times", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "workerGroupId", column = "worker_group_id", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "timeout", column = "timeout", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "processInstancePriority", column = "process_instance_priority", javaType = Priority.class, typeHandler = EnumOrdinalTypeHandler.class, jdbcType = JdbcType.TINYINT)
})
@SelectProvider(type = ProcessInstanceMapperProvider.class, method = "queryById")
@ -171,6 +173,7 @@ public interface ProcessInstanceMapper {
@Result(property = "dependenceScheduleTimes", column = "dependence_schedule_times", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "processInstanceJson", column = "process_instance_json", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "workerGroupId", column = "worker_group_id", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "timeout", column = "timeout", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "processInstancePriority", column = "process_instance_priority", javaType = Priority.class, typeHandler = EnumOrdinalTypeHandler.class, jdbcType = JdbcType.TINYINT)
})
@ -209,6 +212,7 @@ public interface ProcessInstanceMapper {
@Result(property = "dependenceScheduleTimes", column = "dependence_schedule_times", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "processInstanceJson", column = "process_instance_json", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "workerGroupId", column = "worker_group_id", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "timeout", column = "timeout", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "processInstancePriority", column = "process_instance_priority", javaType = Priority.class, typeHandler = EnumOrdinalTypeHandler.class, jdbcType = JdbcType.TINYINT)
})
@ -256,6 +260,7 @@ public interface ProcessInstanceMapper {
@Result(property = "duration", column = "duration", javaType = Long.class, jdbcType = JdbcType.BIGINT),
@Result(property = "processInstanceJson", column = "process_instance_json", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "workerGroupId", column = "worker_group_id", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "timeout", column = "timeout", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "processInstancePriority", column = "process_instance_priority", javaType = Priority.class, typeHandler = EnumOrdinalTypeHandler.class, jdbcType = JdbcType.TINYINT)
})
@ -352,6 +357,7 @@ public interface ProcessInstanceMapper {
@Result(property = "duration", column = "duration", javaType = Long.class, jdbcType = JdbcType.BIGINT),
@Result(property = "processInstanceJson", column = "process_instance_json", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "workerGroupId", column = "worker_group_id", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "timeout", column = "timeout", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "processInstancePriority", column = "process_instance_priority", javaType = Priority.class, typeHandler = EnumOrdinalTypeHandler.class, jdbcType = JdbcType.TINYINT)
})
@ -444,6 +450,7 @@ public interface ProcessInstanceMapper {
@Result(property = "duration", column = "duration", javaType = Long.class, jdbcType = JdbcType.BIGINT),
@Result(property = "processInstanceJson", column = "process_instance_json", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "workerGroupId", column = "worker_group_id", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "timeout", column = "timeout", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "processInstancePriority", column = "process_instance_priority", javaType = Priority.class, typeHandler = EnumOrdinalTypeHandler.class, jdbcType = JdbcType.TINYINT)
})
@ -488,6 +495,7 @@ public interface ProcessInstanceMapper {
@Result(property = "duration", column = "duration", javaType = Long.class, jdbcType = JdbcType.BIGINT),
@Result(property = "processInstanceJson", column = "process_instance_json", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "workerGroupId", column = "worker_group_id", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "timeout", column = "timeout", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "processInstancePriority", column = "process_instance_priority", javaType = Priority.class, typeHandler = EnumOrdinalTypeHandler.class, jdbcType = JdbcType.TINYINT)
})
@ -532,6 +540,7 @@ public interface ProcessInstanceMapper {
@Result(property = "dependenceScheduleTimes", column = "dependence_schedule_times", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "processInstanceJson", column = "process_instance_json", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "workerGroupId", column = "worker_group_id", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "timeout", column = "timeout", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "processInstancePriority", column = "process_instance_priority", javaType = Priority.class, typeHandler = EnumOrdinalTypeHandler.class, jdbcType = JdbcType.TINYINT)
})
@ -574,6 +583,7 @@ public interface ProcessInstanceMapper {
@Result(property = "dependenceScheduleTimes", column = "dependence_schedule_times", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "processInstanceJson", column = "process_instance_json", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "workerGroupId", column = "worker_group_id", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "timeout", column = "timeout", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "processInstancePriority", column = "process_instance_priority", javaType = Priority.class, typeHandler = EnumOrdinalTypeHandler.class, jdbcType = JdbcType.TINYINT)
})
@SelectProvider(type = ProcessInstanceMapperProvider.class, method = "queryLastRunningProcess")
@ -616,6 +626,7 @@ public interface ProcessInstanceMapper {
@Result(property = "dependenceScheduleTimes", column = "dependence_schedule_times", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "processInstanceJson", column = "process_instance_json", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "workerGroupId", column = "worker_group_id", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "timeout", column = "timeout", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
@Result(property = "processInstancePriority", column = "process_instance_priority", javaType = Priority.class, typeHandler = EnumOrdinalTypeHandler.class, jdbcType = JdbcType.TINYINT)
})
@SelectProvider(type = ProcessInstanceMapperProvider.class, method = "queryLastManualProcess")

2
escheduler-dao/src/main/java/cn/escheduler/dao/mapper/ProcessInstanceMapperProvider.java

@ -68,6 +68,7 @@ public class ProcessInstanceMapperProvider {
VALUES("`is_sub_process`", EnumFieldUtil.genFieldStr("processInstance.isSubProcess", Flag.class));
VALUES("`executor_id`", "#{processInstance.executorId}");
VALUES("`worker_group_id`", "#{processInstance.workerGroupId}");
VALUES("`timeout`", "#{processInstance.timeout}");
VALUES("`process_instance_priority`", EnumFieldUtil.genFieldStr("processInstance.processInstancePriority", Priority.class));
}
}.toString();
@ -141,6 +142,7 @@ public class ProcessInstanceMapperProvider {
SET("`is_sub_process`="+EnumFieldUtil.genFieldStr("processInstance.isSubProcess", Flag.class));
SET("`executor_id`=#{processInstance.executorId}");
SET("`worker_group_id`=#{processInstance.workerGroupId}");
SET("`timeout`=#{processInstance.timeout}");
WHERE("`id`=#{processInstance.id}");

10
escheduler-dao/src/main/java/cn/escheduler/dao/model/ProcessData.java

@ -37,6 +37,9 @@ public class ProcessData {
private List<Property> globalParams;
private int timeout;
public ProcessData() {
}
@ -82,4 +85,11 @@ public class ProcessData {
this.globalParams = globalParams;
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
}

15
escheduler-dao/src/main/java/cn/escheduler/dao/model/ProcessDefinition.java

@ -136,6 +136,11 @@ public class ProcessDefinition {
*/
private ReleaseState scheduleReleaseState;
/**
* process warning time out. unit: minute
*/
private int timeout;
public String getName() {
return name;
@ -316,6 +321,14 @@ public class ProcessDefinition {
this.scheduleReleaseState = scheduleReleaseState;
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
@Override
public String toString() {
return "ProcessDefinition{" +
@ -340,6 +353,8 @@ public class ProcessDefinition {
", receivers='" + receivers + '\'' +
", receiversCc='" + receiversCc + '\'' +
", scheduleReleaseState=" + scheduleReleaseState +
", timeout=" + timeout +
'}';
}
}

15
escheduler-dao/src/main/java/cn/escheduler/dao/model/ProcessInstance.java

@ -183,6 +183,11 @@ public class ProcessInstance {
*/
private int workerGroupId;
/**
* process timeout for warning
*/
private int timeout;
public ProcessInstance(){
}
@ -495,6 +500,14 @@ public class ProcessInstance {
this.workerGroupId = workerGroupId;
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
@Override
public String toString() {
return "ProcessInstance{" +
@ -528,7 +541,9 @@ public class ProcessInstance {
", historyCmd='" + historyCmd + '\'' +
", dependenceScheduleTimes='" + dependenceScheduleTimes + '\'' +
", duration=" + duration +
", timeout=" + timeout +
", processInstancePriority=" + processInstancePriority +
'}';
}
}

31
escheduler-dao/src/main/java/cn/escheduler/dao/upgrade/EschedulerManager.java

@ -30,12 +30,17 @@ public class EschedulerManager {
UpgradeDao upgradeDao = UpgradeDao.getInstance();
public void initEscheduler() {
// Determines whether the escheduler table structure has been init
if(upgradeDao.isExistsTable("t_escheduler_version") || upgradeDao.isExistsTable("t_escheduler_queue")) {
logger.info("The database has been initialized. Skip the initialization step");
return;
}
this.initEschedulerSchema();
}
public void initEschedulerSchema() {
logger.info("Start initializing the ark manager mysql table structure");
logger.info("Start initializing the escheduler manager mysql table structure");
upgradeDao.initEschedulerSchema();
}
@ -52,15 +57,21 @@ public class EschedulerManager {
}else {
String version = "";
// Gets the version of the current system
if (upgradeDao.isExistsTable("t_escheduler_version")) {
version = upgradeDao.getCurrentVersion();
}else if(upgradeDao.isExistsColumn("t_escheduler_queue","create_time")){
version = "1.0.1";
}else if(upgradeDao.isExistsTable("t_escheduler_queue")){
version = "1.0.0";
}else{
logger.error("Unable to determine current software version, so cannot upgrade");
throw new RuntimeException("Unable to determine current software version, so cannot upgrade");
}
// The target version of the upgrade
String schemaVersion = "";
for(String schemaDir : schemaList) {
// Gets the version of the current system
if (upgradeDao.isExistsTable("t_escheduler_version")) {
version = upgradeDao.getCurrentVersion();
}else {
version = "1.0.0";
}
schemaVersion = schemaDir.split("_")[0];
if(SchemaUtils.isAGreatVersion(schemaVersion , version)) {
@ -70,7 +81,11 @@ public class EschedulerManager {
logger.info("Begin upgrading escheduler's mysql table structure");
upgradeDao.upgradeEscheduler(schemaDir);
if(SchemaUtils.isAGreatVersion(version,"1.0.1")){
version = upgradeDao.getCurrentVersion();
}else {
version = schemaVersion;
}
}
}

57
escheduler-dao/src/main/java/cn/escheduler/dao/upgrade/UpgradeDao.java

@ -20,6 +20,7 @@ import cn.escheduler.common.utils.MysqlUtil;
import cn.escheduler.common.utils.ScriptRunner;
import cn.escheduler.dao.AbstractBaseDao;
import cn.escheduler.dao.datasource.ConnectionFactory;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -33,6 +34,7 @@ public class UpgradeDao extends AbstractBaseDao {
public static final Logger logger = LoggerFactory.getLogger(UpgradeDao.class);
private static final String T_VERSION_NAME = "t_escheduler_version";
private static final String rootDir = System.getProperty("user.dir");
@Override
protected void init() {
@ -64,6 +66,10 @@ public class UpgradeDao extends AbstractBaseDao {
private void runInitEschedulerDML() {
Connection conn = null;
if (StringUtils.isEmpty(rootDir)) {
throw new RuntimeException("Environment variable user.dir not found");
}
String mysqlSQLFilePath = rootDir + "/sql/create/release-1.0.0_schema/mysql/escheduler_dml.sql";
try {
conn = ConnectionFactory.getDataSource().getConnection();
conn.setAutoCommit(false);
@ -71,7 +77,7 @@ public class UpgradeDao extends AbstractBaseDao {
// Execute the ark_manager_dml.sql script to import the data related to escheduler
ScriptRunner initScriptRunner = new ScriptRunner(conn, false, true);
Reader initSqlReader = new FileReader(new File("sql/create/release-1.0.0_schema/mysql/escheduler_dml.sql"));
Reader initSqlReader = new FileReader(new File(mysqlSQLFilePath));
initScriptRunner.runScript(initSqlReader);
conn.commit();
@ -100,11 +106,15 @@ public class UpgradeDao extends AbstractBaseDao {
private void runInitEschedulerDDL() {
Connection conn = null;
if (StringUtils.isEmpty(rootDir)) {
throw new RuntimeException("Environment variable user.dir not found");
}
String mysqlSQLFilePath = rootDir + "/sql/create/release-1.0.0_schema/mysql/escheduler_ddl.sql";
try {
conn = ConnectionFactory.getDataSource().getConnection();
// Execute the escheduler_ddl.sql script to create the table structure of escheduler
ScriptRunner initScriptRunner = new ScriptRunner(conn, true, true);
Reader initSqlReader = new FileReader(new File("sql/create/release-1.0.0_schema/mysql/escheduler_ddl.sql"));
Reader initSqlReader = new FileReader(new File(mysqlSQLFilePath));
initScriptRunner.runScript(initSqlReader);
} catch (IOException e) {
@ -122,7 +132,11 @@ public class UpgradeDao extends AbstractBaseDao {
}
/**
* Determines whether a table exists
* @param tableName
* @return
*/
public boolean isExistsTable(String tableName) {
Connection conn = null;
try {
@ -144,6 +158,33 @@ public class UpgradeDao extends AbstractBaseDao {
}
/**
* Determines whether a field exists in the specified table
* @param tableName
* @param columnName
* @return
*/
public boolean isExistsColumn(String tableName,String columnName) {
Connection conn = null;
try {
conn = ConnectionFactory.getDataSource().getConnection();
ResultSet rs = conn.getMetaData().getColumns(null,null,tableName,columnName);
if (rs.next()) {
return true;
} else {
return false;
}
} catch (SQLException e) {
logger.error(e.getMessage(),e);
throw new RuntimeException(e.getMessage(),e);
} finally {
MysqlUtil.realeaseResource(null, null, conn);
}
}
public String getCurrentVersion() {
String sql = String.format("select version from %s",T_VERSION_NAME);
@ -182,7 +223,10 @@ public class UpgradeDao extends AbstractBaseDao {
private void upgradeEschedulerDML(String schemaDir) {
String schemaVersion = schemaDir.split("_")[0];
String mysqlSQLFilePath = "sql/upgrade/" + schemaDir + "/mysql/escheduler_dml.sql";
if (StringUtils.isEmpty(rootDir)) {
throw new RuntimeException("Environment variable user.dir not found");
}
String mysqlSQLFilePath = rootDir + "/sql/upgrade/" + schemaDir + "/mysql/escheduler_dml.sql";
Connection conn = null;
PreparedStatement pstmt = null;
try {
@ -239,7 +283,10 @@ public class UpgradeDao extends AbstractBaseDao {
}
private void upgradeEschedulerDDL(String schemaDir) {
String mysqlSQLFilePath = "sql/upgrade/" + schemaDir + "/mysql/escheduler_ddl.sql";
if (StringUtils.isEmpty(rootDir)) {
throw new RuntimeException("Environment variable user.dir not found");
}
String mysqlSQLFilePath = rootDir + "/sql/upgrade/" + schemaDir + "/mysql/escheduler_ddl.sql";
Connection conn = null;
PreparedStatement pstmt = null;
try {

1
escheduler-dao/src/main/java/cn/escheduler/dao/upgrade/shell/CreateEscheduler.java

@ -29,7 +29,6 @@ public class CreateEscheduler {
private static final Logger logger = LoggerFactory.getLogger(CreateEscheduler.class);
public static void main(String[] args) {
Thread.currentThread().setName("manager-CreateEscheduler");
EschedulerManager eschedulerManager = new EschedulerManager();
eschedulerManager.initEscheduler();
logger.info("init escheduler finished");

2
escheduler-dao/src/main/java/cn/escheduler/dao/upgrade/shell/UpgradeEscheduler.java

@ -27,8 +27,6 @@ public class UpgradeEscheduler {
private static final Logger logger = LoggerFactory.getLogger(UpgradeEscheduler.class);
public static void main(String[] args) {
Thread.currentThread().setName("manager-UpgradeEscheduler");
EschedulerManager eschedulerManager = new EschedulerManager();
try {
eschedulerManager.upgradeEscheduler();

6
escheduler-dao/src/main/resources/dao/data_source.properties

@ -1,9 +1,9 @@
# base spring data source configuration
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.220.188:3306/escheduler_new?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=root@123
spring.datasource.url=jdbc:mysql://192.168.xx.xx:3306/escheduler?characterEncoding=UTF-8
spring.datasource.username=xx
spring.datasource.password=xx
# connection configuration
spring.datasource.initialSize=5

2
escheduler-rpc/pom.xml

@ -4,7 +4,7 @@
<parent>
<artifactId>escheduler</artifactId>
<groupId>cn.analysys</groupId>
<version>1.0.1-SNAPSHOT</version>
<version>1.0.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

2
escheduler-server/pom.xml

@ -3,7 +3,7 @@
<parent>
<artifactId>escheduler</artifactId>
<groupId>cn.analysys</groupId>
<version>1.0.1-SNAPSHOT</version>
<version>1.0.2-SNAPSHOT</version>
</parent>
<artifactId>escheduler-server</artifactId>
<name>escheduler-server</name>

32
escheduler-server/src/main/java/cn/escheduler/server/master/runner/MasterExecThread.java

@ -258,7 +258,7 @@ public class MasterExecThread implements Runnable {
processDao.createRecoveryWaitingThreadCommand(null, processInstance);
}
List<TaskInstance> taskInstances = processDao.findValidTaskListByProcessId(processInstance.getId());
alertManager.sendWarnningOfProcessInstance(processInstance, taskInstances);
alertManager.sendAlertProcessInstance(processInstance, taskInstances);
}
@ -775,8 +775,15 @@ public class MasterExecThread implements Runnable {
private void runProcess(){
// submit start node
submitPostNode(null);
// submitStandByTask();
boolean sendTimeWarning = false;
while(!processInstance.IsProcessInstanceStop()){
// send warning email if process time out.
if( !sendTimeWarning && checkProcessTimeOut(processInstance) ){
alertManager.sendProcessTimeoutAlert(processInstance,
processDao.findProcessDefineById(processInstance.getProcessDefinitionId()));
sendTimeWarning = true;
}
Set<MasterBaseTaskExecThread> keys = activeTaskNode.keySet();
for (MasterBaseTaskExecThread taskExecThread : keys) {
Future<Boolean> future = activeTaskNode.get(taskExecThread);
@ -821,7 +828,7 @@ public class MasterExecThread implements Runnable {
}
// send alert
if(this.recoverToleranceFaultTaskList.size() > 0){
alertManager.sendWarnningWorkerleranceFault(processInstance, recoverToleranceFaultTaskList);
alertManager.sendAlertWorkerToleranceFault(processInstance, recoverToleranceFaultTaskList);
this.recoverToleranceFaultTaskList.clear();
}
// updateProcessInstance completed task status
@ -851,6 +858,25 @@ public class MasterExecThread implements Runnable {
logger.info("process:{} end, state :{}", processInstance.getId(), processInstance.getState());
}
/**
* check process time out
* @param processInstance
* @return
*/
private boolean checkProcessTimeOut(ProcessInstance processInstance) {
if(processInstance.getTimeout() == 0 ){
return false;
}
Date now = new Date();
long runningTime = DateUtils.differMs(now, processInstance.getStartTime());
if(runningTime > processInstance.getTimeout()){
return true;
}
return false;
}
private boolean canSubmitTaskToQueue() {
return OSUtils.checkResource(conf, true);
}

58
escheduler-server/src/main/java/cn/escheduler/server/utils/AlertManager.java

@ -26,6 +26,7 @@ import cn.escheduler.common.utils.JSONUtils;
import cn.escheduler.dao.AlertDao;
import cn.escheduler.dao.DaoFactory;
import cn.escheduler.dao.model.Alert;
import cn.escheduler.dao.model.ProcessDefinition;
import cn.escheduler.dao.model.ProcessInstance;
import cn.escheduler.dao.model.TaskInstance;
import org.slf4j.Logger;
@ -54,27 +55,27 @@ public class AlertManager {
private String getCommandCnName(CommandType commandType) {
switch (commandType) {
case RECOVER_TOLERANCE_FAULT_PROCESS:
return "恢复容错";
return "recover tolerance fault process";
case RECOVER_SUSPENDED_PROCESS:
return "恢复暂停流程";
return "recover suspended process";
case START_CURRENT_TASK_PROCESS:
return "从当前节点开始执行";
return "start current task process";
case START_FAILURE_TASK_PROCESS:
return "从失败节点开始执行";
return "start failure task process";
case START_PROCESS:
return "启动工作流";
return "start process";
case REPEAT_RUNNING:
return "重跑";
return "repeat running";
case SCHEDULER:
return "定时执行";
return "scheduler";
case COMPLEMENT_DATA:
return "补数";
return "complement data";
case PAUSE:
return "暂停工作流";
return "pause";
case STOP:
return "停止工作流";
return "stop";
default:
return "未知的命令类型";
return "unknown type";
}
}
@ -124,14 +125,14 @@ public class AlertManager {
continue;
}
LinkedHashMap<String, String> failedTaskMap = new LinkedHashMap();
failedTaskMap.put("任务id", String.valueOf(task.getId()));
failedTaskMap.put("任务名称", task.getName());
failedTaskMap.put("任务类型", task.getTaskType());
failedTaskMap.put("任务状态", task.getState().toString());
failedTaskMap.put("任务开始时间", DateUtils.dateToString(task.getStartTime()));
failedTaskMap.put("任务结束时间", DateUtils.dateToString(task.getEndTime()));
failedTaskMap.put("task id", String.valueOf(task.getId()));
failedTaskMap.put("task name", task.getName());
failedTaskMap.put("task type", task.getTaskType());
failedTaskMap.put("task state", task.getState().toString());
failedTaskMap.put("task start time", DateUtils.dateToString(task.getStartTime()));
failedTaskMap.put("task end time", DateUtils.dateToString(task.getEndTime()));
failedTaskMap.put("host", task.getHost());
failedTaskMap.put("日志路径", task.getLogPath());
failedTaskMap.put("log path", task.getLogPath());
failedTaskList.add(failedTaskMap);
}
res = JSONUtils.toJson(failedTaskList);
@ -152,10 +153,10 @@ public class AlertManager {
for(TaskInstance taskInstance: toleranceTaskList){
LinkedHashMap<String, String> toleranceWorkerContentMap = new LinkedHashMap();
toleranceWorkerContentMap.put("工作流程名称", processInstance.getName());
toleranceWorkerContentMap.put("容错任务名称", taskInstance.getName());
toleranceWorkerContentMap.put("容错机器IP", taskInstance.getHost());
toleranceWorkerContentMap.put("任务失败次数", String.valueOf(taskInstance.getRetryTimes()));
toleranceWorkerContentMap.put("process name", processInstance.getName());
toleranceWorkerContentMap.put("task name", taskInstance.getName());
toleranceWorkerContentMap.put("host", taskInstance.getHost());
toleranceWorkerContentMap.put("task retry times", String.valueOf(taskInstance.getRetryTimes()));
toleranceTaskInstanceList.add(toleranceWorkerContentMap);
}
return JSONUtils.toJson(toleranceTaskInstanceList);
@ -166,9 +167,9 @@ public class AlertManager {
* @param processInstance
* @param toleranceTaskList
*/
public void sendWarnningWorkerleranceFault(ProcessInstance processInstance, List<TaskInstance> toleranceTaskList){
public void sendAlertWorkerToleranceFault(ProcessInstance processInstance, List<TaskInstance> toleranceTaskList){
Alert alert = new Alert();
alert.setTitle("worker容错报警");
alert.setTitle("worker fault tolerance");
alert.setShowType(ShowType.TABLE);
String content = getWorkerToleranceContent(processInstance, toleranceTaskList);
alert.setContent(content);
@ -187,8 +188,8 @@ public class AlertManager {
* send process instance alert
* @param processInstance
*/
public void sendWarnningOfProcessInstance(ProcessInstance processInstance,
List<TaskInstance> taskInstances){
public void sendAlertProcessInstance(ProcessInstance processInstance,
List<TaskInstance> taskInstances){
boolean sendWarnning = false;
WarningType warningType = processInstance.getWarningType();
@ -217,7 +218,7 @@ public class AlertManager {
String cmdName = getCommandCnName(processInstance.getCommandType());
String success = processInstance.getState().typeIsSuccess() ? "成功" :"失败";
String success = processInstance.getState().typeIsSuccess() ? "success" :"failed";
alert.setTitle(cmdName + success);
ShowType showType = processInstance.getState().typeIsSuccess() ? ShowType.TEXT : ShowType.TABLE;
alert.setShowType(showType);
@ -233,4 +234,7 @@ public class AlertManager {
logger.info("add alert to db , alert: {}", alert.toString());
}
public void sendProcessTimeoutAlert(ProcessInstance processInstance, ProcessDefinition processDefinition) {
alertDao.sendProcessTimeoutAlert(processInstance, processDefinition);
}
}

7
escheduler-server/src/main/java/cn/escheduler/server/worker/task/sql/SqlTask.java

@ -305,7 +305,7 @@ public class SqlTask extends AbstractTask {
receviersList.add(user.getEmail());
}
// custom receiver
String receivers = processDefine.getReceivers();
String receivers = sqlParameters.getReceivers();
if (StringUtils.isNotEmpty(receivers)){
String[] splits = receivers.split(Constants.COMMA);
for (String receiver : splits){
@ -315,11 +315,8 @@ public class SqlTask extends AbstractTask {
// copy list
List<String> receviersCcList = new ArrayList<String>();
// Custom Copier
String receiversCc = processDefine.getReceiversCc();
String receiversCc = sqlParameters.getReceiversCc();
if (StringUtils.isNotEmpty(receiversCc)){
String[] splits = receiversCc.split(Constants.COMMA);
for (String receiverCc : splits){

4
escheduler-server/src/test/java/cn/escheduler/server/master/AlertManagerTest.java

@ -76,7 +76,7 @@ public class AlertManagerTest {
toleranceTaskList.add(toleranceTask1);
toleranceTaskList.add(toleranceTask2);
alertManager.sendWarnningWorkerleranceFault(processInstance, toleranceTaskList);
alertManager.sendAlertWorkerToleranceFault(processInstance, toleranceTaskList);
}
@ -103,7 +103,7 @@ public class AlertManagerTest {
toleranceTaskList.add(toleranceTask1);
toleranceTaskList.add(toleranceTask2);
alertManager.sendWarnningOfProcessInstance(processInstance, toleranceTaskList);
alertManager.sendAlertProcessInstance(processInstance, toleranceTaskList);
}
}

14
escheduler-ui/dist/css/home/index.0212fa5.css vendored

File diff suppressed because one or more lines are too long

14
escheduler-ui/dist/css/login/index.6083d91.css vendored

File diff suppressed because one or more lines are too long

4
escheduler-ui/dist/index.html vendored

@ -1,7 +1,7 @@
<!doctype html><html><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta http-equiv="Cache-Control" content="no-siteapp"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-title" content="标题"><meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"><meta name="format-detection" content="telphone=no, email=no"><meta name="screen-orientation" content="portrait"><meta name="x5-orientation" content="portrait"><meta name="theme-color" content="#4a8dee"><meta name="msapplication-navbutton-color" content="#4a8dee"><meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1"><link rel="shortcut icon" href="/images/favicon.ico"><link href="/combo/1.0.0/base.css?v1.0.0.1" rel="stylesheet"><link href="/combo/1.0.0/3rd.css?v1.0.0.1" rel="stylesheet"><!--[if lt IE 9]>
<script src="/combo/1.0.0/es5.js"></script>
<![endif]--><script>let NODE_ENV = 'true'</script><title>EasyScheduler</title><link href="/css/common.8ba9af7.css" rel="stylesheet"><link href="/css/home/index.0212fa5.css" rel="stylesheet"></head><body><div id="app"></div><div id="contextmenu" class="contextmenu"></div><div class="global-loading"><div class="svg-box"><svg class="lds-gears" width="54px" height="54px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" style="background: none;"><g transform="translate(50 50)"><g transform="translate(-19 -19) scale(0.6)"><g transform="rotate(107.866)"><animateTransform attributeName="transform" type="rotate" values="0;360" keyTimes="0;1" dur="1s" begin="0s" repeatCount="indefinite"></animateTransform><path
<![endif]--><script>let NODE_ENV = 'true'</script><title>EasyScheduler</title><link href="/css/common.8ba9af7.css" rel="stylesheet"><link href="/css/home/index.b444b91.css" rel="stylesheet"></head><body><div id="app"></div><div id="contextmenu" class="contextmenu"></div><div class="global-loading"><div class="svg-box"><svg class="lds-gears" width="54px" height="54px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" style="background: none;"><g transform="translate(50 50)"><g transform="translate(-19 -19) scale(0.6)"><g transform="rotate(107.866)"><animateTransform attributeName="transform" type="rotate" values="0;360" keyTimes="0;1" dur="1s" begin="0s" repeatCount="indefinite"></animateTransform><path
d="M37.3496987939662 -7 L47.3496987939662 -7 L47.3496987939662 7 L37.3496987939662 7 A38 38 0 0 1 31.359972760794346 21.46047782418268 L31.359972760794346 21.46047782418268 L38.431040572659825 28.531545636048154 L28.531545636048154 38.431040572659825 L21.46047782418268 31.359972760794346 A38 38 0 0 1 7.0000000000000036 37.3496987939662 L7.0000000000000036 37.3496987939662 L7.000000000000004 47.3496987939662 L-6.999999999999999 47.3496987939662 L-7 37.3496987939662 A38 38 0 0 1 -21.46047782418268 31.35997276079435 L-21.46047782418268 31.35997276079435 L-28.531545636048154 38.431040572659825 L-38.43104057265982 28.531545636048158 L-31.359972760794346 21.460477824182682 A38 38 0 0 1 -37.3496987939662 7.000000000000007 L-37.3496987939662 7.000000000000007 L-47.3496987939662 7.000000000000008 L-47.3496987939662 -6.9999999999999964 L-37.3496987939662 -6.999999999999997 A38 38 0 0 1 -31.35997276079435 -21.460477824182675 L-31.35997276079435 -21.460477824182675 L-38.431040572659825 -28.531545636048147 L-28.53154563604818 -38.4310405726598 L-21.4604778241827 -31.35997276079433 A38 38 0 0 1 -6.999999999999992 -37.3496987939662 L-6.999999999999992 -37.3496987939662 L-6.999999999999994 -47.3496987939662 L6.999999999999977 -47.3496987939662 L6.999999999999979 -37.3496987939662 A38 38 0 0 1 21.460477824182686 -31.359972760794342 L21.460477824182686 -31.359972760794342 L28.531545636048158 -38.43104057265982 L38.4310405726598 -28.53154563604818 L31.35997276079433 -21.4604778241827 A38 38 0 0 1 37.3496987939662 -6.999999999999995 M0 -23A23 23 0 1 0 0 23 A23 23 0 1 0 0 -23"
fill="#0097e0"></path></g></g><g transform="translate(19 19) scale(0.6)"><g transform="rotate(229.634)"><animateTransform attributeName="transform" type="rotate" values="360;0" keyTimes="0;1" dur="1s" begin="-0.0625s" repeatCount="indefinite"></animateTransform><path
d="M37.3496987939662 -7 L47.3496987939662 -7 L47.3496987939662 7 L37.3496987939662 7 A38 38 0 0 1 31.359972760794346 21.46047782418268 L31.359972760794346 21.46047782418268 L38.431040572659825 28.531545636048154 L28.531545636048154 38.431040572659825 L21.46047782418268 31.359972760794346 A38 38 0 0 1 7.0000000000000036 37.3496987939662 L7.0000000000000036 37.3496987939662 L7.000000000000004 47.3496987939662 L-6.999999999999999 47.3496987939662 L-7 37.3496987939662 A38 38 0 0 1 -21.46047782418268 31.35997276079435 L-21.46047782418268 31.35997276079435 L-28.531545636048154 38.431040572659825 L-38.43104057265982 28.531545636048158 L-31.359972760794346 21.460477824182682 A38 38 0 0 1 -37.3496987939662 7.000000000000007 L-37.3496987939662 7.000000000000007 L-47.3496987939662 7.000000000000008 L-47.3496987939662 -6.9999999999999964 L-37.3496987939662 -6.999999999999997 A38 38 0 0 1 -31.35997276079435 -21.460477824182675 L-31.35997276079435 -21.460477824182675 L-38.431040572659825 -28.531545636048147 L-28.53154563604818 -38.4310405726598 L-21.4604778241827 -31.35997276079433 A38 38 0 0 1 -6.999999999999992 -37.3496987939662 L-6.999999999999992 -37.3496987939662 L-6.999999999999994 -47.3496987939662 L6.999999999999977 -47.3496987939662 L6.999999999999979 -37.3496987939662 A38 38 0 0 1 21.460477824182686 -31.359972760794342 L21.460477824182686 -31.359972760794342 L28.531545636048158 -38.43104057265982 L38.4310405726598 -28.53154563604818 L31.35997276079433 -21.4604778241827 A38 38 0 0 1 37.3496987939662 -6.999999999999995 M0 -23A23 23 0 1 0 0 23 A23 23 0 1 0 0 -23"
fill="#7f8b95"></path></g></g></g></svg> <span class="sp1">Loading ...</span></div></div><script src="/combo/1.0.0/3rd.js?v1.0.0.1"></script><script src="/js/common.804ec41.js"></script><script src="/js/home/index.2ed28db.js"></script></body></html>
fill="#7f8b95"></path></g></g></g></svg> <span class="sp1">Loading ...</span></div></div><script src="/combo/1.0.0/3rd.js?v1.0.0.1"></script><script src="/js/common.5ba245f.js"></script><script src="/js/home/index.1b09c2f.js"></script></body></html>

2
escheduler-ui/dist/js/0.8ca091c.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/0.8ca091c.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/0.bf0a1e2.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/0.bf0a1e2.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/1.3ff7adc.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/1.3ff7adc.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/1.bdb0cc7.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/1.bdb0cc7.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/10.73c0240.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/10.73c0240.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/10.90da74f.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/10.90da74f.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/11.078cbab.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/11.078cbab.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/11.ca8ac79.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/11.ca8ac79.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/12.864692a.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/12.864692a.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/12.b6fb265.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/12.b6fb265.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/13.7e1b794.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/13.7e1b794.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/13.a8f5ee9.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/13.a8f5ee9.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/14.10001b2.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/14.10001b2.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/14.22fa282.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/14.22fa282.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/15.9119d76.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/15.9119d76.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/15.eea1d19.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/15.eea1d19.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/16.648c64b.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/16.648c64b.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/16.fd660eb.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/16.fd660eb.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/17.4aef6ba.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/17.4aef6ba.js.map vendored

File diff suppressed because one or more lines are too long

9
escheduler-ui/dist/js/17.6761755.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/17.6761755.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/18.3bc2e58.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/18.3bc2e58.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/18.b14d7b0.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/18.b14d7b0.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/19.35e5748.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/19.35e5748.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/19.5ce986e.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/19.5ce986e.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/2.3b16c4b.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/2.3b16c4b.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/2.d6885e7.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/2.d6885e7.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/20.15ed1ee.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/20.15ed1ee.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/20.65383c2.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/20.65383c2.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/21.c62cd9a.js vendored

File diff suppressed because one or more lines are too long

1
escheduler-ui/dist/js/21.c62cd9a.js.map vendored

File diff suppressed because one or more lines are too long

2
escheduler-ui/dist/js/21.cc0a847.js vendored

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save