mirror of
https://github.com/dromara/RuoYi-Vue-Plus.git
synced 2025-09-17 16:56:39 +08:00
!359 [需求认领] 对接 powerjob 实现分布式任务调度 集成方式参考框架内 xxl-job
* 对接powerjob替换xxl-job实现分布式任务调度
This commit is contained in:
parent
bbe9dc7dc8
commit
effd504d48
@ -54,7 +54,7 @@
|
|||||||
| 序列化 | 采用 Jackson Spring官方内置序列化 靠谱!!! | 采用 fastjson bugjson 远近闻名 |
|
| 序列化 | 采用 Jackson Spring官方内置序列化 靠谱!!! | 采用 fastjson bugjson 远近闻名 |
|
||||||
| 分布式幂等 | 参考美团GTIS防重系统简化实现(细节可看文档) | 手动编写注解基于aop实现 |
|
| 分布式幂等 | 参考美团GTIS防重系统简化实现(细节可看文档) | 手动编写注解基于aop实现 |
|
||||||
| 分布式锁 | 采用 Lock4j 底层基于 Redisson | 无 |
|
| 分布式锁 | 采用 Lock4j 底层基于 Redisson | 无 |
|
||||||
| 分布式任务调度 | 采用 Xxl-Job 天生支持分布式 统一的管理中心 | 采用 Quartz 基于数据库锁性能差 集群需要做很多配置与改造 |
|
| 分布式任务调度 | 采用 PowerJob 天生支持分布式 统一的管理中心 | 采用 Quartz 基于数据库锁性能差 集群需要做很多配置与改造 |
|
||||||
| 文件存储 | 采用 Minio 分布式文件存储 天生支持多机、多硬盘、多分片、多副本存储<br/>支持权限管理 安全可靠 文件可加密存储 | 采用 本机文件存储 文件裸漏 易丢失泄漏 不支持集群有单点效应 |
|
| 文件存储 | 采用 Minio 分布式文件存储 天生支持多机、多硬盘、多分片、多副本存储<br/>支持权限管理 安全可靠 文件可加密存储 | 采用 本机文件存储 文件裸漏 易丢失泄漏 不支持集群有单点效应 |
|
||||||
| 云存储 | 采用 AWS S3 协议客户端 支持 七牛、阿里、腾讯 等一切支持S3协议的厂家 | 不支持 |
|
| 云存储 | 采用 AWS S3 协议客户端 支持 七牛、阿里、腾讯 等一切支持S3协议的厂家 | 不支持 |
|
||||||
| 短信 | 采用 sms4j 短信融合包 支持数十种短信厂家 只需在yml配置好厂家密钥即可使用 可多厂家共用 | 不支持 |
|
| 短信 | 采用 sms4j 短信融合包 支持数十种短信厂家 只需在yml配置好厂家密钥即可使用 可多厂家共用 | 不支持 |
|
||||||
|
20
pom.xml
20
pom.xml
@ -34,7 +34,7 @@
|
|||||||
<lock4j.version>2.2.4</lock4j.version>
|
<lock4j.version>2.2.4</lock4j.version>
|
||||||
<dynamic-ds.version>3.6.1</dynamic-ds.version>
|
<dynamic-ds.version>3.6.1</dynamic-ds.version>
|
||||||
<alibaba-ttl.version>2.14.2</alibaba-ttl.version>
|
<alibaba-ttl.version>2.14.2</alibaba-ttl.version>
|
||||||
<xxl-job.version>2.4.0</xxl-job.version>
|
<powerjob.version>4.3.3</powerjob.version>
|
||||||
<mapstruct-plus.version>1.2.3</mapstruct-plus.version>
|
<mapstruct-plus.version>1.2.3</mapstruct-plus.version>
|
||||||
<mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version>
|
<mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version>
|
||||||
<lombok.version>1.18.26</lombok.version>
|
<lombok.version>1.18.26</lombok.version>
|
||||||
@ -264,12 +264,6 @@
|
|||||||
<version>${lock4j.version}</version>
|
<version>${lock4j.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- xxl-job-core -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.xuxueli</groupId>
|
|
||||||
<artifactId>xxl-job-core</artifactId>
|
|
||||||
<version>${xxl-job.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba</groupId>
|
<groupId>com.alibaba</groupId>
|
||||||
@ -328,6 +322,18 @@
|
|||||||
<version>${revision}</version>
|
<version>${revision}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- PowerJob -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>tech.powerjob</groupId>
|
||||||
|
<artifactId>powerjob-worker-spring-boot-starter</artifactId>
|
||||||
|
<version>${powerjob.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>tech.powerjob</groupId>
|
||||||
|
<artifactId>powerjob-official-processors</artifactId>
|
||||||
|
<version>${powerjob.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
|
@ -8,27 +8,19 @@ spring.boot.admin.client:
|
|||||||
username: ruoyi
|
username: ruoyi
|
||||||
password: 123456
|
password: 123456
|
||||||
|
|
||||||
--- # xxl-job 配置
|
--- # powerjob 配置
|
||||||
xxl.job:
|
powerjob:
|
||||||
# 执行器开关
|
worker:
|
||||||
enabled: true
|
enabled: true
|
||||||
# 调度中心地址:如调度中心集群部署存在多个地址则用逗号分隔。
|
# 需要现在powerjob登录页执行应用注册后才能使用
|
||||||
admin-addresses: http://localhost:9100/xxl-job-admin
|
app-name: ruoyi-worker
|
||||||
# 执行器通讯TOKEN:非空时启用
|
enable-test-mode: false
|
||||||
access-token: xxl-job
|
max-appended-wf-context-length: 4096
|
||||||
executor:
|
max-result-length: 4096
|
||||||
# 执行器AppName:执行器心跳注册分组依据;为空则关闭自动注册
|
port: 27777
|
||||||
appname: xxl-job-executor
|
protocol: http
|
||||||
# 执行器端口号 执行器从9101开始往后写
|
server-address: 127.0.0.1:7700,127.0.0.1:7701
|
||||||
port: 9101
|
store-strategy: disk
|
||||||
# 执行器注册:默认IP:PORT
|
|
||||||
address:
|
|
||||||
# 执行器IP:默认自动获取IP
|
|
||||||
ip:
|
|
||||||
# 执行器运行日志文件存储磁盘路径
|
|
||||||
logpath: ./logs/xxl-job
|
|
||||||
# 执行器日志文件保存天数:大于3生效
|
|
||||||
logretentiondays: 30
|
|
||||||
|
|
||||||
--- # 数据源配置
|
--- # 数据源配置
|
||||||
spring:
|
spring:
|
||||||
|
@ -11,27 +11,19 @@ spring.boot.admin.client:
|
|||||||
username: ruoyi
|
username: ruoyi
|
||||||
password: 123456
|
password: 123456
|
||||||
|
|
||||||
--- # xxl-job 配置
|
--- # powerjob 配置
|
||||||
xxl.job:
|
powerjob:
|
||||||
# 执行器开关
|
worker:
|
||||||
enabled: true
|
enabled: true
|
||||||
# 调度中心地址:如调度中心集群部署存在多个地址则用逗号分隔。
|
# 需要现在powerjob登录页执行应用注册后才能使用
|
||||||
admin-addresses: http://localhost:9100/xxl-job-admin
|
app-name: ruoyi-worker
|
||||||
# 执行器通讯TOKEN:非空时启用
|
enable-test-mode: false
|
||||||
access-token: xxl-job
|
max-appended-wf-context-length: 4096
|
||||||
executor:
|
max-result-length: 4096
|
||||||
# 执行器AppName:执行器心跳注册分组依据;为空则关闭自动注册
|
port: 27777
|
||||||
appname: xxl-job-executor
|
protocol: http
|
||||||
# 执行器端口号 执行器从9101开始往后写
|
server-address: 127.0.0.1:7700,127.0.0.1:7701
|
||||||
port: 9101
|
store-strategy: disk
|
||||||
# 执行器注册:默认IP:PORT
|
|
||||||
address:
|
|
||||||
# 执行器IP:默认自动获取IP
|
|
||||||
ip:
|
|
||||||
# 执行器运行日志文件存储磁盘路径
|
|
||||||
logpath: ./logs/xxl-job
|
|
||||||
# 执行器日志文件保存天数:大于3生效
|
|
||||||
logretentiondays: 30
|
|
||||||
|
|
||||||
--- # 数据源配置
|
--- # 数据源配置
|
||||||
spring:
|
spring:
|
||||||
|
@ -15,17 +15,21 @@
|
|||||||
ruoyi-common-job 定时任务
|
ruoyi-common-job 定时任务
|
||||||
</description>
|
</description>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- xxl-job-core -->
|
<!--PowerJob-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.xuxueli</groupId>
|
<groupId>tech.powerjob</groupId>
|
||||||
<artifactId>xxl-job-core</artifactId>
|
<artifactId>powerjob-worker-spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>tech.powerjob</groupId>
|
||||||
|
<artifactId>powerjob-official-processors</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -1,80 +0,0 @@
|
|||||||
package com.xxl.job.core.glue.impl;
|
|
||||||
|
|
||||||
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
|
|
||||||
import com.xxl.job.core.glue.GlueFactory;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
|
||||||
import org.springframework.core.annotation.AnnotationUtils;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author xuxueli 2018-11-01
|
|
||||||
*/
|
|
||||||
public class SpringGlueFactory extends GlueFactory {
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(SpringGlueFactory.class);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* inject action of spring
|
|
||||||
* @param instance
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void injectService(Object instance){
|
|
||||||
if (instance==null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (XxlJobSpringExecutor.getApplicationContext() == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Field[] fields = instance.getClass().getDeclaredFields();
|
|
||||||
for (Field field : fields) {
|
|
||||||
if (Modifier.isStatic(field.getModifiers())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object fieldBean = null;
|
|
||||||
// with bean-id, bean could be found by both @Resource and @Autowired, or bean could only be found by @Autowired
|
|
||||||
|
|
||||||
if (AnnotationUtils.getAnnotation(field, Resource.class) != null) {
|
|
||||||
try {
|
|
||||||
Resource resource = AnnotationUtils.getAnnotation(field, Resource.class);
|
|
||||||
if (resource.name()!=null && resource.name().length()>0){
|
|
||||||
fieldBean = XxlJobSpringExecutor.getApplicationContext().getBean(resource.name());
|
|
||||||
} else {
|
|
||||||
fieldBean = XxlJobSpringExecutor.getApplicationContext().getBean(field.getName());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
if (fieldBean==null ) {
|
|
||||||
fieldBean = XxlJobSpringExecutor.getApplicationContext().getBean(field.getType());
|
|
||||||
}
|
|
||||||
} else if (AnnotationUtils.getAnnotation(field, Autowired.class) != null) {
|
|
||||||
Qualifier qualifier = AnnotationUtils.getAnnotation(field, Qualifier.class);
|
|
||||||
if (qualifier!=null && qualifier.value()!=null && qualifier.value().length()>0) {
|
|
||||||
fieldBean = XxlJobSpringExecutor.getApplicationContext().getBean(qualifier.value());
|
|
||||||
} else {
|
|
||||||
fieldBean = XxlJobSpringExecutor.getApplicationContext().getBean(field.getType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fieldBean!=null) {
|
|
||||||
field.setAccessible(true);
|
|
||||||
try {
|
|
||||||
field.set(instance, fieldBean);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,21 @@
|
|||||||
|
package org.dromara.common.job.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
|
import tech.powerjob.worker.PowerJobWorker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动定时任务
|
||||||
|
* @author yhan219
|
||||||
|
* @since 2023/6/2
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnBean(PowerJobWorker.class)
|
||||||
|
@ConditionalOnProperty(prefix = "powerjob.worker", name = "enabled", havingValue = "true")
|
||||||
|
@EnableScheduling
|
||||||
|
public class PowerJobConfig {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,38 +0,0 @@
|
|||||||
package org.dromara.common.job.config;
|
|
||||||
|
|
||||||
import org.dromara.common.job.config.properties.XxlJobProperties;
|
|
||||||
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* xxl-job config
|
|
||||||
*
|
|
||||||
* @author Lion Li
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@AutoConfiguration
|
|
||||||
@EnableConfigurationProperties(XxlJobProperties.class)
|
|
||||||
@ConditionalOnProperty(prefix = "xxl.job", name = "enabled", havingValue = "true")
|
|
||||||
public class XxlJobConfig {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public XxlJobSpringExecutor xxlJobExecutor(XxlJobProperties xxlJobProperties) {
|
|
||||||
log.info(">>>>>>>>>>> xxl-job config init.");
|
|
||||||
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
|
|
||||||
xxlJobSpringExecutor.setAdminAddresses(xxlJobProperties.getAdminAddresses());
|
|
||||||
xxlJobSpringExecutor.setAccessToken(xxlJobProperties.getAccessToken());
|
|
||||||
XxlJobProperties.Executor executor = xxlJobProperties.getExecutor();
|
|
||||||
xxlJobSpringExecutor.setAppname(executor.getAppname());
|
|
||||||
xxlJobSpringExecutor.setAddress(executor.getAddress());
|
|
||||||
xxlJobSpringExecutor.setIp(executor.getIp());
|
|
||||||
xxlJobSpringExecutor.setPort(executor.getPort());
|
|
||||||
xxlJobSpringExecutor.setLogPath(executor.getLogPath());
|
|
||||||
xxlJobSpringExecutor.setLogRetentionDays(executor.getLogRetentionDays());
|
|
||||||
return xxlJobSpringExecutor;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
package org.dromara.common.job.config.properties;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* xxljob配置类
|
|
||||||
*
|
|
||||||
* @author Lion Li
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@ConfigurationProperties(prefix = "xxl.job")
|
|
||||||
public class XxlJobProperties {
|
|
||||||
|
|
||||||
private Boolean enabled;
|
|
||||||
|
|
||||||
private String adminAddresses;
|
|
||||||
|
|
||||||
private String accessToken;
|
|
||||||
|
|
||||||
private Executor executor;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@NoArgsConstructor
|
|
||||||
public static class Executor {
|
|
||||||
|
|
||||||
private String appname;
|
|
||||||
|
|
||||||
private String address;
|
|
||||||
|
|
||||||
private String ip;
|
|
||||||
|
|
||||||
private int port;
|
|
||||||
|
|
||||||
private String logPath;
|
|
||||||
|
|
||||||
private int logRetentionDays;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
org.dromara.common.job.config.XxlJobConfig
|
|
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
<module>ruoyi-monitor-admin</module>
|
<module>ruoyi-monitor-admin</module>
|
||||||
<module>ruoyi-xxl-job-admin</module>
|
<module>ruoyi-powerjob-server</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
63
ruoyi-extend/ruoyi-powerjob-server/pom.xml
Normal file
63
ruoyi-extend/ruoyi-powerjob-server/pom.xml
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<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/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.dromara</groupId>
|
||||||
|
<artifactId>ruoyi-extend</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
<groupId>org.dromara</groupId>
|
||||||
|
<artifactId>ruoyi-powerjob-server</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<spring-boot.version>2.7.4</spring-boot.version>
|
||||||
|
</properties>
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>${spring-boot.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- PowerJob server-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>tech.powerjob</groupId>
|
||||||
|
<artifactId>powerjob-server-starter</artifactId>
|
||||||
|
<version>${powerjob.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<finalName>${project.artifactId}</finalName>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<version>${spring-boot.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>repackage</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,45 @@
|
|||||||
|
package org.dromara.powerjob.server;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
|
import tech.powerjob.server.PowerJobServerApplication;
|
||||||
|
import tech.powerjob.server.common.utils.PropertyUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Admin 监控启动程序
|
||||||
|
*
|
||||||
|
* @author yhan219
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@EnableScheduling
|
||||||
|
@SpringBootApplication(scanBasePackages = "tech.powerjob.server")
|
||||||
|
public class RuoyiPowerJobServerApplication {
|
||||||
|
|
||||||
|
private static final String TIPS = "\n\n" +
|
||||||
|
"******************* PowerJob Tips *******************\n" +
|
||||||
|
"如果应用无法启动,我们建议您仔细阅读以下文档来解决:\n" +
|
||||||
|
"if server can't startup, we recommend that you read the documentation to find a solution:\n" +
|
||||||
|
"https://www.yuque.com/powerjob/guidence/problem\n" +
|
||||||
|
"******************* PowerJob Tips *******************\n\n";
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
pre();
|
||||||
|
|
||||||
|
// Start SpringBoot application.
|
||||||
|
try {
|
||||||
|
SpringApplication.run(PowerJobServerApplication.class, args);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
log.error(TIPS);
|
||||||
|
throw t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void pre() {
|
||||||
|
log.info(TIPS);
|
||||||
|
PropertyUtils.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
oms.env=DAILY
|
||||||
|
logging.config=classpath:logback-dev.xml
|
||||||
|
|
||||||
|
####### Database properties(Configure according to the the environment) #######
|
||||||
|
spring.datasource.core.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||||
|
spring.datasource.core.jdbc-url=jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
|
||||||
|
spring.datasource.core.username=root
|
||||||
|
spring.datasource.core.password=root
|
||||||
|
spring.datasource.core.maximum-pool-size=20
|
||||||
|
spring.datasource.core.minimum-idle=5
|
||||||
|
|
||||||
|
####### MongoDB properties(Non-core configuration properties) #######
|
||||||
|
####### delete mongodb config to disable mongodb #######
|
||||||
|
#oms.mongodb.enable=true
|
||||||
|
#spring.data.mongodb.uri=mongodb+srv://zqq:No1Bug2Please3!@cluster0.wie54.gcp.mongodb.net/powerjob_daily?retryWrites=true&w=majority
|
||||||
|
|
||||||
|
####### Email properties(Non-core configuration properties) #######
|
||||||
|
####### Delete the following code to disable the mail #######
|
||||||
|
#spring.mail.host=smtp.163.com
|
||||||
|
#spring.mail.username=zqq@163.com
|
||||||
|
#spring.mail.password=GOFZPNARMVKCGONV
|
||||||
|
#spring.mail.properties.mail.smtp.auth=true
|
||||||
|
#spring.mail.properties.mail.smtp.starttls.enable=true
|
||||||
|
#spring.mail.properties.mail.smtp.starttls.required=true
|
||||||
|
|
||||||
|
####### DingTalk properties(Non-core configuration properties) #######
|
||||||
|
####### Delete the following code to disable the DingTalk #######
|
||||||
|
#oms.alarm.ding.app-key=dingauqwkvxxnqskknfv
|
||||||
|
#oms.alarm.ding.app-secret=XWrEPdAZMPgJeFtHuL0LH73LRj-74umF2_0BFcoXMfvnX0pCQvt0rpb1JOJU_HLl
|
||||||
|
#oms.alarm.ding.agent-id=847044348
|
||||||
|
|
||||||
|
####### Resource cleaning properties #######
|
||||||
|
oms.instanceinfo.retention=1
|
||||||
|
oms.container.retention.local=1
|
||||||
|
oms.container.retention.remote=-1
|
||||||
|
|
||||||
|
####### Cache properties #######
|
||||||
|
oms.instance.metadata.cache.size=1024
|
||||||
|
|
||||||
|
####### Threshold in precise fetching server(0~100). 100 means full detection of server, in which #######
|
||||||
|
####### split-brain could be avoided while performance overhead would increase. #######
|
||||||
|
oms.accurate.select.server.percentage = 50
|
@ -0,0 +1,42 @@
|
|||||||
|
oms.env=PRE
|
||||||
|
logging.config=classpath:logback-product.xml
|
||||||
|
|
||||||
|
####### Database properties(Configure according to the the environment) #######
|
||||||
|
spring.datasource.core.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||||
|
spring.datasource.core.jdbc-url=jdbc:mysql://remotehost:3306/powerjob-pre?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
|
||||||
|
spring.datasource.core.username=root
|
||||||
|
spring.datasource.core.password=No1Bug2Please3!
|
||||||
|
spring.datasource.core.maximum-pool-size=20
|
||||||
|
spring.datasource.core.minimum-idle=5
|
||||||
|
|
||||||
|
####### MongoDB properties(Non-core configuration properties) #######
|
||||||
|
####### delete mongodb config to disable mongodb #######
|
||||||
|
oms.mongodb.enable=true
|
||||||
|
spring.data.mongodb.uri=mongodb://remotehost:27017/powerjob-pre
|
||||||
|
|
||||||
|
####### Email properties(Non-core configuration properties) #######
|
||||||
|
####### Delete the following code to disable the mail #######
|
||||||
|
spring.mail.host=smtp.qq.com
|
||||||
|
spring.mail.username=zqq
|
||||||
|
spring.mail.password=qqz
|
||||||
|
spring.mail.properties.mail.smtp.auth=true
|
||||||
|
spring.mail.properties.mail.smtp.starttls.enable=true
|
||||||
|
spring.mail.properties.mail.smtp.starttls.required=true
|
||||||
|
|
||||||
|
####### DingTalk properties(Non-core configuration properties) #######
|
||||||
|
####### Delete the following code to disable the DingTalk #######
|
||||||
|
oms.alarm.ding.app-key=dingauqwkvxxnqskknfv
|
||||||
|
oms.alarm.ding.app-secret=XWrEPdAZMPgJeFtHuL0LH73LRj-74umF2_0BFcoXMfvnX0pCQvt0rpb1JOJU_HLl
|
||||||
|
oms.alarm.ding.agent-id=847044348
|
||||||
|
|
||||||
|
####### Resource cleaning properties #######
|
||||||
|
oms.instanceinfo.retention=3
|
||||||
|
oms.container.retention.local=3
|
||||||
|
oms.container.retention.remote=-1
|
||||||
|
|
||||||
|
####### Cache properties #######
|
||||||
|
oms.instance.metadata.cache.size=1024
|
||||||
|
|
||||||
|
####### Threshold in precise fetching server(0~100). 100 means full detection of server, in which #######
|
||||||
|
####### split-brain could be avoided while performance overhead would increase. #######
|
||||||
|
oms.accurate.select.server.percentage = 50
|
@ -0,0 +1,42 @@
|
|||||||
|
oms.env=PRODUCT
|
||||||
|
logging.config=classpath:logback-product.xml
|
||||||
|
|
||||||
|
####### Database properties(Configure according to the the environment) #######
|
||||||
|
spring.datasource.core.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||||
|
spring.datasource.core.jdbc-url=jdbc:mysql://localhost:3306/powerjob-product?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
|
||||||
|
spring.datasource.core.username=root
|
||||||
|
spring.datasource.core.password=No1Bug2Please3!
|
||||||
|
spring.datasource.core.maximum-pool-size=20
|
||||||
|
spring.datasource.core.minimum-idle=5
|
||||||
|
|
||||||
|
####### MongoDB properties(Non-core configuration properties) #######
|
||||||
|
####### delete mongodb config to disable mongodb #######
|
||||||
|
oms.mongodb.enable=true
|
||||||
|
spring.data.mongodb.uri=mongodb://localhost:27017/powerjob-product
|
||||||
|
|
||||||
|
####### Email properties(Non-core configuration properties) #######
|
||||||
|
####### Delete the following code to disable the mail #######
|
||||||
|
spring.mail.host=smtp.qq.com
|
||||||
|
spring.mail.username=zqq
|
||||||
|
spring.mail.password=qqz
|
||||||
|
spring.mail.properties.mail.smtp.auth=true
|
||||||
|
spring.mail.properties.mail.smtp.starttls.enable=true
|
||||||
|
spring.mail.properties.mail.smtp.starttls.required=true
|
||||||
|
|
||||||
|
####### DingTalk properties(Non-core configuration properties) #######
|
||||||
|
####### Delete the following code to disable the DingTalk #######
|
||||||
|
oms.alarm.ding.app-key=
|
||||||
|
oms.alarm.ding.app-secret=
|
||||||
|
oms.alarm.ding.agent-id=
|
||||||
|
|
||||||
|
####### Resource cleaning properties #######
|
||||||
|
oms.instanceinfo.retention=7
|
||||||
|
oms.container.retention.local=7
|
||||||
|
oms.container.retention.remote=-1
|
||||||
|
|
||||||
|
####### Cache properties #######
|
||||||
|
oms.instance.metadata.cache.size=2048
|
||||||
|
|
||||||
|
####### Threshold in precise fetching server(0~100). 100 means full detection of server, in which #######
|
||||||
|
####### split-brain could be avoided while performance overhead would increase. #######
|
||||||
|
oms.accurate.select.server.percentage = 50
|
@ -0,0 +1,22 @@
|
|||||||
|
# Http server port
|
||||||
|
server.port=7700
|
||||||
|
|
||||||
|
spring.profiles.active=daily
|
||||||
|
spring.main.banner-mode=log
|
||||||
|
spring.jpa.open-in-view=false
|
||||||
|
spring.data.mongodb.repositories.type=none
|
||||||
|
logging.level.org.mongodb=warn
|
||||||
|
|
||||||
|
# Configuration for uploading files.
|
||||||
|
spring.servlet.multipart.enabled=true
|
||||||
|
spring.servlet.multipart.file-size-threshold=0
|
||||||
|
spring.servlet.multipart.max-file-size=209715200
|
||||||
|
spring.servlet.multipart.max-request-size=209715200
|
||||||
|
|
||||||
|
###### PowerJob transporter configuration ######
|
||||||
|
oms.transporter.active.protocols=AKKA,HTTP
|
||||||
|
oms.transporter.main.protocol=HTTP
|
||||||
|
oms.akka.port=10086
|
||||||
|
oms.http.port=10010
|
||||||
|
# Prefix for all tables. Default empty string. Config if you have needs, i.e. pj_
|
||||||
|
oms.table-prefix=pj_
|
@ -0,0 +1,15 @@
|
|||||||
|
${AnsiColor.GREEN}
|
||||||
|
███████ ██ ██
|
||||||
|
░██░░░░██ ░██ ░██
|
||||||
|
░██ ░██ ██████ ███ ██ █████ ██████ ░██ ██████ ░██
|
||||||
|
░███████ ██░░░░██░░██ █ ░██ ██░░░██░░██░░█ ░██ ██░░░░██░██████
|
||||||
|
░██░░░░ ░██ ░██ ░██ ███░██░███████ ░██ ░ ░██░██ ░██░██░░░██
|
||||||
|
░██ ░██ ░██ ░████░████░██░░░░ ░██ ██ ░██░██ ░██░██ ░██
|
||||||
|
░██ ░░██████ ███░ ░░░██░░██████░███ ░░█████ ░░██████ ░██████
|
||||||
|
░░ ░░░░░░ ░░░ ░░░ ░░░░░░ ░░░ ░░░░░ ░░░░░░ ░░░░░
|
||||||
|
${AnsiColor.BRIGHT_RED}
|
||||||
|
* Maintainer: tengjiqi@gmail.com & Team PowerJob
|
||||||
|
* OfficialWebsite: http://www.powerjob.tech/
|
||||||
|
* SourceCode: https://github.com/PowerJob/PowerJob
|
||||||
|
* PoweredBy: SpringBoot${spring-boot.formatted-version}
|
||||||
|
${AnsiColor.DEFAULT}
|
@ -0,0 +1,132 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<included>
|
||||||
|
|
||||||
|
<property name="MONITOR_LOG_PATH" value="${LOG_PATH}/monitors"/>
|
||||||
|
<property name="ROTATE_PATTERN" value="%d{yyyy-MM-dd}.%i"/>
|
||||||
|
|
||||||
|
<property name="MONITOR_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS}|%thread|%X{serverId}|%msg%n"/>
|
||||||
|
|
||||||
|
<!-- database -->
|
||||||
|
<appender name="MONITOR_LOGGER_DB_OPERATION_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${MONITOR_LOG_PATH}/database.log</file>
|
||||||
|
<encoder>
|
||||||
|
<pattern>${MONITOR_LOG_PATTERN}</pattern>
|
||||||
|
<charset>UTF-8</charset>
|
||||||
|
</encoder>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>${MONITOR_LOG_PATH}/database.log.${ROTATE_PATTERN}</fileNamePattern>
|
||||||
|
<maxHistory>3</maxHistory>
|
||||||
|
<maxFileSize>200MB</maxFileSize>
|
||||||
|
<totalSizeCap>1000MB</totalSizeCap>
|
||||||
|
</rollingPolicy>
|
||||||
|
</appender>
|
||||||
|
<appender name="ASYNC_MONITOR_LOGGER_DB_OPERATION_APPENDER" class="ch.qos.logback.classic.AsyncAppender">
|
||||||
|
<queueSize>512</queueSize>
|
||||||
|
<discardingThreshold>0</discardingThreshold>
|
||||||
|
<neverBlock>true</neverBlock>
|
||||||
|
<appender-ref ref="MONITOR_LOGGER_DB_OPERATION_APPENDER"/>
|
||||||
|
</appender>
|
||||||
|
<logger name="MONITOR_LOGGER_DB_OPERATION" level="INFO" additivity="false">
|
||||||
|
<appender-ref ref="ASYNC_MONITOR_LOGGER_DB_OPERATION_APPENDER"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- TtReportInstanceStatusEvent -->
|
||||||
|
<appender name="MONITOR_LOGGER_TT_REPORT_STATUS_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${MONITOR_LOG_PATH}/tt_status_report.log</file>
|
||||||
|
<encoder>
|
||||||
|
<pattern>${MONITOR_LOG_PATTERN}</pattern>
|
||||||
|
<charset>UTF-8</charset>
|
||||||
|
</encoder>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>${MONITOR_LOG_PATH}/tt_status_report.log.${ROTATE_PATTERN}</fileNamePattern>
|
||||||
|
<maxHistory>3</maxHistory>
|
||||||
|
<maxFileSize>200MB</maxFileSize>
|
||||||
|
<totalSizeCap>1000MB</totalSizeCap>
|
||||||
|
</rollingPolicy>
|
||||||
|
</appender>
|
||||||
|
<appender name="ASYNC_MONITOR_LOGGER_TT_REPORT_STATUS_APPENDER" class="ch.qos.logback.classic.AsyncAppender">
|
||||||
|
<queueSize>512</queueSize>
|
||||||
|
<discardingThreshold>0</discardingThreshold>
|
||||||
|
<neverBlock>true</neverBlock>
|
||||||
|
<appender-ref ref="MONITOR_LOGGER_TT_REPORT_STATUS_APPENDER"/>
|
||||||
|
</appender>
|
||||||
|
<logger name="MONITOR_LOGGER_TT_REPORT_STATUS" level="INFO" additivity="false">
|
||||||
|
<appender-ref ref="ASYNC_MONITOR_LOGGER_TT_REPORT_STATUS_APPENDER"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<!-- WorkerHeartbeatEvent -->
|
||||||
|
<appender name="MONITOR_LOGGER_WORKER_HEART_BEAT_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${MONITOR_LOG_PATH}/worker_heartbeat.log</file>
|
||||||
|
<encoder>
|
||||||
|
<pattern>${MONITOR_LOG_PATTERN}</pattern>
|
||||||
|
<charset>UTF-8</charset>
|
||||||
|
</encoder>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>${MONITOR_LOG_PATH}/worker_heartbeat.log.${ROTATE_PATTERN}</fileNamePattern>
|
||||||
|
<maxHistory>3</maxHistory>
|
||||||
|
<maxFileSize>200MB</maxFileSize>
|
||||||
|
<totalSizeCap>1000MB</totalSizeCap>
|
||||||
|
</rollingPolicy>
|
||||||
|
</appender>
|
||||||
|
<appender name="ASYNC_MONITOR_LOGGER_WORKER_HEART_BEAT_APPENDER" class="ch.qos.logback.classic.AsyncAppender">
|
||||||
|
<queueSize>512</queueSize>
|
||||||
|
<discardingThreshold>0</discardingThreshold>
|
||||||
|
<neverBlock>true</neverBlock>
|
||||||
|
<appender-ref ref="MONITOR_LOGGER_WORKER_HEART_BEAT_APPENDER"/>
|
||||||
|
</appender>
|
||||||
|
<logger name="MONITOR_LOGGER_WORKER_HEART_BEAT" level="INFO" additivity="false">
|
||||||
|
<appender-ref ref="ASYNC_MONITOR_LOGGER_WORKER_HEART_BEAT_APPENDER"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- WorkerLogReportEvent -->
|
||||||
|
<appender name="MONITOR_LOGGER_WORKER_LOG_REPORT_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${MONITOR_LOG_PATH}/worker_log_report.log</file>
|
||||||
|
<encoder>
|
||||||
|
<pattern>${MONITOR_LOG_PATTERN}</pattern>
|
||||||
|
<charset>UTF-8</charset>
|
||||||
|
</encoder>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>${MONITOR_LOG_PATH}/worker_log_report.log.${ROTATE_PATTERN}</fileNamePattern>
|
||||||
|
<maxHistory>3</maxHistory>
|
||||||
|
<maxFileSize>200MB</maxFileSize>
|
||||||
|
<totalSizeCap>1000MB</totalSizeCap>
|
||||||
|
</rollingPolicy>
|
||||||
|
</appender>
|
||||||
|
<appender name="ASYNC_MONITOR_LOGGER_WORKER_LOG_REPORT_APPENDER" class="ch.qos.logback.classic.AsyncAppender">
|
||||||
|
<queueSize>512</queueSize>
|
||||||
|
<discardingThreshold>0</discardingThreshold>
|
||||||
|
<neverBlock>true</neverBlock>
|
||||||
|
<appender-ref ref="MONITOR_LOGGER_WORKER_LOG_REPORT_APPENDER"/>
|
||||||
|
</appender>
|
||||||
|
<logger name="MONITOR_LOGGER_WORKER_LOG_REPORT" level="INFO" additivity="false">
|
||||||
|
<appender-ref ref="ASYNC_MONITOR_LOGGER_WORKER_LOG_REPORT_APPENDER"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- SlowLockEvent -->
|
||||||
|
<appender name="MONITOR_LOGGER_SLOW_LOCK_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${MONITOR_LOG_PATH}/lock.log</file>
|
||||||
|
<encoder>
|
||||||
|
<pattern>${MONITOR_LOG_PATTERN}</pattern>
|
||||||
|
<charset>UTF-8</charset>
|
||||||
|
</encoder>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>${MONITOR_LOG_PATH}/lock.log.${ROTATE_PATTERN}</fileNamePattern>
|
||||||
|
<maxHistory>3</maxHistory>
|
||||||
|
<maxFileSize>200MB</maxFileSize>
|
||||||
|
<totalSizeCap>1000MB</totalSizeCap>
|
||||||
|
</rollingPolicy>
|
||||||
|
</appender>
|
||||||
|
<appender name="ASYNC_MONITOR_LOGGER_SLOW_LOCK_APPENDER" class="ch.qos.logback.classic.AsyncAppender">
|
||||||
|
<queueSize>512</queueSize>
|
||||||
|
<discardingThreshold>0</discardingThreshold>
|
||||||
|
<neverBlock>true</neverBlock>
|
||||||
|
<appender-ref ref="MONITOR_LOGGER_SLOW_LOCK_APPENDER"/>
|
||||||
|
</appender>
|
||||||
|
<logger name="MONITOR_LOGGER_SLOW_LOCK" level="INFO" additivity="false">
|
||||||
|
<appender-ref ref="ASYNC_MONITOR_LOGGER_SLOW_LOCK_APPENDER"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
</included>
|
@ -0,0 +1,38 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!-- Configuration for local environment, all logs would print in console. -->
|
||||||
|
<configuration>
|
||||||
|
<!-- Configure color for logs. -->
|
||||||
|
<!-- Classes for rendering color. -->
|
||||||
|
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
|
||||||
|
<conversionRule conversionWord="wex"
|
||||||
|
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
|
||||||
|
<conversionRule conversionWord="wEx"
|
||||||
|
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
|
||||||
|
<!-- Color log pattern. -->
|
||||||
|
<property name="CONSOLE_LOG_PATTERN"
|
||||||
|
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{20}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
|
||||||
|
|
||||||
|
<logger name="MONITOR_LOGGER_DB_OPERATION" level="OFF"/>
|
||||||
|
|
||||||
|
<!-- Configuration for console output. -->
|
||||||
|
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
|
||||||
|
<charset>utf8</charset>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<!-- Quit timing logs, which seems disordered. -->
|
||||||
|
<logger name="tech.powerjob.server.service.timing" level="WARN" additivity="false">
|
||||||
|
<appender-ref ref="CONSOLE"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<logger name="tech.powerjob" level="DEBUG" additivity="false">
|
||||||
|
<appender-ref ref="CONSOLE"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="CONSOLE"/>
|
||||||
|
</root>
|
||||||
|
|
||||||
|
</configuration>
|
@ -0,0 +1,78 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!-- Configuration for production environment. -->
|
||||||
|
<configuration>
|
||||||
|
|
||||||
|
<!-- Default configuration. -->
|
||||||
|
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
|
||||||
|
<!-- Configuration for console. -->
|
||||||
|
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Log path, pay attention to permission, logs may be unable to generate.
|
||||||
|
Bug recording: Setting `~/logs`, is unable to create folder in user home directory,
|
||||||
|
a folder with the name ~ is created in project folder.
|
||||||
|
-->
|
||||||
|
<property name="LOG_PATH" value="${user.home}/powerjob/server/logs"/>
|
||||||
|
|
||||||
|
<!-- include other logback configs -->
|
||||||
|
<include resource="logback-config/powerjob_monitor.xml"/>
|
||||||
|
|
||||||
|
<!-- Configuration for ERROR logs. All error logs will write twice. -->
|
||||||
|
<appender name="ERROR_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${LOG_PATH}/powerjob-server-error.log</file>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<FileNamePattern>${LOG_PATH}/powerjob-server-error.%d{yyyy-MM-dd}.log</FileNamePattern>
|
||||||
|
<MaxHistory>7</MaxHistory>
|
||||||
|
</rollingPolicy>
|
||||||
|
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||||
|
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{20} - %msg%n</pattern>
|
||||||
|
<charset>UTF-8</charset>
|
||||||
|
</encoder>
|
||||||
|
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||||
|
<level>ERROR</level>
|
||||||
|
<onMatch>ACCEPT</onMatch>
|
||||||
|
<onMismatch>DENY</onMismatch>
|
||||||
|
</filter>
|
||||||
|
</appender>
|
||||||
|
<!-- End of configuration for ERROR logs. -->
|
||||||
|
|
||||||
|
<!-- Configuration for Web services. -->
|
||||||
|
<appender name="WEB_LOG_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${LOG_PATH}/powerjob-server-web.log</file>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<FileNamePattern>${LOG_PATH}/powerjob-server-web.%d{yyyy-MM-dd}.log</FileNamePattern>
|
||||||
|
<MaxHistory>7</MaxHistory>
|
||||||
|
</rollingPolicy>
|
||||||
|
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||||
|
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level - %msg%n</pattern>
|
||||||
|
<charset>UTF-8</charset>
|
||||||
|
</encoder>
|
||||||
|
<append>true</append>
|
||||||
|
</appender>
|
||||||
|
<logger name="WEB_LOG" level="INFO" additivity="false">
|
||||||
|
<appender-ref ref="WEB_LOG_APPENDER"/>
|
||||||
|
</logger>
|
||||||
|
<!-- End of configuration for Web services. -->
|
||||||
|
|
||||||
|
<!-- Configuration for system logs. -->
|
||||||
|
<appender name="DEFAULT_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${LOG_PATH}/powerjob-server-application.log</file>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<FileNamePattern>${LOG_PATH}/powerjob-server-application.%d{yyyy-MM-dd}.log</FileNamePattern>
|
||||||
|
<MaxHistory>7</MaxHistory>
|
||||||
|
</rollingPolicy>
|
||||||
|
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||||
|
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{20} - %msg%n</pattern>
|
||||||
|
<charset>UTF-8</charset>
|
||||||
|
</encoder>
|
||||||
|
<append>true</append>
|
||||||
|
</appender>
|
||||||
|
<!-- End of configuration for system logs. -->
|
||||||
|
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="CONSOLE"/>
|
||||||
|
<appender-ref ref="DEFAULT_APPENDER"/>
|
||||||
|
<appender-ref ref="ERROR_APPENDER"/>
|
||||||
|
</root>
|
||||||
|
|
||||||
|
</configuration>
|
@ -1,16 +0,0 @@
|
|||||||
FROM findepi/graalvm:java17-native
|
|
||||||
|
|
||||||
MAINTAINER Lion Li
|
|
||||||
|
|
||||||
RUN mkdir -p /ruoyi/xxljob/logs
|
|
||||||
|
|
||||||
WORKDIR /ruoyi/xxljob
|
|
||||||
|
|
||||||
ENV TZ=PRC
|
|
||||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
|
||||||
|
|
||||||
EXPOSE 9100
|
|
||||||
|
|
||||||
ADD ./target/ruoyi-xxl-job-admin.jar ./app.jar
|
|
||||||
|
|
||||||
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
|
|
@ -1,111 +0,0 @@
|
|||||||
<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">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<parent>
|
|
||||||
<artifactId>ruoyi-extend</artifactId>
|
|
||||||
<groupId>org.dromara</groupId>
|
|
||||||
<version>${revision}</version>
|
|
||||||
</parent>
|
|
||||||
<artifactId>ruoyi-xxl-job-admin</artifactId>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<spring-boot.version>2.7.12</spring-boot.version>
|
|
||||||
<spring-boot-admin.version>2.7.10</spring-boot-admin.version>
|
|
||||||
<mybatis-spring-boot.version>2.2.2</mybatis-spring-boot.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<dependencyManagement>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
|
||||||
<version>${spring-boot.version}</version>
|
|
||||||
<type>pom</type>
|
|
||||||
<scope>import</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</dependencyManagement>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
|
|
||||||
<!-- starter-web:spring-webmvc + autoconfigure + logback + yaml + tomcat -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<!-- starter-test:junit + spring-test + mockito -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- freemarker-starter -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-freemarker</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- mail-starter -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-mail</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- starter-actuator -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-aop</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- mybatis-starter:mybatis + mybatis-spring + hikari(default) -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mybatis.spring.boot</groupId>
|
|
||||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
|
||||||
<version>${mybatis-spring-boot.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- mysql -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.mysql</groupId>
|
|
||||||
<artifactId>mysql-connector-j</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>de.codecentric</groupId>
|
|
||||||
<artifactId>spring-boot-admin-starter-client</artifactId>
|
|
||||||
<version>${spring-boot-admin.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- xxl-job-core -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.xuxueli</groupId>
|
|
||||||
<artifactId>xxl-job-core</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<finalName>${project.artifactId}</finalName>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
|
||||||
<version>${spring-boot.version}</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<goals>
|
|
||||||
<goal>repackage</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
</project>
|
|
@ -1,16 +0,0 @@
|
|||||||
package com.xxl.job.admin;
|
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author xuxueli 2018-10-28 00:38:13
|
|
||||||
*/
|
|
||||||
@SpringBootApplication
|
|
||||||
public class XxlJobAdminApplication {
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
SpringApplication.run(XxlJobAdminApplication.class, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,97 +0,0 @@
|
|||||||
package com.xxl.job.admin.controller;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.controller.annotation.PermissionLimit;
|
|
||||||
import com.xxl.job.admin.service.LoginService;
|
|
||||||
import com.xxl.job.admin.service.XxlJobService;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import org.springframework.beans.propertyeditors.CustomDateEditor;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.ui.Model;
|
|
||||||
import org.springframework.web.bind.WebDataBinder;
|
|
||||||
import org.springframework.web.bind.annotation.InitBinder;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
|
||||||
import org.springframework.web.servlet.view.RedirectView;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* index controller
|
|
||||||
*
|
|
||||||
* @author xuxueli 2015-12-19 16:13:16
|
|
||||||
*/
|
|
||||||
@Controller
|
|
||||||
public class IndexController {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private XxlJobService xxlJobService;
|
|
||||||
@Resource
|
|
||||||
private LoginService loginService;
|
|
||||||
|
|
||||||
|
|
||||||
@RequestMapping("/")
|
|
||||||
public String index(Model model) {
|
|
||||||
|
|
||||||
Map<String, Object> dashboardMap = xxlJobService.dashboardInfo();
|
|
||||||
model.addAllAttributes(dashboardMap);
|
|
||||||
|
|
||||||
return "index";
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/chartInfo")
|
|
||||||
@ResponseBody
|
|
||||||
public ReturnT<Map<String, Object>> chartInfo(Date startDate, Date endDate) {
|
|
||||||
ReturnT<Map<String, Object>> chartInfo = xxlJobService.chartInfo(startDate, endDate);
|
|
||||||
return chartInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/toLogin")
|
|
||||||
@PermissionLimit(limit = false)
|
|
||||||
public ModelAndView toLogin(HttpServletRequest request, HttpServletResponse response, ModelAndView modelAndView) {
|
|
||||||
if (loginService.ifLogin(request, response) != null) {
|
|
||||||
modelAndView.setView(new RedirectView("/", true, false));
|
|
||||||
return modelAndView;
|
|
||||||
}
|
|
||||||
return new ModelAndView("login");
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping(value = "login", method = RequestMethod.POST)
|
|
||||||
@ResponseBody
|
|
||||||
@PermissionLimit(limit = false)
|
|
||||||
public ReturnT<String> loginDo(HttpServletRequest request, HttpServletResponse response, String userName, String password, String ifRemember) {
|
|
||||||
boolean ifRem = (ifRemember != null && ifRemember.trim().length() > 0 && "on".equals(ifRemember)) ? true : false;
|
|
||||||
return loginService.login(request, response, userName, password, ifRem);
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping(value = "logout", method = RequestMethod.POST)
|
|
||||||
@ResponseBody
|
|
||||||
@PermissionLimit(limit = false)
|
|
||||||
public ReturnT<String> logout(HttpServletRequest request, HttpServletResponse response) {
|
|
||||||
return loginService.logout(request, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/help")
|
|
||||||
public String help() {
|
|
||||||
|
|
||||||
/*if (!PermissionInterceptor.ifLogin(request)) {
|
|
||||||
return "redirect:/toLogin";
|
|
||||||
}*/
|
|
||||||
|
|
||||||
return "help";
|
|
||||||
}
|
|
||||||
|
|
||||||
@InitBinder
|
|
||||||
public void initBinder(WebDataBinder binder) {
|
|
||||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
||||||
dateFormat.setLenient(false);
|
|
||||||
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
package com.xxl.job.admin.controller;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.controller.annotation.PermissionLimit;
|
|
||||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
|
||||||
import com.xxl.job.core.biz.AdminBiz;
|
|
||||||
import com.xxl.job.core.biz.model.HandleCallbackParam;
|
|
||||||
import com.xxl.job.core.biz.model.RegistryParam;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import com.xxl.job.core.util.GsonTool;
|
|
||||||
import com.xxl.job.core.util.XxlJobRemotingUtil;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by xuxueli on 17/5/10.
|
|
||||||
*/
|
|
||||||
@Controller
|
|
||||||
@RequestMapping("/api")
|
|
||||||
public class JobApiController {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private AdminBiz adminBiz;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* api
|
|
||||||
*
|
|
||||||
* @param uri
|
|
||||||
* @param data
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@RequestMapping("/{uri}")
|
|
||||||
@ResponseBody
|
|
||||||
@PermissionLimit(limit = false)
|
|
||||||
public ReturnT<String> api(HttpServletRequest request, @PathVariable("uri") String uri, @RequestBody(required = false) String data) {
|
|
||||||
|
|
||||||
// valid
|
|
||||||
if (!"POST".equalsIgnoreCase(request.getMethod())) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, "invalid request, HttpMethod not support.");
|
|
||||||
}
|
|
||||||
if (uri == null || uri.trim().length() == 0) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, "invalid request, uri-mapping empty.");
|
|
||||||
}
|
|
||||||
if (XxlJobAdminConfig.getAdminConfig().getAccessToken() != null
|
|
||||||
&& XxlJobAdminConfig.getAdminConfig().getAccessToken().trim().length() > 0
|
|
||||||
&& !XxlJobAdminConfig.getAdminConfig().getAccessToken().equals(request.getHeader(XxlJobRemotingUtil.XXL_JOB_ACCESS_TOKEN))) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, "The access token is wrong.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// services mapping
|
|
||||||
if ("callback".equals(uri)) {
|
|
||||||
List<HandleCallbackParam> callbackParamList = GsonTool.fromJson(data, List.class, HandleCallbackParam.class);
|
|
||||||
return adminBiz.callback(callbackParamList);
|
|
||||||
} else if ("registry".equals(uri)) {
|
|
||||||
RegistryParam registryParam = GsonTool.fromJson(data, RegistryParam.class);
|
|
||||||
return adminBiz.registry(registryParam);
|
|
||||||
} else if ("registryRemove".equals(uri)) {
|
|
||||||
RegistryParam registryParam = GsonTool.fromJson(data, RegistryParam.class);
|
|
||||||
return adminBiz.registryRemove(registryParam);
|
|
||||||
} else {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, "invalid request, uri-mapping(" + uri + ") not found.");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,97 +0,0 @@
|
|||||||
package com.xxl.job.admin.controller;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobLogGlue;
|
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
|
||||||
import com.xxl.job.admin.dao.XxlJobInfoDao;
|
|
||||||
import com.xxl.job.admin.dao.XxlJobLogGlueDao;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import com.xxl.job.core.glue.GlueTypeEnum;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.ui.Model;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* job code controller
|
|
||||||
*
|
|
||||||
* @author xuxueli 2015-12-19 16:13:16
|
|
||||||
*/
|
|
||||||
@Controller
|
|
||||||
@RequestMapping("/jobcode")
|
|
||||||
public class JobCodeController {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private XxlJobInfoDao xxlJobInfoDao;
|
|
||||||
@Resource
|
|
||||||
private XxlJobLogGlueDao xxlJobLogGlueDao;
|
|
||||||
|
|
||||||
@RequestMapping
|
|
||||||
public String index(HttpServletRequest request, Model model, int jobId) {
|
|
||||||
XxlJobInfo jobInfo = xxlJobInfoDao.loadById(jobId);
|
|
||||||
List<XxlJobLogGlue> jobLogGlues = xxlJobLogGlueDao.findByJobId(jobId);
|
|
||||||
|
|
||||||
if (jobInfo == null) {
|
|
||||||
throw new RuntimeException(I18nUtil.getString("jobinfo_glue_jobid_unvalid"));
|
|
||||||
}
|
|
||||||
if (GlueTypeEnum.BEAN == GlueTypeEnum.match(jobInfo.getGlueType())) {
|
|
||||||
throw new RuntimeException(I18nUtil.getString("jobinfo_glue_gluetype_unvalid"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// valid permission
|
|
||||||
JobInfoController.validPermission(request, jobInfo.getJobGroup());
|
|
||||||
|
|
||||||
// Glue类型-字典
|
|
||||||
model.addAttribute("GlueTypeEnum", GlueTypeEnum.values());
|
|
||||||
|
|
||||||
model.addAttribute("jobInfo", jobInfo);
|
|
||||||
model.addAttribute("jobLogGlues", jobLogGlues);
|
|
||||||
return "jobcode/jobcode.index";
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/save")
|
|
||||||
@ResponseBody
|
|
||||||
public ReturnT<String> save(Model model, int id, String glueSource, String glueRemark) {
|
|
||||||
// valid
|
|
||||||
if (glueRemark == null) {
|
|
||||||
return new ReturnT<String>(500, (I18nUtil.getString("system_please_input") + I18nUtil.getString("jobinfo_glue_remark")));
|
|
||||||
}
|
|
||||||
if (glueRemark.length() < 4 || glueRemark.length() > 100) {
|
|
||||||
return new ReturnT<String>(500, I18nUtil.getString("jobinfo_glue_remark_limit"));
|
|
||||||
}
|
|
||||||
XxlJobInfo exists_jobInfo = xxlJobInfoDao.loadById(id);
|
|
||||||
if (exists_jobInfo == null) {
|
|
||||||
return new ReturnT<String>(500, I18nUtil.getString("jobinfo_glue_jobid_unvalid"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// update new code
|
|
||||||
exists_jobInfo.setGlueSource(glueSource);
|
|
||||||
exists_jobInfo.setGlueRemark(glueRemark);
|
|
||||||
exists_jobInfo.setGlueUpdatetime(new Date());
|
|
||||||
|
|
||||||
exists_jobInfo.setUpdateTime(new Date());
|
|
||||||
xxlJobInfoDao.update(exists_jobInfo);
|
|
||||||
|
|
||||||
// log old code
|
|
||||||
XxlJobLogGlue xxlJobLogGlue = new XxlJobLogGlue();
|
|
||||||
xxlJobLogGlue.setJobId(exists_jobInfo.getId());
|
|
||||||
xxlJobLogGlue.setGlueType(exists_jobInfo.getGlueType());
|
|
||||||
xxlJobLogGlue.setGlueSource(glueSource);
|
|
||||||
xxlJobLogGlue.setGlueRemark(glueRemark);
|
|
||||||
|
|
||||||
xxlJobLogGlue.setAddTime(new Date());
|
|
||||||
xxlJobLogGlue.setUpdateTime(new Date());
|
|
||||||
xxlJobLogGlueDao.save(xxlJobLogGlue);
|
|
||||||
|
|
||||||
// remove code backup more than 30
|
|
||||||
xxlJobLogGlueDao.removeOld(exists_jobInfo.getId(), 30);
|
|
||||||
|
|
||||||
return ReturnT.SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,205 +0,0 @@
|
|||||||
package com.xxl.job.admin.controller;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.controller.annotation.PermissionLimit;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobGroup;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobRegistry;
|
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
|
||||||
import com.xxl.job.admin.dao.XxlJobGroupDao;
|
|
||||||
import com.xxl.job.admin.dao.XxlJobInfoDao;
|
|
||||||
import com.xxl.job.admin.dao.XxlJobRegistryDao;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import com.xxl.job.core.enums.RegistryConfig;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.ui.Model;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* job group controller
|
|
||||||
*
|
|
||||||
* @author xuxueli 2016-10-02 20:52:56
|
|
||||||
*/
|
|
||||||
@Controller
|
|
||||||
@RequestMapping("/jobgroup")
|
|
||||||
public class JobGroupController {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
public XxlJobInfoDao xxlJobInfoDao;
|
|
||||||
@Resource
|
|
||||||
public XxlJobGroupDao xxlJobGroupDao;
|
|
||||||
@Resource
|
|
||||||
private XxlJobRegistryDao xxlJobRegistryDao;
|
|
||||||
|
|
||||||
@RequestMapping
|
|
||||||
@PermissionLimit(adminuser = true)
|
|
||||||
public String index(Model model) {
|
|
||||||
return "jobgroup/jobgroup.index";
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/pageList")
|
|
||||||
@ResponseBody
|
|
||||||
@PermissionLimit(adminuser = true)
|
|
||||||
public Map<String, Object> pageList(HttpServletRequest request,
|
|
||||||
@RequestParam(required = false, defaultValue = "0") int start,
|
|
||||||
@RequestParam(required = false, defaultValue = "10") int length,
|
|
||||||
String appname, String title) {
|
|
||||||
|
|
||||||
// page query
|
|
||||||
List<XxlJobGroup> list = xxlJobGroupDao.pageList(start, length, appname, title);
|
|
||||||
int list_count = xxlJobGroupDao.pageListCount(start, length, appname, title);
|
|
||||||
|
|
||||||
// package result
|
|
||||||
Map<String, Object> maps = new HashMap<String, Object>();
|
|
||||||
maps.put("recordsTotal", list_count); // 总记录数
|
|
||||||
maps.put("recordsFiltered", list_count); // 过滤后的总记录数
|
|
||||||
maps.put("data", list); // 分页列表
|
|
||||||
return maps;
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/save")
|
|
||||||
@ResponseBody
|
|
||||||
@PermissionLimit(adminuser = true)
|
|
||||||
public ReturnT<String> save(XxlJobGroup xxlJobGroup) {
|
|
||||||
|
|
||||||
// valid
|
|
||||||
if (xxlJobGroup.getAppname() == null || xxlJobGroup.getAppname().trim().length() == 0) {
|
|
||||||
return new ReturnT<String>(500, (I18nUtil.getString("system_please_input") + "AppName"));
|
|
||||||
}
|
|
||||||
if (xxlJobGroup.getAppname().length() < 4 || xxlJobGroup.getAppname().length() > 64) {
|
|
||||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_appname_length"));
|
|
||||||
}
|
|
||||||
if (xxlJobGroup.getAppname().contains(">") || xxlJobGroup.getAppname().contains("<")) {
|
|
||||||
return new ReturnT<String>(500, "AppName" + I18nUtil.getString("system_unvalid"));
|
|
||||||
}
|
|
||||||
if (xxlJobGroup.getTitle() == null || xxlJobGroup.getTitle().trim().length() == 0) {
|
|
||||||
return new ReturnT<String>(500, (I18nUtil.getString("system_please_input") + I18nUtil.getString("jobgroup_field_title")));
|
|
||||||
}
|
|
||||||
if (xxlJobGroup.getTitle().contains(">") || xxlJobGroup.getTitle().contains("<")) {
|
|
||||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_title") + I18nUtil.getString("system_unvalid"));
|
|
||||||
}
|
|
||||||
if (xxlJobGroup.getAddressType() != 0) {
|
|
||||||
if (xxlJobGroup.getAddressList() == null || xxlJobGroup.getAddressList().trim().length() == 0) {
|
|
||||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_addressType_limit"));
|
|
||||||
}
|
|
||||||
if (xxlJobGroup.getAddressList().contains(">") || xxlJobGroup.getAddressList().contains("<")) {
|
|
||||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_registryList") + I18nUtil.getString("system_unvalid"));
|
|
||||||
}
|
|
||||||
|
|
||||||
String[] addresss = xxlJobGroup.getAddressList().split(",");
|
|
||||||
for (String item : addresss) {
|
|
||||||
if (item == null || item.trim().length() == 0) {
|
|
||||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_registryList_unvalid"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// process
|
|
||||||
xxlJobGroup.setUpdateTime(new Date());
|
|
||||||
|
|
||||||
int ret = xxlJobGroupDao.save(xxlJobGroup);
|
|
||||||
return (ret > 0) ? ReturnT.SUCCESS : ReturnT.FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/update")
|
|
||||||
@ResponseBody
|
|
||||||
@PermissionLimit(adminuser = true)
|
|
||||||
public ReturnT<String> update(XxlJobGroup xxlJobGroup) {
|
|
||||||
// valid
|
|
||||||
if (xxlJobGroup.getAppname() == null || xxlJobGroup.getAppname().trim().length() == 0) {
|
|
||||||
return new ReturnT<String>(500, (I18nUtil.getString("system_please_input") + "AppName"));
|
|
||||||
}
|
|
||||||
if (xxlJobGroup.getAppname().length() < 4 || xxlJobGroup.getAppname().length() > 64) {
|
|
||||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_appname_length"));
|
|
||||||
}
|
|
||||||
if (xxlJobGroup.getTitle() == null || xxlJobGroup.getTitle().trim().length() == 0) {
|
|
||||||
return new ReturnT<String>(500, (I18nUtil.getString("system_please_input") + I18nUtil.getString("jobgroup_field_title")));
|
|
||||||
}
|
|
||||||
if (xxlJobGroup.getAddressType() == 0) {
|
|
||||||
// 0=自动注册
|
|
||||||
List<String> registryList = findRegistryByAppName(xxlJobGroup.getAppname());
|
|
||||||
String addressListStr = null;
|
|
||||||
if (registryList != null && !registryList.isEmpty()) {
|
|
||||||
Collections.sort(registryList);
|
|
||||||
addressListStr = "";
|
|
||||||
for (String item : registryList) {
|
|
||||||
addressListStr += item + ",";
|
|
||||||
}
|
|
||||||
addressListStr = addressListStr.substring(0, addressListStr.length() - 1);
|
|
||||||
}
|
|
||||||
xxlJobGroup.setAddressList(addressListStr);
|
|
||||||
} else {
|
|
||||||
// 1=手动录入
|
|
||||||
if (xxlJobGroup.getAddressList() == null || xxlJobGroup.getAddressList().trim().length() == 0) {
|
|
||||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_addressType_limit"));
|
|
||||||
}
|
|
||||||
String[] addresss = xxlJobGroup.getAddressList().split(",");
|
|
||||||
for (String item : addresss) {
|
|
||||||
if (item == null || item.trim().length() == 0) {
|
|
||||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_registryList_unvalid"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// process
|
|
||||||
xxlJobGroup.setUpdateTime(new Date());
|
|
||||||
|
|
||||||
int ret = xxlJobGroupDao.update(xxlJobGroup);
|
|
||||||
return (ret > 0) ? ReturnT.SUCCESS : ReturnT.FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> findRegistryByAppName(String appnameParam) {
|
|
||||||
HashMap<String, List<String>> appAddressMap = new HashMap<String, List<String>>();
|
|
||||||
List<XxlJobRegistry> list = xxlJobRegistryDao.findAll(RegistryConfig.DEAD_TIMEOUT, new Date());
|
|
||||||
if (list != null) {
|
|
||||||
for (XxlJobRegistry item : list) {
|
|
||||||
if (RegistryConfig.RegistType.EXECUTOR.name().equals(item.getRegistryGroup())) {
|
|
||||||
String appname = item.getRegistryKey();
|
|
||||||
List<String> registryList = appAddressMap.get(appname);
|
|
||||||
if (registryList == null) {
|
|
||||||
registryList = new ArrayList<String>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!registryList.contains(item.getRegistryValue())) {
|
|
||||||
registryList.add(item.getRegistryValue());
|
|
||||||
}
|
|
||||||
appAddressMap.put(appname, registryList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return appAddressMap.get(appnameParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/remove")
|
|
||||||
@ResponseBody
|
|
||||||
@PermissionLimit(adminuser = true)
|
|
||||||
public ReturnT<String> remove(int id) {
|
|
||||||
|
|
||||||
// valid
|
|
||||||
int count = xxlJobInfoDao.pageListCount(0, 10, id, -1, null, null, null);
|
|
||||||
if (count > 0) {
|
|
||||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_del_limit_0"));
|
|
||||||
}
|
|
||||||
|
|
||||||
List<XxlJobGroup> allList = xxlJobGroupDao.findAll();
|
|
||||||
if (allList.size() == 1) {
|
|
||||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_del_limit_1"));
|
|
||||||
}
|
|
||||||
|
|
||||||
int ret = xxlJobGroupDao.remove(id);
|
|
||||||
return (ret > 0) ? ReturnT.SUCCESS : ReturnT.FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/loadById")
|
|
||||||
@ResponseBody
|
|
||||||
@PermissionLimit(adminuser = true)
|
|
||||||
public ReturnT<XxlJobGroup> loadById(int id) {
|
|
||||||
XxlJobGroup jobGroup = xxlJobGroupDao.load(id);
|
|
||||||
return jobGroup != null ? new ReturnT<XxlJobGroup>(jobGroup) : new ReturnT<XxlJobGroup>(ReturnT.FAIL_CODE, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,180 +0,0 @@
|
|||||||
package com.xxl.job.admin.controller;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.exception.XxlJobException;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobGroup;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobUser;
|
|
||||||
import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;
|
|
||||||
import com.xxl.job.admin.core.scheduler.MisfireStrategyEnum;
|
|
||||||
import com.xxl.job.admin.core.scheduler.ScheduleTypeEnum;
|
|
||||||
import com.xxl.job.admin.core.thread.JobScheduleHelper;
|
|
||||||
import com.xxl.job.admin.core.thread.JobTriggerPoolHelper;
|
|
||||||
import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
|
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
|
||||||
import com.xxl.job.admin.dao.XxlJobGroupDao;
|
|
||||||
import com.xxl.job.admin.service.LoginService;
|
|
||||||
import com.xxl.job.admin.service.XxlJobService;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import com.xxl.job.core.enums.ExecutorBlockStrategyEnum;
|
|
||||||
import com.xxl.job.core.glue.GlueTypeEnum;
|
|
||||||
import com.xxl.job.core.util.DateUtil;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.ui.Model;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* index controller
|
|
||||||
*
|
|
||||||
* @author xuxueli 2015-12-19 16:13:16
|
|
||||||
*/
|
|
||||||
@Controller
|
|
||||||
@RequestMapping("/jobinfo")
|
|
||||||
public class JobInfoController {
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(JobInfoController.class);
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private XxlJobGroupDao xxlJobGroupDao;
|
|
||||||
@Resource
|
|
||||||
private XxlJobService xxlJobService;
|
|
||||||
|
|
||||||
@RequestMapping
|
|
||||||
public String index(HttpServletRequest request, Model model, @RequestParam(required = false, defaultValue = "-1") int jobGroup) {
|
|
||||||
|
|
||||||
// 枚举-字典
|
|
||||||
model.addAttribute("ExecutorRouteStrategyEnum", ExecutorRouteStrategyEnum.values()); // 路由策略-列表
|
|
||||||
model.addAttribute("GlueTypeEnum", GlueTypeEnum.values()); // Glue类型-字典
|
|
||||||
model.addAttribute("ExecutorBlockStrategyEnum", ExecutorBlockStrategyEnum.values()); // 阻塞处理策略-字典
|
|
||||||
model.addAttribute("ScheduleTypeEnum", ScheduleTypeEnum.values()); // 调度类型
|
|
||||||
model.addAttribute("MisfireStrategyEnum", MisfireStrategyEnum.values()); // 调度过期策略
|
|
||||||
|
|
||||||
// 执行器列表
|
|
||||||
List<XxlJobGroup> jobGroupList_all = xxlJobGroupDao.findAll();
|
|
||||||
|
|
||||||
// filter group
|
|
||||||
List<XxlJobGroup> jobGroupList = filterJobGroupByRole(request, jobGroupList_all);
|
|
||||||
if (jobGroupList == null || jobGroupList.size() == 0) {
|
|
||||||
throw new XxlJobException(I18nUtil.getString("jobgroup_empty"));
|
|
||||||
}
|
|
||||||
|
|
||||||
model.addAttribute("JobGroupList", jobGroupList);
|
|
||||||
model.addAttribute("jobGroup", jobGroup);
|
|
||||||
|
|
||||||
return "jobinfo/jobinfo.index";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<XxlJobGroup> filterJobGroupByRole(HttpServletRequest request, List<XxlJobGroup> jobGroupList_all) {
|
|
||||||
List<XxlJobGroup> jobGroupList = new ArrayList<>();
|
|
||||||
if (jobGroupList_all != null && jobGroupList_all.size() > 0) {
|
|
||||||
XxlJobUser loginUser = (XxlJobUser) request.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
|
|
||||||
if (loginUser.getRole() == 1) {
|
|
||||||
jobGroupList = jobGroupList_all;
|
|
||||||
} else {
|
|
||||||
List<String> groupIdStrs = new ArrayList<>();
|
|
||||||
if (loginUser.getPermission() != null && loginUser.getPermission().trim().length() > 0) {
|
|
||||||
groupIdStrs = Arrays.asList(loginUser.getPermission().trim().split(","));
|
|
||||||
}
|
|
||||||
for (XxlJobGroup groupItem : jobGroupList_all) {
|
|
||||||
if (groupIdStrs.contains(String.valueOf(groupItem.getId()))) {
|
|
||||||
jobGroupList.add(groupItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return jobGroupList;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void validPermission(HttpServletRequest request, int jobGroup) {
|
|
||||||
XxlJobUser loginUser = (XxlJobUser) request.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
|
|
||||||
if (!loginUser.validPermission(jobGroup)) {
|
|
||||||
throw new RuntimeException(I18nUtil.getString("system_permission_limit") + "[username=" + loginUser.getUsername() + "]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/pageList")
|
|
||||||
@ResponseBody
|
|
||||||
public Map<String, Object> pageList(@RequestParam(required = false, defaultValue = "0") int start,
|
|
||||||
@RequestParam(required = false, defaultValue = "10") int length,
|
|
||||||
int jobGroup, int triggerStatus, String jobDesc, String executorHandler, String author) {
|
|
||||||
|
|
||||||
return xxlJobService.pageList(start, length, jobGroup, triggerStatus, jobDesc, executorHandler, author);
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/add")
|
|
||||||
@ResponseBody
|
|
||||||
public ReturnT<String> add(XxlJobInfo jobInfo) {
|
|
||||||
return xxlJobService.add(jobInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/update")
|
|
||||||
@ResponseBody
|
|
||||||
public ReturnT<String> update(XxlJobInfo jobInfo) {
|
|
||||||
return xxlJobService.update(jobInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/remove")
|
|
||||||
@ResponseBody
|
|
||||||
public ReturnT<String> remove(int id) {
|
|
||||||
return xxlJobService.remove(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/stop")
|
|
||||||
@ResponseBody
|
|
||||||
public ReturnT<String> pause(int id) {
|
|
||||||
return xxlJobService.stop(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/start")
|
|
||||||
@ResponseBody
|
|
||||||
public ReturnT<String> start(int id) {
|
|
||||||
return xxlJobService.start(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/trigger")
|
|
||||||
@ResponseBody
|
|
||||||
//@PermissionLimit(limit = false)
|
|
||||||
public ReturnT<String> triggerJob(int id, String executorParam, String addressList) {
|
|
||||||
// force cover job param
|
|
||||||
if (executorParam == null) {
|
|
||||||
executorParam = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
JobTriggerPoolHelper.trigger(id, TriggerTypeEnum.MANUAL, -1, null, executorParam, addressList);
|
|
||||||
return ReturnT.SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/nextTriggerTime")
|
|
||||||
@ResponseBody
|
|
||||||
public ReturnT<List<String>> nextTriggerTime(String scheduleType, String scheduleConf) {
|
|
||||||
|
|
||||||
XxlJobInfo paramXxlJobInfo = new XxlJobInfo();
|
|
||||||
paramXxlJobInfo.setScheduleType(scheduleType);
|
|
||||||
paramXxlJobInfo.setScheduleConf(scheduleConf);
|
|
||||||
|
|
||||||
List<String> result = new ArrayList<>();
|
|
||||||
try {
|
|
||||||
Date lastTime = new Date();
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
lastTime = JobScheduleHelper.generateNextValidTime(paramXxlJobInfo, lastTime);
|
|
||||||
if (lastTime != null) {
|
|
||||||
result.add(DateUtil.formatDateTime(lastTime));
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
return new ReturnT<List<String>>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")) + e.getMessage());
|
|
||||||
}
|
|
||||||
return new ReturnT<List<String>>(result);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,238 +0,0 @@
|
|||||||
package com.xxl.job.admin.controller;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.exception.XxlJobException;
|
|
||||||
import com.xxl.job.admin.core.complete.XxlJobCompleter;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobGroup;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobLog;
|
|
||||||
import com.xxl.job.admin.core.scheduler.XxlJobScheduler;
|
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
|
||||||
import com.xxl.job.admin.dao.XxlJobGroupDao;
|
|
||||||
import com.xxl.job.admin.dao.XxlJobInfoDao;
|
|
||||||
import com.xxl.job.admin.dao.XxlJobLogDao;
|
|
||||||
import com.xxl.job.core.biz.ExecutorBiz;
|
|
||||||
import com.xxl.job.core.biz.model.KillParam;
|
|
||||||
import com.xxl.job.core.biz.model.LogParam;
|
|
||||||
import com.xxl.job.core.biz.model.LogResult;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import com.xxl.job.core.util.DateUtil;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.ui.Model;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* index controller
|
|
||||||
*
|
|
||||||
* @author xuxueli 2015-12-19 16:13:16
|
|
||||||
*/
|
|
||||||
@Controller
|
|
||||||
@RequestMapping("/joblog")
|
|
||||||
public class JobLogController {
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(JobLogController.class);
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private XxlJobGroupDao xxlJobGroupDao;
|
|
||||||
@Resource
|
|
||||||
public XxlJobInfoDao xxlJobInfoDao;
|
|
||||||
@Resource
|
|
||||||
public XxlJobLogDao xxlJobLogDao;
|
|
||||||
|
|
||||||
@RequestMapping
|
|
||||||
public String index(HttpServletRequest request, Model model, @RequestParam(required = false, defaultValue = "0") Integer jobId) {
|
|
||||||
|
|
||||||
// 执行器列表
|
|
||||||
List<XxlJobGroup> jobGroupList_all = xxlJobGroupDao.findAll();
|
|
||||||
|
|
||||||
// filter group
|
|
||||||
List<XxlJobGroup> jobGroupList = JobInfoController.filterJobGroupByRole(request, jobGroupList_all);
|
|
||||||
if (jobGroupList == null || jobGroupList.size() == 0) {
|
|
||||||
throw new XxlJobException(I18nUtil.getString("jobgroup_empty"));
|
|
||||||
}
|
|
||||||
|
|
||||||
model.addAttribute("JobGroupList", jobGroupList);
|
|
||||||
|
|
||||||
// 任务
|
|
||||||
if (jobId > 0) {
|
|
||||||
XxlJobInfo jobInfo = xxlJobInfoDao.loadById(jobId);
|
|
||||||
if (jobInfo == null) {
|
|
||||||
throw new RuntimeException(I18nUtil.getString("jobinfo_field_id") + I18nUtil.getString("system_unvalid"));
|
|
||||||
}
|
|
||||||
|
|
||||||
model.addAttribute("jobInfo", jobInfo);
|
|
||||||
|
|
||||||
// valid permission
|
|
||||||
JobInfoController.validPermission(request, jobInfo.getJobGroup());
|
|
||||||
}
|
|
||||||
|
|
||||||
return "joblog/joblog.index";
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/getJobsByGroup")
|
|
||||||
@ResponseBody
|
|
||||||
public ReturnT<List<XxlJobInfo>> getJobsByGroup(int jobGroup) {
|
|
||||||
List<XxlJobInfo> list = xxlJobInfoDao.getJobsByGroup(jobGroup);
|
|
||||||
return new ReturnT<List<XxlJobInfo>>(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/pageList")
|
|
||||||
@ResponseBody
|
|
||||||
public Map<String, Object> pageList(HttpServletRequest request,
|
|
||||||
@RequestParam(required = false, defaultValue = "0") int start,
|
|
||||||
@RequestParam(required = false, defaultValue = "10") int length,
|
|
||||||
int jobGroup, int jobId, int logStatus, String filterTime) {
|
|
||||||
|
|
||||||
// valid permission
|
|
||||||
JobInfoController.validPermission(request, jobGroup); // 仅管理员支持查询全部;普通用户仅支持查询有权限的 jobGroup
|
|
||||||
|
|
||||||
// parse param
|
|
||||||
Date triggerTimeStart = null;
|
|
||||||
Date triggerTimeEnd = null;
|
|
||||||
if (filterTime != null && filterTime.trim().length() > 0) {
|
|
||||||
String[] temp = filterTime.split(" - ");
|
|
||||||
if (temp.length == 2) {
|
|
||||||
triggerTimeStart = DateUtil.parseDateTime(temp[0]);
|
|
||||||
triggerTimeEnd = DateUtil.parseDateTime(temp[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// page query
|
|
||||||
List<XxlJobLog> list = xxlJobLogDao.pageList(start, length, jobGroup, jobId, triggerTimeStart, triggerTimeEnd, logStatus);
|
|
||||||
int list_count = xxlJobLogDao.pageListCount(start, length, jobGroup, jobId, triggerTimeStart, triggerTimeEnd, logStatus);
|
|
||||||
|
|
||||||
// package result
|
|
||||||
Map<String, Object> maps = new HashMap<String, Object>();
|
|
||||||
maps.put("recordsTotal", list_count); // 总记录数
|
|
||||||
maps.put("recordsFiltered", list_count); // 过滤后的总记录数
|
|
||||||
maps.put("data", list); // 分页列表
|
|
||||||
return maps;
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/logDetailPage")
|
|
||||||
public String logDetailPage(int id, Model model) {
|
|
||||||
|
|
||||||
// base check
|
|
||||||
ReturnT<String> logStatue = ReturnT.SUCCESS;
|
|
||||||
XxlJobLog jobLog = xxlJobLogDao.load(id);
|
|
||||||
if (jobLog == null) {
|
|
||||||
throw new RuntimeException(I18nUtil.getString("joblog_logid_unvalid"));
|
|
||||||
}
|
|
||||||
|
|
||||||
model.addAttribute("triggerCode", jobLog.getTriggerCode());
|
|
||||||
model.addAttribute("handleCode", jobLog.getHandleCode());
|
|
||||||
model.addAttribute("logId", jobLog.getId());
|
|
||||||
return "joblog/joblog.detail";
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/logDetailCat")
|
|
||||||
@ResponseBody
|
|
||||||
public ReturnT<LogResult> logDetailCat(long logId, int fromLineNum) {
|
|
||||||
try {
|
|
||||||
// valid
|
|
||||||
XxlJobLog jobLog = xxlJobLogDao.load(logId); // todo, need to improve performance
|
|
||||||
if (jobLog == null) {
|
|
||||||
return new ReturnT<LogResult>(ReturnT.FAIL_CODE, I18nUtil.getString("joblog_logid_unvalid"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// log cat
|
|
||||||
ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(jobLog.getExecutorAddress());
|
|
||||||
ReturnT<LogResult> logResult = executorBiz.log(new LogParam(jobLog.getTriggerTime().getTime(), logId, fromLineNum));
|
|
||||||
|
|
||||||
// is end
|
|
||||||
if (logResult.getContent() != null && logResult.getContent().getFromLineNum() > logResult.getContent().getToLineNum()) {
|
|
||||||
if (jobLog.getHandleCode() > 0) {
|
|
||||||
logResult.getContent().setEnd(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return logResult;
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
return new ReturnT<LogResult>(ReturnT.FAIL_CODE, e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/logKill")
|
|
||||||
@ResponseBody
|
|
||||||
public ReturnT<String> logKill(int id) {
|
|
||||||
// base check
|
|
||||||
XxlJobLog log = xxlJobLogDao.load(id);
|
|
||||||
XxlJobInfo jobInfo = xxlJobInfoDao.loadById(log.getJobId());
|
|
||||||
if (jobInfo == null) {
|
|
||||||
return new ReturnT<String>(500, I18nUtil.getString("jobinfo_glue_jobid_unvalid"));
|
|
||||||
}
|
|
||||||
if (ReturnT.SUCCESS_CODE != log.getTriggerCode()) {
|
|
||||||
return new ReturnT<String>(500, I18nUtil.getString("joblog_kill_log_limit"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// request of kill
|
|
||||||
ReturnT<String> runResult = null;
|
|
||||||
try {
|
|
||||||
ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(log.getExecutorAddress());
|
|
||||||
runResult = executorBiz.kill(new KillParam(jobInfo.getId()));
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
runResult = new ReturnT<String>(500, e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ReturnT.SUCCESS_CODE == runResult.getCode()) {
|
|
||||||
log.setHandleCode(ReturnT.FAIL_CODE);
|
|
||||||
log.setHandleMsg(I18nUtil.getString("joblog_kill_log_byman") + ":" + (runResult.getMsg() != null ? runResult.getMsg() : ""));
|
|
||||||
log.setHandleTime(new Date());
|
|
||||||
XxlJobCompleter.updateHandleInfoAndFinish(log);
|
|
||||||
return new ReturnT<String>(runResult.getMsg());
|
|
||||||
} else {
|
|
||||||
return new ReturnT<String>(500, runResult.getMsg());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/clearLog")
|
|
||||||
@ResponseBody
|
|
||||||
public ReturnT<String> clearLog(int jobGroup, int jobId, int type) {
|
|
||||||
|
|
||||||
Date clearBeforeTime = null;
|
|
||||||
int clearBeforeNum = 0;
|
|
||||||
if (type == 1) {
|
|
||||||
clearBeforeTime = DateUtil.addMonths(new Date(), -1); // 清理一个月之前日志数据
|
|
||||||
} else if (type == 2) {
|
|
||||||
clearBeforeTime = DateUtil.addMonths(new Date(), -3); // 清理三个月之前日志数据
|
|
||||||
} else if (type == 3) {
|
|
||||||
clearBeforeTime = DateUtil.addMonths(new Date(), -6); // 清理六个月之前日志数据
|
|
||||||
} else if (type == 4) {
|
|
||||||
clearBeforeTime = DateUtil.addYears(new Date(), -1); // 清理一年之前日志数据
|
|
||||||
} else if (type == 5) {
|
|
||||||
clearBeforeNum = 1000; // 清理一千条以前日志数据
|
|
||||||
} else if (type == 6) {
|
|
||||||
clearBeforeNum = 10000; // 清理一万条以前日志数据
|
|
||||||
} else if (type == 7) {
|
|
||||||
clearBeforeNum = 30000; // 清理三万条以前日志数据
|
|
||||||
} else if (type == 8) {
|
|
||||||
clearBeforeNum = 100000; // 清理十万条以前日志数据
|
|
||||||
} else if (type == 9) {
|
|
||||||
clearBeforeNum = 0; // 清理所有日志数据
|
|
||||||
} else {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("joblog_clean_type_unvalid"));
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Long> logIds = null;
|
|
||||||
do {
|
|
||||||
logIds = xxlJobLogDao.findClearLogIds(jobGroup, jobId, clearBeforeTime, clearBeforeNum, 1000);
|
|
||||||
if (logIds != null && logIds.size() > 0) {
|
|
||||||
xxlJobLogDao.clearLog(logIds);
|
|
||||||
}
|
|
||||||
} while (logIds != null && logIds.size() > 0);
|
|
||||||
|
|
||||||
return ReturnT.SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,179 +0,0 @@
|
|||||||
package com.xxl.job.admin.controller;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.controller.annotation.PermissionLimit;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobGroup;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobUser;
|
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
|
||||||
import com.xxl.job.admin.dao.XxlJobGroupDao;
|
|
||||||
import com.xxl.job.admin.dao.XxlJobUserDao;
|
|
||||||
import com.xxl.job.admin.service.LoginService;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.ui.Model;
|
|
||||||
import org.springframework.util.DigestUtils;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author xuxueli 2019-05-04 16:39:50
|
|
||||||
*/
|
|
||||||
@Controller
|
|
||||||
@RequestMapping("/user")
|
|
||||||
public class UserController {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private XxlJobUserDao xxlJobUserDao;
|
|
||||||
@Resource
|
|
||||||
private XxlJobGroupDao xxlJobGroupDao;
|
|
||||||
|
|
||||||
@RequestMapping
|
|
||||||
@PermissionLimit(adminuser = true)
|
|
||||||
public String index(Model model) {
|
|
||||||
|
|
||||||
// 执行器列表
|
|
||||||
List<XxlJobGroup> groupList = xxlJobGroupDao.findAll();
|
|
||||||
model.addAttribute("groupList", groupList);
|
|
||||||
|
|
||||||
return "user/user.index";
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/pageList")
|
|
||||||
@ResponseBody
|
|
||||||
@PermissionLimit(adminuser = true)
|
|
||||||
public Map<String, Object> pageList(@RequestParam(required = false, defaultValue = "0") int start,
|
|
||||||
@RequestParam(required = false, defaultValue = "10") int length,
|
|
||||||
String username, int role) {
|
|
||||||
|
|
||||||
// page list
|
|
||||||
List<XxlJobUser> list = xxlJobUserDao.pageList(start, length, username, role);
|
|
||||||
int list_count = xxlJobUserDao.pageListCount(start, length, username, role);
|
|
||||||
|
|
||||||
// filter
|
|
||||||
if (list != null && list.size() > 0) {
|
|
||||||
for (XxlJobUser item : list) {
|
|
||||||
item.setPassword(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// package result
|
|
||||||
Map<String, Object> maps = new HashMap<String, Object>();
|
|
||||||
maps.put("recordsTotal", list_count); // 总记录数
|
|
||||||
maps.put("recordsFiltered", list_count); // 过滤后的总记录数
|
|
||||||
maps.put("data", list); // 分页列表
|
|
||||||
return maps;
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/add")
|
|
||||||
@ResponseBody
|
|
||||||
@PermissionLimit(adminuser = true)
|
|
||||||
public ReturnT<String> add(XxlJobUser xxlJobUser) {
|
|
||||||
|
|
||||||
// valid username
|
|
||||||
if (!StringUtils.hasText(xxlJobUser.getUsername())) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("system_please_input") + I18nUtil.getString("user_username"));
|
|
||||||
}
|
|
||||||
xxlJobUser.setUsername(xxlJobUser.getUsername().trim());
|
|
||||||
if (!(xxlJobUser.getUsername().length() >= 4 && xxlJobUser.getUsername().length() <= 20)) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("system_lengh_limit") + "[4-20]");
|
|
||||||
}
|
|
||||||
// valid password
|
|
||||||
if (!StringUtils.hasText(xxlJobUser.getPassword())) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("system_please_input") + I18nUtil.getString("user_password"));
|
|
||||||
}
|
|
||||||
xxlJobUser.setPassword(xxlJobUser.getPassword().trim());
|
|
||||||
if (!(xxlJobUser.getPassword().length() >= 4 && xxlJobUser.getPassword().length() <= 20)) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("system_lengh_limit") + "[4-20]");
|
|
||||||
}
|
|
||||||
// md5 password
|
|
||||||
xxlJobUser.setPassword(DigestUtils.md5DigestAsHex(xxlJobUser.getPassword().getBytes()));
|
|
||||||
|
|
||||||
// check repeat
|
|
||||||
XxlJobUser existUser = xxlJobUserDao.loadByUserName(xxlJobUser.getUsername());
|
|
||||||
if (existUser != null) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("user_username_repeat"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// write
|
|
||||||
xxlJobUserDao.save(xxlJobUser);
|
|
||||||
return ReturnT.SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/update")
|
|
||||||
@ResponseBody
|
|
||||||
@PermissionLimit(adminuser = true)
|
|
||||||
public ReturnT<String> update(HttpServletRequest request, XxlJobUser xxlJobUser) {
|
|
||||||
|
|
||||||
// avoid opt login seft
|
|
||||||
XxlJobUser loginUser = (XxlJobUser) request.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
|
|
||||||
if (loginUser.getUsername().equals(xxlJobUser.getUsername())) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL.getCode(), I18nUtil.getString("user_update_loginuser_limit"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// valid password
|
|
||||||
if (StringUtils.hasText(xxlJobUser.getPassword())) {
|
|
||||||
xxlJobUser.setPassword(xxlJobUser.getPassword().trim());
|
|
||||||
if (!(xxlJobUser.getPassword().length() >= 4 && xxlJobUser.getPassword().length() <= 20)) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("system_lengh_limit") + "[4-20]");
|
|
||||||
}
|
|
||||||
// md5 password
|
|
||||||
xxlJobUser.setPassword(DigestUtils.md5DigestAsHex(xxlJobUser.getPassword().getBytes()));
|
|
||||||
} else {
|
|
||||||
xxlJobUser.setPassword(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
// write
|
|
||||||
xxlJobUserDao.update(xxlJobUser);
|
|
||||||
return ReturnT.SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/remove")
|
|
||||||
@ResponseBody
|
|
||||||
@PermissionLimit(adminuser = true)
|
|
||||||
public ReturnT<String> remove(HttpServletRequest request, int id) {
|
|
||||||
|
|
||||||
// avoid opt login seft
|
|
||||||
XxlJobUser loginUser = (XxlJobUser) request.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
|
|
||||||
if (loginUser.getId() == id) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL.getCode(), I18nUtil.getString("user_update_loginuser_limit"));
|
|
||||||
}
|
|
||||||
|
|
||||||
xxlJobUserDao.delete(id);
|
|
||||||
return ReturnT.SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/updatePwd")
|
|
||||||
@ResponseBody
|
|
||||||
public ReturnT<String> updatePwd(HttpServletRequest request, String password) {
|
|
||||||
|
|
||||||
// valid password
|
|
||||||
if (password == null || password.trim().length() == 0) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL.getCode(), "密码不可为空");
|
|
||||||
}
|
|
||||||
password = password.trim();
|
|
||||||
if (!(password.length() >= 4 && password.length() <= 20)) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("system_lengh_limit") + "[4-20]");
|
|
||||||
}
|
|
||||||
|
|
||||||
// md5 password
|
|
||||||
String md5Password = DigestUtils.md5DigestAsHex(password.getBytes());
|
|
||||||
|
|
||||||
// update pwd
|
|
||||||
XxlJobUser loginUser = (XxlJobUser) request.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
|
|
||||||
|
|
||||||
// do write
|
|
||||||
XxlJobUser existUser = xxlJobUserDao.loadByUserName(loginUser.getUsername());
|
|
||||||
existUser.setPassword(md5Password);
|
|
||||||
xxlJobUserDao.update(existUser);
|
|
||||||
|
|
||||||
return ReturnT.SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
package com.xxl.job.admin.controller.annotation;
|
|
||||||
|
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 权限限制
|
|
||||||
*
|
|
||||||
* @author xuxueli 2015-12-12 18:29:02
|
|
||||||
*/
|
|
||||||
@Target(ElementType.METHOD)
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
public @interface PermissionLimit {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 登录拦截 (默认拦截)
|
|
||||||
*/
|
|
||||||
boolean limit() default true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 要求管理员权限
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
boolean adminuser() default false;
|
|
||||||
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
package com.xxl.job.admin.controller.interceptor;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.util.FtlUtil;
|
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.web.servlet.AsyncHandlerInterceptor;
|
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
|
||||||
|
|
||||||
import javax.servlet.http.Cookie;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* push cookies to model as cookieMap
|
|
||||||
*
|
|
||||||
* @author xuxueli 2015-12-12 18:09:04
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class CookieInterceptor implements AsyncHandlerInterceptor {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
|
|
||||||
ModelAndView modelAndView) throws Exception {
|
|
||||||
|
|
||||||
// cookie
|
|
||||||
if (modelAndView != null && request.getCookies() != null && request.getCookies().length > 0) {
|
|
||||||
HashMap<String, Cookie> cookieMap = new HashMap<String, Cookie>();
|
|
||||||
for (Cookie ck : request.getCookies()) {
|
|
||||||
cookieMap.put(ck.getName(), ck);
|
|
||||||
}
|
|
||||||
modelAndView.addObject("cookieMap", cookieMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
// static method
|
|
||||||
if (modelAndView != null) {
|
|
||||||
modelAndView.addObject("I18nUtil", FtlUtil.generateStaticModel(I18nUtil.class.getName()));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
package com.xxl.job.admin.controller.interceptor;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.controller.annotation.PermissionLimit;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobUser;
|
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
|
||||||
import com.xxl.job.admin.service.LoginService;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.web.method.HandlerMethod;
|
|
||||||
import org.springframework.web.servlet.AsyncHandlerInterceptor;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 权限拦截
|
|
||||||
*
|
|
||||||
* @author xuxueli 2015-12-12 18:09:04
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class PermissionInterceptor implements AsyncHandlerInterceptor {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private LoginService loginService;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
|
||||||
|
|
||||||
if (!(handler instanceof HandlerMethod)) {
|
|
||||||
return true; // proceed with the next interceptor
|
|
||||||
}
|
|
||||||
|
|
||||||
// if need login
|
|
||||||
boolean needLogin = true;
|
|
||||||
boolean needAdminuser = false;
|
|
||||||
HandlerMethod method = (HandlerMethod) handler;
|
|
||||||
PermissionLimit permission = method.getMethodAnnotation(PermissionLimit.class);
|
|
||||||
if (permission != null) {
|
|
||||||
needLogin = permission.limit();
|
|
||||||
needAdminuser = permission.adminuser();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needLogin) {
|
|
||||||
XxlJobUser loginUser = loginService.ifLogin(request, response);
|
|
||||||
if (loginUser == null) {
|
|
||||||
response.setStatus(302);
|
|
||||||
response.setHeader("location", request.getContextPath() + "/toLogin");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (needAdminuser && loginUser.getRole() != 1) {
|
|
||||||
throw new RuntimeException(I18nUtil.getString("system_permission_limit"));
|
|
||||||
}
|
|
||||||
request.setAttribute(LoginService.LOGIN_IDENTITY_KEY, loginUser);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true; // proceed with the next interceptor
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
package com.xxl.job.admin.controller.interceptor;
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* web mvc config
|
|
||||||
*
|
|
||||||
* @author xuxueli 2018-04-02 20:48:20
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
public class WebMvcConfig implements WebMvcConfigurer {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private PermissionInterceptor permissionInterceptor;
|
|
||||||
@Resource
|
|
||||||
private CookieInterceptor cookieInterceptor;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addInterceptors(InterceptorRegistry registry) {
|
|
||||||
registry.addInterceptor(permissionInterceptor).addPathPatterns("/**");
|
|
||||||
registry.addInterceptor(cookieInterceptor).addPathPatterns("/**");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,66 +0,0 @@
|
|||||||
package com.xxl.job.admin.controller.resolver;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.exception.XxlJobException;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import com.xxl.job.admin.core.util.JacksonUtil;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
import org.springframework.web.method.HandlerMethod;
|
|
||||||
import org.springframework.web.servlet.HandlerExceptionResolver;
|
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* common exception resolver
|
|
||||||
*
|
|
||||||
* @author xuxueli 2016-1-6 19:22:18
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class WebExceptionResolver implements HandlerExceptionResolver {
|
|
||||||
private static transient Logger logger = LoggerFactory.getLogger(WebExceptionResolver.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ModelAndView resolveException(HttpServletRequest request,
|
|
||||||
HttpServletResponse response, Object handler, Exception ex) {
|
|
||||||
|
|
||||||
if (!(ex instanceof XxlJobException)) {
|
|
||||||
logger.error("WebExceptionResolver:{}", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if json
|
|
||||||
boolean isJson = false;
|
|
||||||
if (handler instanceof HandlerMethod) {
|
|
||||||
HandlerMethod method = (HandlerMethod) handler;
|
|
||||||
ResponseBody responseBody = method.getMethodAnnotation(ResponseBody.class);
|
|
||||||
if (responseBody != null) {
|
|
||||||
isJson = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// error result
|
|
||||||
ReturnT<String> errorResult = new ReturnT<String>(ReturnT.FAIL_CODE, ex.toString().replaceAll("\n", "<br/>"));
|
|
||||||
|
|
||||||
// response
|
|
||||||
ModelAndView mv = new ModelAndView();
|
|
||||||
if (isJson) {
|
|
||||||
try {
|
|
||||||
response.setContentType("application/json;charset=utf-8");
|
|
||||||
response.getWriter().print(JacksonUtil.writeValueAsString(errorResult));
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
return mv;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
mv.addObject("exceptionMsg", errorResult.getMsg());
|
|
||||||
mv.setViewName("/common/common.exception");
|
|
||||||
return mv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.alarm;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobLog;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author xuxueli 2020-01-19
|
|
||||||
*/
|
|
||||||
public interface JobAlarm {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* job alarm
|
|
||||||
*
|
|
||||||
* @param info
|
|
||||||
* @param jobLog
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean doAlarm(XxlJobInfo info, XxlJobLog jobLog);
|
|
||||||
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.alarm;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobLog;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.BeansException;
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.context.ApplicationContextAware;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class JobAlarmer implements ApplicationContextAware, InitializingBean {
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(JobAlarmer.class);
|
|
||||||
|
|
||||||
private ApplicationContext applicationContext;
|
|
||||||
private List<JobAlarm> jobAlarmList;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
|
||||||
this.applicationContext = applicationContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterPropertiesSet() throws Exception {
|
|
||||||
Map<String, JobAlarm> serviceBeanMap = applicationContext.getBeansOfType(JobAlarm.class);
|
|
||||||
if (serviceBeanMap != null && serviceBeanMap.size() > 0) {
|
|
||||||
jobAlarmList = new ArrayList<JobAlarm>(serviceBeanMap.values());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* job alarm
|
|
||||||
*
|
|
||||||
* @param info
|
|
||||||
* @param jobLog
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean alarm(XxlJobInfo info, XxlJobLog jobLog) {
|
|
||||||
|
|
||||||
boolean result = false;
|
|
||||||
if (jobAlarmList != null && jobAlarmList.size() > 0) {
|
|
||||||
result = true; // success means all-success
|
|
||||||
for (JobAlarm alarm : jobAlarmList) {
|
|
||||||
boolean resultItem = false;
|
|
||||||
try {
|
|
||||||
resultItem = alarm.doAlarm(info, jobLog);
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
if (!resultItem) {
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,118 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.alarm.impl;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.alarm.JobAlarm;
|
|
||||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobGroup;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobLog;
|
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.mail.javamail.MimeMessageHelper;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import javax.mail.internet.MimeMessage;
|
|
||||||
import java.text.MessageFormat;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* job alarm by email
|
|
||||||
*
|
|
||||||
* @author xuxueli 2020-01-19
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class EmailJobAlarm implements JobAlarm {
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(EmailJobAlarm.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* fail alarm
|
|
||||||
*
|
|
||||||
* @param jobLog
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean doAlarm(XxlJobInfo info, XxlJobLog jobLog) {
|
|
||||||
boolean alarmResult = true;
|
|
||||||
|
|
||||||
// send monitor email
|
|
||||||
if (info != null && info.getAlarmEmail() != null && info.getAlarmEmail().trim().length() > 0) {
|
|
||||||
|
|
||||||
// alarmContent
|
|
||||||
String alarmContent = "Alarm Job LogId=" + jobLog.getId();
|
|
||||||
if (jobLog.getTriggerCode() != ReturnT.SUCCESS_CODE) {
|
|
||||||
alarmContent += "<br>TriggerMsg=<br>" + jobLog.getTriggerMsg();
|
|
||||||
}
|
|
||||||
if (jobLog.getHandleCode() > 0 && jobLog.getHandleCode() != ReturnT.SUCCESS_CODE) {
|
|
||||||
alarmContent += "<br>HandleCode=" + jobLog.getHandleMsg();
|
|
||||||
}
|
|
||||||
|
|
||||||
// email info
|
|
||||||
XxlJobGroup group = XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().load(Integer.valueOf(info.getJobGroup()));
|
|
||||||
String personal = I18nUtil.getString("admin_name_full");
|
|
||||||
String title = I18nUtil.getString("jobconf_monitor");
|
|
||||||
String content = MessageFormat.format(loadEmailJobAlarmTemplate(),
|
|
||||||
group != null ? group.getTitle() : "null",
|
|
||||||
info.getId(),
|
|
||||||
info.getJobDesc(),
|
|
||||||
alarmContent);
|
|
||||||
|
|
||||||
Set<String> emailSet = new HashSet<String>(Arrays.asList(info.getAlarmEmail().split(",")));
|
|
||||||
for (String email : emailSet) {
|
|
||||||
|
|
||||||
// make mail
|
|
||||||
try {
|
|
||||||
MimeMessage mimeMessage = XxlJobAdminConfig.getAdminConfig().getMailSender().createMimeMessage();
|
|
||||||
|
|
||||||
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
|
|
||||||
helper.setFrom(XxlJobAdminConfig.getAdminConfig().getEmailFrom(), personal);
|
|
||||||
helper.setTo(email);
|
|
||||||
helper.setSubject(title);
|
|
||||||
helper.setText(content, true);
|
|
||||||
|
|
||||||
XxlJobAdminConfig.getAdminConfig().getMailSender().send(mimeMessage);
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error(">>>>>>>>>>> xxl-job, job fail alarm email send error, JobLogId:{}", jobLog.getId(), e);
|
|
||||||
|
|
||||||
alarmResult = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return alarmResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* load email job alarm template
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private static final String loadEmailJobAlarmTemplate() {
|
|
||||||
String mailBodyTemplate = "<h5>" + I18nUtil.getString("jobconf_monitor_detail") + ":</span>" +
|
|
||||||
"<table border=\"1\" cellpadding=\"3\" style=\"border-collapse:collapse; width:80%;\" >\n" +
|
|
||||||
" <thead style=\"font-weight: bold;color: #ffffff;background-color: #ff8c00;\" >" +
|
|
||||||
" <tr>\n" +
|
|
||||||
" <td width=\"20%\" >" + I18nUtil.getString("jobinfo_field_jobgroup") + "</td>\n" +
|
|
||||||
" <td width=\"10%\" >" + I18nUtil.getString("jobinfo_field_id") + "</td>\n" +
|
|
||||||
" <td width=\"20%\" >" + I18nUtil.getString("jobinfo_field_jobdesc") + "</td>\n" +
|
|
||||||
" <td width=\"10%\" >" + I18nUtil.getString("jobconf_monitor_alarm_title") + "</td>\n" +
|
|
||||||
" <td width=\"40%\" >" + I18nUtil.getString("jobconf_monitor_alarm_content") + "</td>\n" +
|
|
||||||
" </tr>\n" +
|
|
||||||
" </thead>\n" +
|
|
||||||
" <tbody>\n" +
|
|
||||||
" <tr>\n" +
|
|
||||||
" <td>{0}</td>\n" +
|
|
||||||
" <td>{1}</td>\n" +
|
|
||||||
" <td>{2}</td>\n" +
|
|
||||||
" <td>" + I18nUtil.getString("jobconf_monitor_alarm_type") + "</td>\n" +
|
|
||||||
" <td>{3}</td>\n" +
|
|
||||||
" </tr>\n" +
|
|
||||||
" </tbody>\n" +
|
|
||||||
"</table>";
|
|
||||||
|
|
||||||
return mailBodyTemplate;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,99 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.complete;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobLog;
|
|
||||||
import com.xxl.job.admin.core.thread.JobTriggerPoolHelper;
|
|
||||||
import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
|
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import com.xxl.job.core.context.XxlJobContext;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author xuxueli 2020-10-30 20:43:10
|
|
||||||
*/
|
|
||||||
public class XxlJobCompleter {
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(XxlJobCompleter.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* common fresh handle entrance (limit only once)
|
|
||||||
*
|
|
||||||
* @param xxlJobLog
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static int updateHandleInfoAndFinish(XxlJobLog xxlJobLog) {
|
|
||||||
|
|
||||||
// finish
|
|
||||||
finishJob(xxlJobLog);
|
|
||||||
|
|
||||||
// text最大64kb 避免长度过长
|
|
||||||
if (xxlJobLog.getHandleMsg().length() > 15000) {
|
|
||||||
xxlJobLog.setHandleMsg(xxlJobLog.getHandleMsg().substring(0, 15000));
|
|
||||||
}
|
|
||||||
|
|
||||||
// fresh handle
|
|
||||||
return XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().updateHandleInfo(xxlJobLog);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* do somethind to finish job
|
|
||||||
*/
|
|
||||||
private static void finishJob(XxlJobLog xxlJobLog) {
|
|
||||||
|
|
||||||
// 1、handle success, to trigger child job
|
|
||||||
String triggerChildMsg = null;
|
|
||||||
if (XxlJobContext.HANDLE_CODE_SUCCESS == xxlJobLog.getHandleCode()) {
|
|
||||||
XxlJobInfo xxlJobInfo = XxlJobAdminConfig.getAdminConfig().getXxlJobInfoDao().loadById(xxlJobLog.getJobId());
|
|
||||||
if (xxlJobInfo != null && xxlJobInfo.getChildJobId() != null && xxlJobInfo.getChildJobId().trim().length() > 0) {
|
|
||||||
triggerChildMsg = "<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>" + I18nUtil.getString("jobconf_trigger_child_run") + "<<<<<<<<<<< </span><br>";
|
|
||||||
|
|
||||||
String[] childJobIds = xxlJobInfo.getChildJobId().split(",");
|
|
||||||
for (int i = 0; i < childJobIds.length; i++) {
|
|
||||||
int childJobId = (childJobIds[i] != null && childJobIds[i].trim().length() > 0 && isNumeric(childJobIds[i])) ? Integer.valueOf(childJobIds[i]) : -1;
|
|
||||||
if (childJobId > 0) {
|
|
||||||
|
|
||||||
JobTriggerPoolHelper.trigger(childJobId, TriggerTypeEnum.PARENT, -1, null, null, null);
|
|
||||||
ReturnT<String> triggerChildResult = ReturnT.SUCCESS;
|
|
||||||
|
|
||||||
// add msg
|
|
||||||
triggerChildMsg += MessageFormat.format(I18nUtil.getString("jobconf_callback_child_msg1"),
|
|
||||||
(i + 1),
|
|
||||||
childJobIds.length,
|
|
||||||
childJobIds[i],
|
|
||||||
(triggerChildResult.getCode() == ReturnT.SUCCESS_CODE ? I18nUtil.getString("system_success") : I18nUtil.getString("system_fail")),
|
|
||||||
triggerChildResult.getMsg());
|
|
||||||
} else {
|
|
||||||
triggerChildMsg += MessageFormat.format(I18nUtil.getString("jobconf_callback_child_msg2"),
|
|
||||||
(i + 1),
|
|
||||||
childJobIds.length,
|
|
||||||
childJobIds[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (triggerChildMsg != null) {
|
|
||||||
xxlJobLog.setHandleMsg(xxlJobLog.getHandleMsg() + triggerChildMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2、fix_delay trigger next
|
|
||||||
// on the way
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isNumeric(String str) {
|
|
||||||
try {
|
|
||||||
int result = Integer.valueOf(str);
|
|
||||||
return true;
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,159 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.conf;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.alarm.JobAlarmer;
|
|
||||||
import com.xxl.job.admin.core.scheduler.XxlJobScheduler;
|
|
||||||
import com.xxl.job.admin.dao.*;
|
|
||||||
import org.springframework.beans.factory.DisposableBean;
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.mail.javamail.JavaMailSender;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.sql.DataSource;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* xxl-job config
|
|
||||||
*
|
|
||||||
* @author xuxueli 2017-04-28
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class XxlJobAdminConfig implements InitializingBean, DisposableBean {
|
|
||||||
|
|
||||||
private static XxlJobAdminConfig adminConfig = null;
|
|
||||||
|
|
||||||
public static XxlJobAdminConfig getAdminConfig() {
|
|
||||||
return adminConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------- XxlJobScheduler ----------------------
|
|
||||||
|
|
||||||
private XxlJobScheduler xxlJobScheduler;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterPropertiesSet() throws Exception {
|
|
||||||
adminConfig = this;
|
|
||||||
|
|
||||||
xxlJobScheduler = new XxlJobScheduler();
|
|
||||||
xxlJobScheduler.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void destroy() throws Exception {
|
|
||||||
xxlJobScheduler.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------- XxlJobScheduler ----------------------
|
|
||||||
|
|
||||||
// conf
|
|
||||||
@Value("${xxl.job.i18n}")
|
|
||||||
private String i18n;
|
|
||||||
|
|
||||||
@Value("${xxl.job.accessToken}")
|
|
||||||
private String accessToken;
|
|
||||||
|
|
||||||
@Value("${spring.mail.from}")
|
|
||||||
private String emailFrom;
|
|
||||||
|
|
||||||
@Value("${xxl.job.triggerpool.fast.max}")
|
|
||||||
private int triggerPoolFastMax;
|
|
||||||
|
|
||||||
@Value("${xxl.job.triggerpool.slow.max}")
|
|
||||||
private int triggerPoolSlowMax;
|
|
||||||
|
|
||||||
@Value("${xxl.job.logretentiondays}")
|
|
||||||
private int logretentiondays;
|
|
||||||
|
|
||||||
// dao, service
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private XxlJobLogDao xxlJobLogDao;
|
|
||||||
@Resource
|
|
||||||
private XxlJobInfoDao xxlJobInfoDao;
|
|
||||||
@Resource
|
|
||||||
private XxlJobRegistryDao xxlJobRegistryDao;
|
|
||||||
@Resource
|
|
||||||
private XxlJobGroupDao xxlJobGroupDao;
|
|
||||||
@Resource
|
|
||||||
private XxlJobLogReportDao xxlJobLogReportDao;
|
|
||||||
@Resource
|
|
||||||
private JavaMailSender mailSender;
|
|
||||||
@Resource
|
|
||||||
private DataSource dataSource;
|
|
||||||
@Resource
|
|
||||||
private JobAlarmer jobAlarmer;
|
|
||||||
|
|
||||||
|
|
||||||
public String getI18n() {
|
|
||||||
if (!Arrays.asList("zh_CN", "zh_TC", "en").contains(i18n)) {
|
|
||||||
return "zh_CN";
|
|
||||||
}
|
|
||||||
return i18n;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAccessToken() {
|
|
||||||
return accessToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getEmailFrom() {
|
|
||||||
return emailFrom;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTriggerPoolFastMax() {
|
|
||||||
if (triggerPoolFastMax < 200) {
|
|
||||||
return 200;
|
|
||||||
}
|
|
||||||
return triggerPoolFastMax;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTriggerPoolSlowMax() {
|
|
||||||
if (triggerPoolSlowMax < 100) {
|
|
||||||
return 100;
|
|
||||||
}
|
|
||||||
return triggerPoolSlowMax;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getLogretentiondays() {
|
|
||||||
if (logretentiondays < 7) {
|
|
||||||
return -1; // Limit greater than or equal to 7, otherwise close
|
|
||||||
}
|
|
||||||
return logretentiondays;
|
|
||||||
}
|
|
||||||
|
|
||||||
public XxlJobLogDao getXxlJobLogDao() {
|
|
||||||
return xxlJobLogDao;
|
|
||||||
}
|
|
||||||
|
|
||||||
public XxlJobInfoDao getXxlJobInfoDao() {
|
|
||||||
return xxlJobInfoDao;
|
|
||||||
}
|
|
||||||
|
|
||||||
public XxlJobRegistryDao getXxlJobRegistryDao() {
|
|
||||||
return xxlJobRegistryDao;
|
|
||||||
}
|
|
||||||
|
|
||||||
public XxlJobGroupDao getXxlJobGroupDao() {
|
|
||||||
return xxlJobGroupDao;
|
|
||||||
}
|
|
||||||
|
|
||||||
public XxlJobLogReportDao getXxlJobLogReportDao() {
|
|
||||||
return xxlJobLogReportDao;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JavaMailSender getMailSender() {
|
|
||||||
return mailSender;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataSource getDataSource() {
|
|
||||||
return dataSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JobAlarmer getJobAlarmer() {
|
|
||||||
return jobAlarmer;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,15 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author xuxueli 2019-05-04 23:19:29
|
|
||||||
*/
|
|
||||||
public class XxlJobException extends RuntimeException {
|
|
||||||
|
|
||||||
public XxlJobException() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public XxlJobException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,78 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.model;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by xuxueli on 16/9/30.
|
|
||||||
*/
|
|
||||||
public class XxlJobGroup {
|
|
||||||
|
|
||||||
private int id;
|
|
||||||
private String appname;
|
|
||||||
private String title;
|
|
||||||
private int addressType; // 执行器地址类型:0=自动注册、1=手动录入
|
|
||||||
private String addressList; // 执行器地址列表,多地址逗号分隔(手动录入)
|
|
||||||
private Date updateTime;
|
|
||||||
|
|
||||||
// registry list
|
|
||||||
private List<String> registryList; // 执行器地址列表(系统注册)
|
|
||||||
|
|
||||||
public List<String> getRegistryList() {
|
|
||||||
if (addressList != null && addressList.trim().length() > 0) {
|
|
||||||
registryList = new ArrayList<String>(Arrays.asList(addressList.split(",")));
|
|
||||||
}
|
|
||||||
return registryList;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(int id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAppname() {
|
|
||||||
return appname;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAppname(String appname) {
|
|
||||||
this.appname = appname;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTitle(String title) {
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getAddressType() {
|
|
||||||
return addressType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAddressType(int addressType) {
|
|
||||||
this.addressType = addressType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAddressList() {
|
|
||||||
return addressList;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getUpdateTime() {
|
|
||||||
return updateTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUpdateTime(Date updateTime) {
|
|
||||||
this.updateTime = updateTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAddressList(String addressList) {
|
|
||||||
this.addressList = addressList;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,237 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.model;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* xxl-job info
|
|
||||||
*
|
|
||||||
* @author xuxueli 2016-1-12 18:25:49
|
|
||||||
*/
|
|
||||||
public class XxlJobInfo {
|
|
||||||
|
|
||||||
private int id; // 主键ID
|
|
||||||
|
|
||||||
private int jobGroup; // 执行器主键ID
|
|
||||||
private String jobDesc;
|
|
||||||
|
|
||||||
private Date addTime;
|
|
||||||
private Date updateTime;
|
|
||||||
|
|
||||||
private String author; // 负责人
|
|
||||||
private String alarmEmail; // 报警邮件
|
|
||||||
|
|
||||||
private String scheduleType; // 调度类型
|
|
||||||
private String scheduleConf; // 调度配置,值含义取决于调度类型
|
|
||||||
private String misfireStrategy; // 调度过期策略
|
|
||||||
|
|
||||||
private String executorRouteStrategy; // 执行器路由策略
|
|
||||||
private String executorHandler; // 执行器,任务Handler名称
|
|
||||||
private String executorParam; // 执行器,任务参数
|
|
||||||
private String executorBlockStrategy; // 阻塞处理策略
|
|
||||||
private int executorTimeout; // 任务执行超时时间,单位秒
|
|
||||||
private int executorFailRetryCount; // 失败重试次数
|
|
||||||
|
|
||||||
private String glueType; // GLUE类型 #com.xxl.job.core.glue.GlueTypeEnum
|
|
||||||
private String glueSource; // GLUE源代码
|
|
||||||
private String glueRemark; // GLUE备注
|
|
||||||
private Date glueUpdatetime; // GLUE更新时间
|
|
||||||
|
|
||||||
private String childJobId; // 子任务ID,多个逗号分隔
|
|
||||||
|
|
||||||
private int triggerStatus; // 调度状态:0-停止,1-运行
|
|
||||||
private long triggerLastTime; // 上次调度时间
|
|
||||||
private long triggerNextTime; // 下次调度时间
|
|
||||||
|
|
||||||
|
|
||||||
public int getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(int id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getJobGroup() {
|
|
||||||
return jobGroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setJobGroup(int jobGroup) {
|
|
||||||
this.jobGroup = jobGroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getJobDesc() {
|
|
||||||
return jobDesc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setJobDesc(String jobDesc) {
|
|
||||||
this.jobDesc = jobDesc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getAddTime() {
|
|
||||||
return addTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAddTime(Date addTime) {
|
|
||||||
this.addTime = addTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getUpdateTime() {
|
|
||||||
return updateTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUpdateTime(Date updateTime) {
|
|
||||||
this.updateTime = updateTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAuthor() {
|
|
||||||
return author;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAuthor(String author) {
|
|
||||||
this.author = author;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAlarmEmail() {
|
|
||||||
return alarmEmail;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAlarmEmail(String alarmEmail) {
|
|
||||||
this.alarmEmail = alarmEmail;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getScheduleType() {
|
|
||||||
return scheduleType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setScheduleType(String scheduleType) {
|
|
||||||
this.scheduleType = scheduleType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getScheduleConf() {
|
|
||||||
return scheduleConf;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setScheduleConf(String scheduleConf) {
|
|
||||||
this.scheduleConf = scheduleConf;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMisfireStrategy() {
|
|
||||||
return misfireStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMisfireStrategy(String misfireStrategy) {
|
|
||||||
this.misfireStrategy = misfireStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getExecutorRouteStrategy() {
|
|
||||||
return executorRouteStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExecutorRouteStrategy(String executorRouteStrategy) {
|
|
||||||
this.executorRouteStrategy = executorRouteStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getExecutorHandler() {
|
|
||||||
return executorHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExecutorHandler(String executorHandler) {
|
|
||||||
this.executorHandler = executorHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getExecutorParam() {
|
|
||||||
return executorParam;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExecutorParam(String executorParam) {
|
|
||||||
this.executorParam = executorParam;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getExecutorBlockStrategy() {
|
|
||||||
return executorBlockStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExecutorBlockStrategy(String executorBlockStrategy) {
|
|
||||||
this.executorBlockStrategy = executorBlockStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getExecutorTimeout() {
|
|
||||||
return executorTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExecutorTimeout(int executorTimeout) {
|
|
||||||
this.executorTimeout = executorTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getExecutorFailRetryCount() {
|
|
||||||
return executorFailRetryCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExecutorFailRetryCount(int executorFailRetryCount) {
|
|
||||||
this.executorFailRetryCount = executorFailRetryCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getGlueType() {
|
|
||||||
return glueType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGlueType(String glueType) {
|
|
||||||
this.glueType = glueType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getGlueSource() {
|
|
||||||
return glueSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGlueSource(String glueSource) {
|
|
||||||
this.glueSource = glueSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getGlueRemark() {
|
|
||||||
return glueRemark;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGlueRemark(String glueRemark) {
|
|
||||||
this.glueRemark = glueRemark;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getGlueUpdatetime() {
|
|
||||||
return glueUpdatetime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGlueUpdatetime(Date glueUpdatetime) {
|
|
||||||
this.glueUpdatetime = glueUpdatetime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getChildJobId() {
|
|
||||||
return childJobId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setChildJobId(String childJobId) {
|
|
||||||
this.childJobId = childJobId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTriggerStatus() {
|
|
||||||
return triggerStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTriggerStatus(int triggerStatus) {
|
|
||||||
this.triggerStatus = triggerStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTriggerLastTime() {
|
|
||||||
return triggerLastTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTriggerLastTime(long triggerLastTime) {
|
|
||||||
this.triggerLastTime = triggerLastTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTriggerNextTime() {
|
|
||||||
return triggerNextTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTriggerNextTime(long triggerNextTime) {
|
|
||||||
this.triggerNextTime = triggerNextTime;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,158 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.model;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* xxl-job log, used to track trigger process
|
|
||||||
*
|
|
||||||
* @author xuxueli 2015-12-19 23:19:09
|
|
||||||
*/
|
|
||||||
public class XxlJobLog {
|
|
||||||
|
|
||||||
private long id;
|
|
||||||
|
|
||||||
// job info
|
|
||||||
private int jobGroup;
|
|
||||||
private int jobId;
|
|
||||||
|
|
||||||
// execute info
|
|
||||||
private String executorAddress;
|
|
||||||
private String executorHandler;
|
|
||||||
private String executorParam;
|
|
||||||
private String executorShardingParam;
|
|
||||||
private int executorFailRetryCount;
|
|
||||||
|
|
||||||
// trigger info
|
|
||||||
private Date triggerTime;
|
|
||||||
private int triggerCode;
|
|
||||||
private String triggerMsg;
|
|
||||||
|
|
||||||
// handle info
|
|
||||||
private Date handleTime;
|
|
||||||
private int handleCode;
|
|
||||||
private String handleMsg;
|
|
||||||
|
|
||||||
// alarm info
|
|
||||||
private int alarmStatus;
|
|
||||||
|
|
||||||
public long getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(long id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getJobGroup() {
|
|
||||||
return jobGroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setJobGroup(int jobGroup) {
|
|
||||||
this.jobGroup = jobGroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getJobId() {
|
|
||||||
return jobId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setJobId(int jobId) {
|
|
||||||
this.jobId = jobId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getExecutorAddress() {
|
|
||||||
return executorAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExecutorAddress(String executorAddress) {
|
|
||||||
this.executorAddress = executorAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getExecutorHandler() {
|
|
||||||
return executorHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExecutorHandler(String executorHandler) {
|
|
||||||
this.executorHandler = executorHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getExecutorParam() {
|
|
||||||
return executorParam;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExecutorParam(String executorParam) {
|
|
||||||
this.executorParam = executorParam;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getExecutorShardingParam() {
|
|
||||||
return executorShardingParam;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExecutorShardingParam(String executorShardingParam) {
|
|
||||||
this.executorShardingParam = executorShardingParam;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getExecutorFailRetryCount() {
|
|
||||||
return executorFailRetryCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExecutorFailRetryCount(int executorFailRetryCount) {
|
|
||||||
this.executorFailRetryCount = executorFailRetryCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getTriggerTime() {
|
|
||||||
return triggerTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTriggerTime(Date triggerTime) {
|
|
||||||
this.triggerTime = triggerTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTriggerCode() {
|
|
||||||
return triggerCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTriggerCode(int triggerCode) {
|
|
||||||
this.triggerCode = triggerCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTriggerMsg() {
|
|
||||||
return triggerMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTriggerMsg(String triggerMsg) {
|
|
||||||
this.triggerMsg = triggerMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getHandleTime() {
|
|
||||||
return handleTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHandleTime(Date handleTime) {
|
|
||||||
this.handleTime = handleTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHandleCode() {
|
|
||||||
return handleCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHandleCode(int handleCode) {
|
|
||||||
this.handleCode = handleCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getHandleMsg() {
|
|
||||||
return handleMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHandleMsg(String handleMsg) {
|
|
||||||
this.handleMsg = handleMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getAlarmStatus() {
|
|
||||||
return alarmStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAlarmStatus(int alarmStatus) {
|
|
||||||
this.alarmStatus = alarmStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.model;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* xxl-job log for glue, used to track job code process
|
|
||||||
*
|
|
||||||
* @author xuxueli 2016-5-19 17:57:46
|
|
||||||
*/
|
|
||||||
public class XxlJobLogGlue {
|
|
||||||
|
|
||||||
private int id;
|
|
||||||
private int jobId; // 任务主键ID
|
|
||||||
private String glueType; // GLUE类型 #com.xxl.job.core.glue.GlueTypeEnum
|
|
||||||
private String glueSource;
|
|
||||||
private String glueRemark;
|
|
||||||
private Date addTime;
|
|
||||||
private Date updateTime;
|
|
||||||
|
|
||||||
public int getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(int id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getJobId() {
|
|
||||||
return jobId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setJobId(int jobId) {
|
|
||||||
this.jobId = jobId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getGlueType() {
|
|
||||||
return glueType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGlueType(String glueType) {
|
|
||||||
this.glueType = glueType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getGlueSource() {
|
|
||||||
return glueSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGlueSource(String glueSource) {
|
|
||||||
this.glueSource = glueSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getGlueRemark() {
|
|
||||||
return glueRemark;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGlueRemark(String glueRemark) {
|
|
||||||
this.glueRemark = glueRemark;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getAddTime() {
|
|
||||||
return addTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAddTime(Date addTime) {
|
|
||||||
this.addTime = addTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getUpdateTime() {
|
|
||||||
return updateTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUpdateTime(Date updateTime) {
|
|
||||||
this.updateTime = updateTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.model;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
public class XxlJobLogReport {
|
|
||||||
|
|
||||||
private int id;
|
|
||||||
|
|
||||||
private Date triggerDay;
|
|
||||||
|
|
||||||
private int runningCount;
|
|
||||||
private int sucCount;
|
|
||||||
private int failCount;
|
|
||||||
|
|
||||||
public int getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(int id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getTriggerDay() {
|
|
||||||
return triggerDay;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTriggerDay(Date triggerDay) {
|
|
||||||
this.triggerDay = triggerDay;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getRunningCount() {
|
|
||||||
return runningCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRunningCount(int runningCount) {
|
|
||||||
this.runningCount = runningCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSucCount() {
|
|
||||||
return sucCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSucCount(int sucCount) {
|
|
||||||
this.sucCount = sucCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getFailCount() {
|
|
||||||
return failCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFailCount(int failCount) {
|
|
||||||
this.failCount = failCount;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.model;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by xuxueli on 16/9/30.
|
|
||||||
*/
|
|
||||||
public class XxlJobRegistry {
|
|
||||||
|
|
||||||
private int id;
|
|
||||||
private String registryGroup;
|
|
||||||
private String registryKey;
|
|
||||||
private String registryValue;
|
|
||||||
private Date updateTime;
|
|
||||||
|
|
||||||
public int getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(int id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRegistryGroup() {
|
|
||||||
return registryGroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRegistryGroup(String registryGroup) {
|
|
||||||
this.registryGroup = registryGroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRegistryKey() {
|
|
||||||
return registryKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRegistryKey(String registryKey) {
|
|
||||||
this.registryKey = registryKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRegistryValue() {
|
|
||||||
return registryValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRegistryValue(String registryValue) {
|
|
||||||
this.registryValue = registryValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getUpdateTime() {
|
|
||||||
return updateTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUpdateTime(Date updateTime) {
|
|
||||||
this.updateTime = updateTime;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,73 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.model;
|
|
||||||
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author xuxueli 2019-05-04 16:43:12
|
|
||||||
*/
|
|
||||||
public class XxlJobUser {
|
|
||||||
|
|
||||||
private int id;
|
|
||||||
private String username; // 账号
|
|
||||||
private String password; // 密码
|
|
||||||
private int role; // 角色:0-普通用户、1-管理员
|
|
||||||
private String permission; // 权限:执行器ID列表,多个逗号分割
|
|
||||||
|
|
||||||
public int getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(int id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUsername() {
|
|
||||||
return username;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUsername(String username) {
|
|
||||||
this.username = username;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPassword() {
|
|
||||||
return password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPassword(String password) {
|
|
||||||
this.password = password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getRole() {
|
|
||||||
return role;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRole(int role) {
|
|
||||||
this.role = role;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPermission() {
|
|
||||||
return permission;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPermission(String permission) {
|
|
||||||
this.permission = permission;
|
|
||||||
}
|
|
||||||
|
|
||||||
// plugin
|
|
||||||
public boolean validPermission(int jobGroup) {
|
|
||||||
if (this.role == 1) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
if (StringUtils.hasText(this.permission)) {
|
|
||||||
for (String permissionItem : this.permission.split(",")) {
|
|
||||||
if (String.valueOf(jobGroup).equals(permissionItem)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.old;//package com.xxl.job.admin.core.jobbean;
|
|
||||||
//
|
|
||||||
//import com.xxl.job.admin.core.thread.JobTriggerPoolHelper;
|
|
||||||
//import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
|
|
||||||
//import org.quartz.JobExecutionContext;
|
|
||||||
//import org.quartz.JobExecutionException;
|
|
||||||
//import org.quartz.JobKey;
|
|
||||||
//import org.slf4j.Logger;
|
|
||||||
//import org.slf4j.LoggerFactory;
|
|
||||||
//import org.springframework.scheduling.quartz.QuartzJobBean;
|
|
||||||
//
|
|
||||||
///**
|
|
||||||
// * http job bean
|
|
||||||
// * “@DisallowConcurrentExecution” disable concurrent, thread size can not be only one, better given more
|
|
||||||
// * @author xuxueli 2015-12-17 18:20:34
|
|
||||||
// */
|
|
||||||
////@DisallowConcurrentExecution
|
|
||||||
//public class RemoteHttpJobBean extends QuartzJobBean {
|
|
||||||
// private static Logger logger = LoggerFactory.getLogger(RemoteHttpJobBean.class);
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// protected void executeInternal(JobExecutionContext context)
|
|
||||||
// throws JobExecutionException {
|
|
||||||
//
|
|
||||||
// // load jobId
|
|
||||||
// JobKey jobKey = context.getTrigger().getJobKey();
|
|
||||||
// Integer jobId = Integer.valueOf(jobKey.getName());
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//}
|
|
@ -1,413 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.old;//package com.xxl.job.admin.core.schedule;
|
|
||||||
//
|
|
||||||
//import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
|
||||||
//import com.xxl.job.admin.core.jobbean.RemoteHttpJobBean;
|
|
||||||
//import com.xxl.job.admin.core.model.XxlJobInfo;
|
|
||||||
//import com.xxl.job.admin.core.thread.JobFailMonitorHelper;
|
|
||||||
//import com.xxl.job.admin.core.thread.JobRegistryMonitorHelper;
|
|
||||||
//import com.xxl.job.admin.core.thread.JobTriggerPoolHelper;
|
|
||||||
//import com.xxl.job.admin.core.util.I18nUtil;
|
|
||||||
//import com.xxl.job.core.biz.AdminBiz;
|
|
||||||
//import com.xxl.job.core.biz.ExecutorBiz;
|
|
||||||
//import com.xxl.job.core.enums.ExecutorBlockStrategyEnum;
|
|
||||||
//import com.xxl.rpc.remoting.invoker.XxlRpcInvokerFactory;
|
|
||||||
//import com.xxl.rpc.remoting.invoker.call.CallType;
|
|
||||||
//import com.xxl.rpc.remoting.invoker.reference.XxlRpcReferenceBean;
|
|
||||||
//import com.xxl.rpc.remoting.invoker.route.LoadBalance;
|
|
||||||
//import com.xxl.rpc.remoting.net.NetEnum;
|
|
||||||
//import com.xxl.rpc.remoting.net.impl.servlet.server.ServletServerHandler;
|
|
||||||
//import com.xxl.rpc.remoting.provider.XxlRpcProviderFactory;
|
|
||||||
//import com.xxl.rpc.serialize.Serializer;
|
|
||||||
//import org.quartz.*;
|
|
||||||
//import org.quartz.Trigger.TriggerState;
|
|
||||||
//import org.quartz.impl.triggers.CronTriggerImpl;
|
|
||||||
//import org.slf4j.Logger;
|
|
||||||
//import org.slf4j.LoggerFactory;
|
|
||||||
//import org.springframework.util.Assert;
|
|
||||||
//
|
|
||||||
//import javax.servlet.ServletException;
|
|
||||||
//import javax.servlet.http.HttpServletRequest;
|
|
||||||
//import javax.servlet.http.HttpServletResponse;
|
|
||||||
//import java.io.IOException;
|
|
||||||
//import java.util.Date;
|
|
||||||
//import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
//
|
|
||||||
///**
|
|
||||||
// * base quartz scheduler util
|
|
||||||
// * @author xuxueli 2015-12-19 16:13:53
|
|
||||||
// */
|
|
||||||
//public final class XxlJobDynamicScheduler {
|
|
||||||
// private static final Logger logger = LoggerFactory.getLogger(XxlJobDynamicScheduler_old.class);
|
|
||||||
//
|
|
||||||
// // ---------------------- param ----------------------
|
|
||||||
//
|
|
||||||
// // scheduler
|
|
||||||
// private static Scheduler scheduler;
|
|
||||||
// public void setScheduler(Scheduler scheduler) {
|
|
||||||
// XxlJobDynamicScheduler_old.scheduler = scheduler;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// // ---------------------- init + destroy ----------------------
|
|
||||||
// public void start() throws Exception {
|
|
||||||
// // valid
|
|
||||||
// Assert.notNull(scheduler, "quartz scheduler is null");
|
|
||||||
//
|
|
||||||
// // init i18n
|
|
||||||
// initI18n();
|
|
||||||
//
|
|
||||||
// // admin registry monitor run
|
|
||||||
// JobRegistryMonitorHelper.getInstance().start();
|
|
||||||
//
|
|
||||||
// // admin monitor run
|
|
||||||
// JobFailMonitorHelper.getInstance().start();
|
|
||||||
//
|
|
||||||
// // admin-server
|
|
||||||
// initRpcProvider();
|
|
||||||
//
|
|
||||||
// logger.info(">>>>>>>>> init xxl-job admin success.");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// public void destroy() throws Exception {
|
|
||||||
// // admin trigger pool stop
|
|
||||||
// JobTriggerPoolHelper.toStop();
|
|
||||||
//
|
|
||||||
// // admin registry stop
|
|
||||||
// JobRegistryMonitorHelper.getInstance().toStop();
|
|
||||||
//
|
|
||||||
// // admin monitor stop
|
|
||||||
// JobFailMonitorHelper.getInstance().toStop();
|
|
||||||
//
|
|
||||||
// // admin-server
|
|
||||||
// stopRpcProvider();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// // ---------------------- I18n ----------------------
|
|
||||||
//
|
|
||||||
// private void initI18n(){
|
|
||||||
// for (ExecutorBlockStrategyEnum item:ExecutorBlockStrategyEnum.values()) {
|
|
||||||
// item.setTitle(I18nUtil.getString("jobconf_block_".concat(item.name())));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// // ---------------------- admin rpc provider (no server version) ----------------------
|
|
||||||
// private static ServletServerHandler servletServerHandler;
|
|
||||||
// private void initRpcProvider(){
|
|
||||||
// // init
|
|
||||||
// XxlRpcProviderFactory xxlRpcProviderFactory = new XxlRpcProviderFactory();
|
|
||||||
// xxlRpcProviderFactory.initConfig(
|
|
||||||
// NetEnum.NETTY_HTTP,
|
|
||||||
// Serializer.SerializeEnum.HESSIAN.getSerializer(),
|
|
||||||
// null,
|
|
||||||
// 0,
|
|
||||||
// XxlJobAdminConfig.getAdminConfig().getAccessToken(),
|
|
||||||
// null,
|
|
||||||
// null);
|
|
||||||
//
|
|
||||||
// // add services
|
|
||||||
// xxlRpcProviderFactory.addService(AdminBiz.class.getName(), null, XxlJobAdminConfig.getAdminConfig().getAdminBiz());
|
|
||||||
//
|
|
||||||
// // servlet handler
|
|
||||||
// servletServerHandler = new ServletServerHandler(xxlRpcProviderFactory);
|
|
||||||
// }
|
|
||||||
// private void stopRpcProvider() throws Exception {
|
|
||||||
// XxlRpcInvokerFactory.getInstance().stop();
|
|
||||||
// }
|
|
||||||
// public static void invokeAdminService(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
|
||||||
// servletServerHandler.handle(null, request, response);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// // ---------------------- executor-client ----------------------
|
|
||||||
// private static ConcurrentHashMap<String, ExecutorBiz> executorBizRepository = new ConcurrentHashMap<String, ExecutorBiz>();
|
|
||||||
// public static ExecutorBiz getExecutorBiz(String address) throws Exception {
|
|
||||||
// // valid
|
|
||||||
// if (address==null || address.trim().length()==0) {
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // load-cache
|
|
||||||
// address = address.trim();
|
|
||||||
// ExecutorBiz executorBiz = executorBizRepository.get(address);
|
|
||||||
// if (executorBiz != null) {
|
|
||||||
// return executorBiz;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // set-cache
|
|
||||||
// executorBiz = (ExecutorBiz) new XxlRpcReferenceBean(
|
|
||||||
// NetEnum.NETTY_HTTP,
|
|
||||||
// Serializer.SerializeEnum.HESSIAN.getSerializer(),
|
|
||||||
// CallType.SYNC,
|
|
||||||
// LoadBalance.ROUND,
|
|
||||||
// ExecutorBiz.class,
|
|
||||||
// null,
|
|
||||||
// 5000,
|
|
||||||
// address,
|
|
||||||
// XxlJobAdminConfig.getAdminConfig().getAccessToken(),
|
|
||||||
// null,
|
|
||||||
// null).getObject();
|
|
||||||
//
|
|
||||||
// executorBizRepository.put(address, executorBiz);
|
|
||||||
// return executorBiz;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// // ---------------------- schedule util ----------------------
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * fill job info
|
|
||||||
// *
|
|
||||||
// * @param jobInfo
|
|
||||||
// */
|
|
||||||
// public static void fillJobInfo(XxlJobInfo jobInfo) {
|
|
||||||
//
|
|
||||||
// String name = String.valueOf(jobInfo.getId());
|
|
||||||
//
|
|
||||||
// // trigger key
|
|
||||||
// TriggerKey triggerKey = TriggerKey.triggerKey(name);
|
|
||||||
// try {
|
|
||||||
//
|
|
||||||
// // trigger cron
|
|
||||||
// Trigger trigger = scheduler.getTrigger(triggerKey);
|
|
||||||
// if (trigger!=null && trigger instanceof CronTriggerImpl) {
|
|
||||||
// String cronExpression = ((CronTriggerImpl) trigger).getCronExpression();
|
|
||||||
// jobInfo.setJobCron(cronExpression);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // trigger state
|
|
||||||
// TriggerState triggerState = scheduler.getTriggerState(triggerKey);
|
|
||||||
// if (triggerState!=null) {
|
|
||||||
// jobInfo.setJobStatus(triggerState.name());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// //JobKey jobKey = new JobKey(jobInfo.getJobName(), String.valueOf(jobInfo.getJobGroup()));
|
|
||||||
// //JobDetail jobDetail = scheduler.getJobDetail(jobKey);
|
|
||||||
// //String jobClass = jobDetail.getJobClass().getName();
|
|
||||||
//
|
|
||||||
// } catch (SchedulerException e) {
|
|
||||||
// logger.error(e.getMessage(), e);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * add trigger + job
|
|
||||||
// *
|
|
||||||
// * @param jobName
|
|
||||||
// * @param cronExpression
|
|
||||||
// * @return
|
|
||||||
// * @throws SchedulerException
|
|
||||||
// */
|
|
||||||
// public static boolean addJob(String jobName, String cronExpression) throws SchedulerException {
|
|
||||||
// // 1、job key
|
|
||||||
// TriggerKey triggerKey = TriggerKey.triggerKey(jobName);
|
|
||||||
// JobKey jobKey = new JobKey(jobName);
|
|
||||||
//
|
|
||||||
// // 2、valid
|
|
||||||
// if (scheduler.checkExists(triggerKey)) {
|
|
||||||
// return true; // PASS
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // 3、corn trigger
|
|
||||||
// CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing(); // withMisfireHandlingInstructionDoNothing 忽略掉调度终止过程中忽略的调度
|
|
||||||
// CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();
|
|
||||||
//
|
|
||||||
// // 4、job detail
|
|
||||||
// Class<? extends Job> jobClass_ = RemoteHttpJobBean.class; // Class.forName(jobInfo.getJobClass());
|
|
||||||
// JobDetail jobDetail = JobBuilder.newJob(jobClass_).withIdentity(jobKey).build();
|
|
||||||
//
|
|
||||||
// /*if (jobInfo.getJobData()!=null) {
|
|
||||||
// JobDataMap jobDataMap = jobDetail.getJobDataMap();
|
|
||||||
// jobDataMap.putAll(JacksonUtil.readValue(jobInfo.getJobData(), Map.class));
|
|
||||||
// // JobExecutionContext context.getMergedJobDataMap().get("mailGuid");
|
|
||||||
// }*/
|
|
||||||
//
|
|
||||||
// // 5、schedule job
|
|
||||||
// Date date = scheduler.scheduleJob(jobDetail, cronTrigger);
|
|
||||||
//
|
|
||||||
// logger.info(">>>>>>>>>>> addJob success(quartz), jobDetail:{}, cronTrigger:{}, date:{}", jobDetail, cronTrigger, date);
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * remove trigger + job
|
|
||||||
// *
|
|
||||||
// * @param jobName
|
|
||||||
// * @return
|
|
||||||
// * @throws SchedulerException
|
|
||||||
// */
|
|
||||||
// public static boolean removeJob(String jobName) throws SchedulerException {
|
|
||||||
//
|
|
||||||
// JobKey jobKey = new JobKey(jobName);
|
|
||||||
// scheduler.deleteJob(jobKey);
|
|
||||||
//
|
|
||||||
// /*TriggerKey triggerKey = TriggerKey.triggerKey(jobName);
|
|
||||||
// if (scheduler.checkExists(triggerKey)) {
|
|
||||||
// scheduler.unscheduleJob(triggerKey); // trigger + job
|
|
||||||
// }*/
|
|
||||||
//
|
|
||||||
// logger.info(">>>>>>>>>>> removeJob success(quartz), jobKey:{}", jobKey);
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * updateJobCron
|
|
||||||
// *
|
|
||||||
// * @param jobName
|
|
||||||
// * @param cronExpression
|
|
||||||
// * @return
|
|
||||||
// * @throws SchedulerException
|
|
||||||
// */
|
|
||||||
// public static boolean updateJobCron(String jobName, String cronExpression) throws SchedulerException {
|
|
||||||
//
|
|
||||||
// // 1、job key
|
|
||||||
// TriggerKey triggerKey = TriggerKey.triggerKey(jobName);
|
|
||||||
//
|
|
||||||
// // 2、valid
|
|
||||||
// if (!scheduler.checkExists(triggerKey)) {
|
|
||||||
// return true; // PASS
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// CronTrigger oldTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
|
|
||||||
//
|
|
||||||
// // 3、avoid repeat cron
|
|
||||||
// String oldCron = oldTrigger.getCronExpression();
|
|
||||||
// if (oldCron.equals(cronExpression)){
|
|
||||||
// return true; // PASS
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // 4、new cron trigger
|
|
||||||
// CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing();
|
|
||||||
// oldTrigger = oldTrigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();
|
|
||||||
//
|
|
||||||
// // 5、rescheduleJob
|
|
||||||
// scheduler.rescheduleJob(triggerKey, oldTrigger);
|
|
||||||
//
|
|
||||||
// /*
|
|
||||||
// JobKey jobKey = new JobKey(jobName);
|
|
||||||
//
|
|
||||||
// // old job detail
|
|
||||||
// JobDetail jobDetail = scheduler.getJobDetail(jobKey);
|
|
||||||
//
|
|
||||||
// // new trigger
|
|
||||||
// HashSet<Trigger> triggerSet = new HashSet<Trigger>();
|
|
||||||
// triggerSet.add(cronTrigger);
|
|
||||||
// // cover trigger of job detail
|
|
||||||
// scheduler.scheduleJob(jobDetail, triggerSet, true);*/
|
|
||||||
//
|
|
||||||
// logger.info(">>>>>>>>>>> resumeJob success, JobName:{}", jobName);
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * pause
|
|
||||||
// *
|
|
||||||
// * @param jobName
|
|
||||||
// * @return
|
|
||||||
// * @throws SchedulerException
|
|
||||||
// */
|
|
||||||
// /*public static boolean pauseJob(String jobName) throws SchedulerException {
|
|
||||||
//
|
|
||||||
// TriggerKey triggerKey = TriggerKey.triggerKey(jobName);
|
|
||||||
//
|
|
||||||
// boolean result = false;
|
|
||||||
// if (scheduler.checkExists(triggerKey)) {
|
|
||||||
// scheduler.pauseTrigger(triggerKey);
|
|
||||||
// result = true;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// logger.info(">>>>>>>>>>> pauseJob {}, triggerKey:{}", (result?"success":"fail"),triggerKey);
|
|
||||||
// return result;
|
|
||||||
// }*/
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * resume
|
|
||||||
// *
|
|
||||||
// * @param jobName
|
|
||||||
// * @return
|
|
||||||
// * @throws SchedulerException
|
|
||||||
// */
|
|
||||||
// /*public static boolean resumeJob(String jobName) throws SchedulerException {
|
|
||||||
//
|
|
||||||
// TriggerKey triggerKey = TriggerKey.triggerKey(jobName);
|
|
||||||
//
|
|
||||||
// boolean result = false;
|
|
||||||
// if (scheduler.checkExists(triggerKey)) {
|
|
||||||
// scheduler.resumeTrigger(triggerKey);
|
|
||||||
// result = true;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// logger.info(">>>>>>>>>>> resumeJob {}, triggerKey:{}", (result?"success":"fail"), triggerKey);
|
|
||||||
// return result;
|
|
||||||
// }*/
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * run
|
|
||||||
// *
|
|
||||||
// * @param jobName
|
|
||||||
// * @return
|
|
||||||
// * @throws SchedulerException
|
|
||||||
// */
|
|
||||||
// /*public static boolean triggerJob(String jobName) throws SchedulerException {
|
|
||||||
// // TriggerKey : name + group
|
|
||||||
// JobKey jobKey = new JobKey(jobName);
|
|
||||||
// TriggerKey triggerKey = TriggerKey.triggerKey(jobName);
|
|
||||||
//
|
|
||||||
// boolean result = false;
|
|
||||||
// if (scheduler.checkExists(triggerKey)) {
|
|
||||||
// scheduler.triggerJob(jobKey);
|
|
||||||
// result = true;
|
|
||||||
// logger.info(">>>>>>>>>>> runJob success, jobKey:{}", jobKey);
|
|
||||||
// } else {
|
|
||||||
// logger.info(">>>>>>>>>>> runJob fail, jobKey:{}", jobKey);
|
|
||||||
// }
|
|
||||||
// return result;
|
|
||||||
// }*/
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * finaAllJobList
|
|
||||||
// *
|
|
||||||
// * @return
|
|
||||||
// *//*
|
|
||||||
// @Deprecated
|
|
||||||
// public static List<Map<String, Object>> finaAllJobList(){
|
|
||||||
// List<Map<String, Object>> jobList = new ArrayList<Map<String,Object>>();
|
|
||||||
//
|
|
||||||
// try {
|
|
||||||
// if (scheduler.getJobGroupNames()==null || scheduler.getJobGroupNames().size()==0) {
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
// String groupName = scheduler.getJobGroupNames().get(0);
|
|
||||||
// Set<JobKey> jobKeys = scheduler.getJobKeys(GroupMatcher.jobGroupEquals(groupName));
|
|
||||||
// if (jobKeys!=null && jobKeys.size()>0) {
|
|
||||||
// for (JobKey jobKey : jobKeys) {
|
|
||||||
// TriggerKey triggerKey = TriggerKey.triggerKey(jobKey.getName(), Scheduler.DEFAULT_GROUP);
|
|
||||||
// Trigger trigger = scheduler.getTrigger(triggerKey);
|
|
||||||
// JobDetail jobDetail = scheduler.getJobDetail(jobKey);
|
|
||||||
// TriggerState triggerState = scheduler.getTriggerState(triggerKey);
|
|
||||||
// Map<String, Object> jobMap = new HashMap<String, Object>();
|
|
||||||
// jobMap.put("TriggerKey", triggerKey);
|
|
||||||
// jobMap.put("Trigger", trigger);
|
|
||||||
// jobMap.put("JobDetail", jobDetail);
|
|
||||||
// jobMap.put("TriggerState", triggerState);
|
|
||||||
// jobList.add(jobMap);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// } catch (SchedulerException e) {
|
|
||||||
// logger.error(e.getMessage(), e);
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
// return jobList;
|
|
||||||
// }*/
|
|
||||||
//
|
|
||||||
//}
|
|
@ -1,58 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.old;//package com.xxl.job.admin.core.quartz;
|
|
||||||
//
|
|
||||||
//import org.quartz.SchedulerConfigException;
|
|
||||||
//import org.quartz.spi.ThreadPool;
|
|
||||||
//
|
|
||||||
///**
|
|
||||||
// * single thread pool, for async trigger
|
|
||||||
// *
|
|
||||||
// * @author xuxueli 2019-03-06
|
|
||||||
// */
|
|
||||||
//public class XxlJobThreadPool implements ThreadPool {
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public boolean runInThread(Runnable runnable) {
|
|
||||||
//
|
|
||||||
// // async run
|
|
||||||
// runnable.run();
|
|
||||||
// return true;
|
|
||||||
//
|
|
||||||
// //return false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public int blockForAvailableThreads() {
|
|
||||||
// return 1;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void initialize() throws SchedulerConfigException {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void shutdown(boolean waitForJobsToComplete) {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public int getPoolSize() {
|
|
||||||
// return 1;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void setInstanceId(String schedInstId) {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void setInstanceName(String schedName) {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // support
|
|
||||||
// public void setThreadCount(int count) {
|
|
||||||
// //
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//}
|
|
@ -1,49 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.route;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.route.strategy.*;
|
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by xuxueli on 17/3/10.
|
|
||||||
*/
|
|
||||||
public enum ExecutorRouteStrategyEnum {
|
|
||||||
|
|
||||||
FIRST(I18nUtil.getString("jobconf_route_first"), new ExecutorRouteFirst()),
|
|
||||||
LAST(I18nUtil.getString("jobconf_route_last"), new ExecutorRouteLast()),
|
|
||||||
ROUND(I18nUtil.getString("jobconf_route_round"), new ExecutorRouteRound()),
|
|
||||||
RANDOM(I18nUtil.getString("jobconf_route_random"), new ExecutorRouteRandom()),
|
|
||||||
CONSISTENT_HASH(I18nUtil.getString("jobconf_route_consistenthash"), new ExecutorRouteConsistentHash()),
|
|
||||||
LEAST_FREQUENTLY_USED(I18nUtil.getString("jobconf_route_lfu"), new ExecutorRouteLFU()),
|
|
||||||
LEAST_RECENTLY_USED(I18nUtil.getString("jobconf_route_lru"), new ExecutorRouteLRU()),
|
|
||||||
FAILOVER(I18nUtil.getString("jobconf_route_failover"), new ExecutorRouteFailover()),
|
|
||||||
BUSYOVER(I18nUtil.getString("jobconf_route_busyover"), new ExecutorRouteBusyover()),
|
|
||||||
SHARDING_BROADCAST(I18nUtil.getString("jobconf_route_shard"), null);
|
|
||||||
|
|
||||||
ExecutorRouteStrategyEnum(String title, ExecutorRouter router) {
|
|
||||||
this.title = title;
|
|
||||||
this.router = router;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String title;
|
|
||||||
private ExecutorRouter router;
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExecutorRouter getRouter() {
|
|
||||||
return router;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ExecutorRouteStrategyEnum match(String name, ExecutorRouteStrategyEnum defaultItem) {
|
|
||||||
if (name != null) {
|
|
||||||
for (ExecutorRouteStrategyEnum item : ExecutorRouteStrategyEnum.values()) {
|
|
||||||
if (item.name().equals(name)) {
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return defaultItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.route;
|
|
||||||
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import com.xxl.job.core.biz.model.TriggerParam;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by xuxueli on 17/3/10.
|
|
||||||
*/
|
|
||||||
public abstract class ExecutorRouter {
|
|
||||||
protected static Logger logger = LoggerFactory.getLogger(ExecutorRouter.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* route address
|
|
||||||
*
|
|
||||||
* @param addressList
|
|
||||||
* @return ReturnT.content=address
|
|
||||||
*/
|
|
||||||
public abstract ReturnT<String> route(TriggerParam triggerParam, List<String> addressList);
|
|
||||||
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.route.strategy;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.scheduler.XxlJobScheduler;
|
|
||||||
import com.xxl.job.admin.core.route.ExecutorRouter;
|
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
|
||||||
import com.xxl.job.core.biz.ExecutorBiz;
|
|
||||||
import com.xxl.job.core.biz.model.IdleBeatParam;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import com.xxl.job.core.biz.model.TriggerParam;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by xuxueli on 17/3/10.
|
|
||||||
*/
|
|
||||||
public class ExecutorRouteBusyover extends ExecutorRouter {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReturnT<String> route(TriggerParam triggerParam, List<String> addressList) {
|
|
||||||
StringBuffer idleBeatResultSB = new StringBuffer();
|
|
||||||
for (String address : addressList) {
|
|
||||||
// beat
|
|
||||||
ReturnT<String> idleBeatResult = null;
|
|
||||||
try {
|
|
||||||
ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(address);
|
|
||||||
idleBeatResult = executorBiz.idleBeat(new IdleBeatParam(triggerParam.getJobId()));
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
idleBeatResult = new ReturnT<String>(ReturnT.FAIL_CODE, "" + e);
|
|
||||||
}
|
|
||||||
idleBeatResultSB.append((idleBeatResultSB.length() > 0) ? "<br><br>" : "")
|
|
||||||
.append(I18nUtil.getString("jobconf_idleBeat") + ":")
|
|
||||||
.append("<br>address:").append(address)
|
|
||||||
.append("<br>code:").append(idleBeatResult.getCode())
|
|
||||||
.append("<br>msg:").append(idleBeatResult.getMsg());
|
|
||||||
|
|
||||||
// beat success
|
|
||||||
if (idleBeatResult.getCode() == ReturnT.SUCCESS_CODE) {
|
|
||||||
idleBeatResult.setMsg(idleBeatResultSB.toString());
|
|
||||||
idleBeatResult.setContent(address);
|
|
||||||
return idleBeatResult;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, idleBeatResultSB.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,86 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.route.strategy;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.route.ExecutorRouter;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import com.xxl.job.core.biz.model.TriggerParam;
|
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.security.MessageDigest;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.SortedMap;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 分组下机器地址相同,不同JOB均匀散列在不同机器上,保证分组下机器分配JOB平均;且每个JOB固定调度其中一台机器;
|
|
||||||
* a、virtual node:解决不均衡问题
|
|
||||||
* b、hash method replace hashCode:String的hashCode可能重复,需要进一步扩大hashCode的取值范围
|
|
||||||
* Created by xuxueli on 17/3/10.
|
|
||||||
*/
|
|
||||||
public class ExecutorRouteConsistentHash extends ExecutorRouter {
|
|
||||||
|
|
||||||
private static int VIRTUAL_NODE_NUM = 100;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get hash code on 2^32 ring (md5散列的方式计算hash值)
|
|
||||||
*
|
|
||||||
* @param key
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private static long hash(String key) {
|
|
||||||
|
|
||||||
// md5 byte
|
|
||||||
MessageDigest md5;
|
|
||||||
try {
|
|
||||||
md5 = MessageDigest.getInstance("MD5");
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
throw new RuntimeException("MD5 not supported", e);
|
|
||||||
}
|
|
||||||
md5.reset();
|
|
||||||
byte[] keyBytes = null;
|
|
||||||
try {
|
|
||||||
keyBytes = key.getBytes("UTF-8");
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
throw new RuntimeException("Unknown string :" + key, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
md5.update(keyBytes);
|
|
||||||
byte[] digest = md5.digest();
|
|
||||||
|
|
||||||
// hash code, Truncate to 32-bits
|
|
||||||
long hashCode = ((long) (digest[3] & 0xFF) << 24)
|
|
||||||
| ((long) (digest[2] & 0xFF) << 16)
|
|
||||||
| ((long) (digest[1] & 0xFF) << 8)
|
|
||||||
| (digest[0] & 0xFF);
|
|
||||||
|
|
||||||
long truncateHashCode = hashCode & 0xffffffffL;
|
|
||||||
return truncateHashCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String hashJob(int jobId, List<String> addressList) {
|
|
||||||
|
|
||||||
// ------A1------A2-------A3------
|
|
||||||
// -----------J1------------------
|
|
||||||
TreeMap<Long, String> addressRing = new TreeMap<Long, String>();
|
|
||||||
for (String address : addressList) {
|
|
||||||
for (int i = 0; i < VIRTUAL_NODE_NUM; i++) {
|
|
||||||
long addressHash = hash("SHARD-" + address + "-NODE-" + i);
|
|
||||||
addressRing.put(addressHash, address);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
long jobHash = hash(String.valueOf(jobId));
|
|
||||||
SortedMap<Long, String> lastRing = addressRing.tailMap(jobHash);
|
|
||||||
if (!lastRing.isEmpty()) {
|
|
||||||
return lastRing.get(lastRing.firstKey());
|
|
||||||
}
|
|
||||||
return addressRing.firstEntry().getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReturnT<String> route(TriggerParam triggerParam, List<String> addressList) {
|
|
||||||
String address = hashJob(triggerParam.getJobId(), addressList);
|
|
||||||
return new ReturnT<String>(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.route.strategy;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.scheduler.XxlJobScheduler;
|
|
||||||
import com.xxl.job.admin.core.route.ExecutorRouter;
|
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
|
||||||
import com.xxl.job.core.biz.ExecutorBiz;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import com.xxl.job.core.biz.model.TriggerParam;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by xuxueli on 17/3/10.
|
|
||||||
*/
|
|
||||||
public class ExecutorRouteFailover extends ExecutorRouter {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReturnT<String> route(TriggerParam triggerParam, List<String> addressList) {
|
|
||||||
|
|
||||||
StringBuffer beatResultSB = new StringBuffer();
|
|
||||||
for (String address : addressList) {
|
|
||||||
// beat
|
|
||||||
ReturnT<String> beatResult = null;
|
|
||||||
try {
|
|
||||||
ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(address);
|
|
||||||
beatResult = executorBiz.beat();
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
beatResult = new ReturnT<String>(ReturnT.FAIL_CODE, "" + e);
|
|
||||||
}
|
|
||||||
beatResultSB.append((beatResultSB.length() > 0) ? "<br><br>" : "")
|
|
||||||
.append(I18nUtil.getString("jobconf_beat") + ":")
|
|
||||||
.append("<br>address:").append(address)
|
|
||||||
.append("<br>code:").append(beatResult.getCode())
|
|
||||||
.append("<br>msg:").append(beatResult.getMsg());
|
|
||||||
|
|
||||||
// beat success
|
|
||||||
if (beatResult.getCode() == ReturnT.SUCCESS_CODE) {
|
|
||||||
|
|
||||||
beatResult.setMsg(beatResultSB.toString());
|
|
||||||
beatResult.setContent(address);
|
|
||||||
return beatResult;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, beatResultSB.toString());
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.route.strategy;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.route.ExecutorRouter;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import com.xxl.job.core.biz.model.TriggerParam;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by xuxueli on 17/3/10.
|
|
||||||
*/
|
|
||||||
public class ExecutorRouteFirst extends ExecutorRouter {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReturnT<String> route(TriggerParam triggerParam, List<String> addressList) {
|
|
||||||
return new ReturnT<String>(addressList.get(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,79 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.route.strategy;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.route.ExecutorRouter;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import com.xxl.job.core.biz.model.TriggerParam;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 单个JOB对应的每个执行器,使用频率最低的优先被选举
|
|
||||||
* a(*)、LFU(Least Frequently Used):最不经常使用,频率/次数
|
|
||||||
* b、LRU(Least Recently Used):最近最久未使用,时间
|
|
||||||
* <p>
|
|
||||||
* Created by xuxueli on 17/3/10.
|
|
||||||
*/
|
|
||||||
public class ExecutorRouteLFU extends ExecutorRouter {
|
|
||||||
|
|
||||||
private static ConcurrentMap<Integer, HashMap<String, Integer>> jobLfuMap = new ConcurrentHashMap<Integer, HashMap<String, Integer>>();
|
|
||||||
private static long CACHE_VALID_TIME = 0;
|
|
||||||
|
|
||||||
public String route(int jobId, List<String> addressList) {
|
|
||||||
|
|
||||||
// cache clear
|
|
||||||
if (System.currentTimeMillis() > CACHE_VALID_TIME) {
|
|
||||||
jobLfuMap.clear();
|
|
||||||
CACHE_VALID_TIME = System.currentTimeMillis() + 1000 * 60 * 60 * 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
// lfu item init
|
|
||||||
HashMap<String, Integer> lfuItemMap = jobLfuMap.get(jobId); // Key排序可以用TreeMap+构造入参Compare;Value排序暂时只能通过ArrayList;
|
|
||||||
if (lfuItemMap == null) {
|
|
||||||
lfuItemMap = new HashMap<String, Integer>();
|
|
||||||
jobLfuMap.putIfAbsent(jobId, lfuItemMap); // 避免重复覆盖
|
|
||||||
}
|
|
||||||
|
|
||||||
// put new
|
|
||||||
for (String address : addressList) {
|
|
||||||
if (!lfuItemMap.containsKey(address) || lfuItemMap.get(address) > 1000000) {
|
|
||||||
lfuItemMap.put(address, new Random().nextInt(addressList.size())); // 初始化时主动Random一次,缓解首次压力
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// remove old
|
|
||||||
List<String> delKeys = new ArrayList<>();
|
|
||||||
for (String existKey : lfuItemMap.keySet()) {
|
|
||||||
if (!addressList.contains(existKey)) {
|
|
||||||
delKeys.add(existKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (delKeys.size() > 0) {
|
|
||||||
for (String delKey : delKeys) {
|
|
||||||
lfuItemMap.remove(delKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// load least userd count address
|
|
||||||
List<Map.Entry<String, Integer>> lfuItemList = new ArrayList<Map.Entry<String, Integer>>(lfuItemMap.entrySet());
|
|
||||||
Collections.sort(lfuItemList, new Comparator<Map.Entry<String, Integer>>() {
|
|
||||||
@Override
|
|
||||||
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
|
|
||||||
return o1.getValue().compareTo(o2.getValue());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Map.Entry<String, Integer> addressItem = lfuItemList.get(0);
|
|
||||||
String minAddress = addressItem.getKey();
|
|
||||||
addressItem.setValue(addressItem.getValue() + 1);
|
|
||||||
|
|
||||||
return addressItem.getKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReturnT<String> route(TriggerParam triggerParam, List<String> addressList) {
|
|
||||||
String address = route(triggerParam.getJobId(), addressList);
|
|
||||||
return new ReturnT<String>(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.route.strategy;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.route.ExecutorRouter;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import com.xxl.job.core.biz.model.TriggerParam;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 单个JOB对应的每个执行器,最久为使用的优先被选举
|
|
||||||
* a、LFU(Least Frequently Used):最不经常使用,频率/次数
|
|
||||||
* b(*)、LRU(Least Recently Used):最近最久未使用,时间
|
|
||||||
* <p>
|
|
||||||
* Created by xuxueli on 17/3/10.
|
|
||||||
*/
|
|
||||||
public class ExecutorRouteLRU extends ExecutorRouter {
|
|
||||||
|
|
||||||
private static ConcurrentMap<Integer, LinkedHashMap<String, String>> jobLRUMap = new ConcurrentHashMap<Integer, LinkedHashMap<String, String>>();
|
|
||||||
private static long CACHE_VALID_TIME = 0;
|
|
||||||
|
|
||||||
public String route(int jobId, List<String> addressList) {
|
|
||||||
|
|
||||||
// cache clear
|
|
||||||
if (System.currentTimeMillis() > CACHE_VALID_TIME) {
|
|
||||||
jobLRUMap.clear();
|
|
||||||
CACHE_VALID_TIME = System.currentTimeMillis() + 1000 * 60 * 60 * 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
// init lru
|
|
||||||
LinkedHashMap<String, String> lruItem = jobLRUMap.get(jobId);
|
|
||||||
if (lruItem == null) {
|
|
||||||
/**
|
|
||||||
* LinkedHashMap
|
|
||||||
* a、accessOrder:true=访问顺序排序(get/put时排序);false=插入顺序排期;
|
|
||||||
* b、removeEldestEntry:新增元素时将会调用,返回true时会删除最老元素;可封装LinkedHashMap并重写该方法,比如定义最大容量,超出是返回true即可实现固定长度的LRU算法;
|
|
||||||
*/
|
|
||||||
lruItem = new LinkedHashMap<String, String>(16, 0.75f, true);
|
|
||||||
jobLRUMap.putIfAbsent(jobId, lruItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
// put new
|
|
||||||
for (String address : addressList) {
|
|
||||||
if (!lruItem.containsKey(address)) {
|
|
||||||
lruItem.put(address, address);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// remove old
|
|
||||||
List<String> delKeys = new ArrayList<>();
|
|
||||||
for (String existKey : lruItem.keySet()) {
|
|
||||||
if (!addressList.contains(existKey)) {
|
|
||||||
delKeys.add(existKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (delKeys.size() > 0) {
|
|
||||||
for (String delKey : delKeys) {
|
|
||||||
lruItem.remove(delKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// load
|
|
||||||
String eldestKey = lruItem.entrySet().iterator().next().getKey();
|
|
||||||
String eldestValue = lruItem.get(eldestKey);
|
|
||||||
return eldestValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReturnT<String> route(TriggerParam triggerParam, List<String> addressList) {
|
|
||||||
String address = route(triggerParam.getJobId(), addressList);
|
|
||||||
return new ReturnT<String>(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.route.strategy;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.route.ExecutorRouter;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import com.xxl.job.core.biz.model.TriggerParam;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by xuxueli on 17/3/10.
|
|
||||||
*/
|
|
||||||
public class ExecutorRouteLast extends ExecutorRouter {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReturnT<String> route(TriggerParam triggerParam, List<String> addressList) {
|
|
||||||
return new ReturnT<String>(addressList.get(addressList.size() - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.route.strategy;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.route.ExecutorRouter;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import com.xxl.job.core.biz.model.TriggerParam;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by xuxueli on 17/3/10.
|
|
||||||
*/
|
|
||||||
public class ExecutorRouteRandom extends ExecutorRouter {
|
|
||||||
|
|
||||||
private static Random localRandom = new Random();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReturnT<String> route(TriggerParam triggerParam, List<String> addressList) {
|
|
||||||
String address = addressList.get(localRandom.nextInt(addressList.size()));
|
|
||||||
return new ReturnT<String>(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,46 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.route.strategy;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.route.ExecutorRouter;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import com.xxl.job.core.biz.model.TriggerParam;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by xuxueli on 17/3/10.
|
|
||||||
*/
|
|
||||||
public class ExecutorRouteRound extends ExecutorRouter {
|
|
||||||
|
|
||||||
private static ConcurrentMap<Integer, AtomicInteger> routeCountEachJob = new ConcurrentHashMap<>();
|
|
||||||
private static long CACHE_VALID_TIME = 0;
|
|
||||||
|
|
||||||
private static int count(int jobId) {
|
|
||||||
// cache clear
|
|
||||||
if (System.currentTimeMillis() > CACHE_VALID_TIME) {
|
|
||||||
routeCountEachJob.clear();
|
|
||||||
CACHE_VALID_TIME = System.currentTimeMillis() + 1000 * 60 * 60 * 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
AtomicInteger count = routeCountEachJob.get(jobId);
|
|
||||||
if (count == null || count.get() > 1000000) {
|
|
||||||
// 初始化时主动Random一次,缓解首次压力
|
|
||||||
count = new AtomicInteger(new Random().nextInt(100));
|
|
||||||
} else {
|
|
||||||
// count++
|
|
||||||
count.addAndGet(1);
|
|
||||||
}
|
|
||||||
routeCountEachJob.put(jobId, count);
|
|
||||||
return count.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReturnT<String> route(TriggerParam triggerParam, List<String> addressList) {
|
|
||||||
String address = addressList.get(count(triggerParam.getJobId()) % addressList.size());
|
|
||||||
return new ReturnT<String>(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.scheduler;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author xuxueli 2020-10-29 21:11:23
|
|
||||||
*/
|
|
||||||
public enum MisfireStrategyEnum {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* do nothing
|
|
||||||
*/
|
|
||||||
DO_NOTHING(I18nUtil.getString("misfire_strategy_do_nothing")),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* fire once now
|
|
||||||
*/
|
|
||||||
FIRE_ONCE_NOW(I18nUtil.getString("misfire_strategy_fire_once_now"));
|
|
||||||
|
|
||||||
private String title;
|
|
||||||
|
|
||||||
MisfireStrategyEnum(String title) {
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MisfireStrategyEnum match(String name, MisfireStrategyEnum defaultItem) {
|
|
||||||
for (MisfireStrategyEnum item : MisfireStrategyEnum.values()) {
|
|
||||||
if (item.name().equals(name)) {
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return defaultItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,46 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.scheduler;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author xuxueli 2020-10-29 21:11:23
|
|
||||||
*/
|
|
||||||
public enum ScheduleTypeEnum {
|
|
||||||
|
|
||||||
NONE(I18nUtil.getString("schedule_type_none")),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* schedule by cron
|
|
||||||
*/
|
|
||||||
CRON(I18nUtil.getString("schedule_type_cron")),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* schedule by fixed rate (in seconds)
|
|
||||||
*/
|
|
||||||
FIX_RATE(I18nUtil.getString("schedule_type_fix_rate")),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* schedule by fix delay (in seconds), after the last time
|
|
||||||
*/
|
|
||||||
/*FIX_DELAY(I18nUtil.getString("schedule_type_fix_delay"))*/;
|
|
||||||
|
|
||||||
private String title;
|
|
||||||
|
|
||||||
ScheduleTypeEnum(String title) {
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ScheduleTypeEnum match(String name, ScheduleTypeEnum defaultItem) {
|
|
||||||
for (ScheduleTypeEnum item : ScheduleTypeEnum.values()) {
|
|
||||||
if (item.name().equals(name)) {
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return defaultItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,102 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.scheduler;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
|
||||||
import com.xxl.job.admin.core.thread.*;
|
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
|
||||||
import com.xxl.job.core.biz.ExecutorBiz;
|
|
||||||
import com.xxl.job.core.biz.client.ExecutorBizClient;
|
|
||||||
import com.xxl.job.core.enums.ExecutorBlockStrategyEnum;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author xuxueli 2018-10-28 00:18:17
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class XxlJobScheduler {
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(XxlJobScheduler.class);
|
|
||||||
|
|
||||||
|
|
||||||
public void init() throws Exception {
|
|
||||||
// init i18n
|
|
||||||
initI18n();
|
|
||||||
|
|
||||||
// admin trigger pool start
|
|
||||||
JobTriggerPoolHelper.toStart();
|
|
||||||
|
|
||||||
// admin registry monitor run
|
|
||||||
JobRegistryHelper.getInstance().start();
|
|
||||||
|
|
||||||
// admin fail-monitor run
|
|
||||||
JobFailMonitorHelper.getInstance().start();
|
|
||||||
|
|
||||||
// admin lose-monitor run ( depend on JobTriggerPoolHelper )
|
|
||||||
JobCompleteHelper.getInstance().start();
|
|
||||||
|
|
||||||
// admin log report start
|
|
||||||
JobLogReportHelper.getInstance().start();
|
|
||||||
|
|
||||||
// start-schedule ( depend on JobTriggerPoolHelper )
|
|
||||||
JobScheduleHelper.getInstance().start();
|
|
||||||
|
|
||||||
logger.info(">>>>>>>>> init xxl-job admin success.");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void destroy() throws Exception {
|
|
||||||
|
|
||||||
// stop-schedule
|
|
||||||
JobScheduleHelper.getInstance().toStop();
|
|
||||||
|
|
||||||
// admin log report stop
|
|
||||||
JobLogReportHelper.getInstance().toStop();
|
|
||||||
|
|
||||||
// admin lose-monitor stop
|
|
||||||
JobCompleteHelper.getInstance().toStop();
|
|
||||||
|
|
||||||
// admin fail-monitor stop
|
|
||||||
JobFailMonitorHelper.getInstance().toStop();
|
|
||||||
|
|
||||||
// admin registry stop
|
|
||||||
JobRegistryHelper.getInstance().toStop();
|
|
||||||
|
|
||||||
// admin trigger pool stop
|
|
||||||
JobTriggerPoolHelper.toStop();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------- I18n ----------------------
|
|
||||||
|
|
||||||
private void initI18n() {
|
|
||||||
for (ExecutorBlockStrategyEnum item : ExecutorBlockStrategyEnum.values()) {
|
|
||||||
item.setTitle(I18nUtil.getString("jobconf_block_".concat(item.name())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------- executor-client ----------------------
|
|
||||||
private static ConcurrentMap<String, ExecutorBiz> executorBizRepository = new ConcurrentHashMap<String, ExecutorBiz>();
|
|
||||||
|
|
||||||
public static ExecutorBiz getExecutorBiz(String address) throws Exception {
|
|
||||||
// valid
|
|
||||||
if (address == null || address.trim().length() == 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// load-cache
|
|
||||||
address = address.trim();
|
|
||||||
ExecutorBiz executorBiz = executorBizRepository.get(address);
|
|
||||||
if (executorBiz != null) {
|
|
||||||
return executorBiz;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set-cache
|
|
||||||
executorBiz = new ExecutorBizClient(address, XxlJobAdminConfig.getAdminConfig().getAccessToken());
|
|
||||||
|
|
||||||
executorBizRepository.put(address, executorBiz);
|
|
||||||
return executorBiz;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,185 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.thread;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.complete.XxlJobCompleter;
|
|
||||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobLog;
|
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
|
||||||
import com.xxl.job.core.biz.model.HandleCallbackParam;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import com.xxl.job.core.util.DateUtil;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* job lose-monitor instance
|
|
||||||
*
|
|
||||||
* @author xuxueli 2015-9-1 18:05:56
|
|
||||||
*/
|
|
||||||
public class JobCompleteHelper {
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(JobCompleteHelper.class);
|
|
||||||
|
|
||||||
private static JobCompleteHelper instance = new JobCompleteHelper();
|
|
||||||
|
|
||||||
public static JobCompleteHelper getInstance() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------- monitor ----------------------
|
|
||||||
|
|
||||||
private ThreadPoolExecutor callbackThreadPool = null;
|
|
||||||
private Thread monitorThread;
|
|
||||||
private volatile boolean toStop = false;
|
|
||||||
|
|
||||||
public void start() {
|
|
||||||
|
|
||||||
// for callback
|
|
||||||
callbackThreadPool = new ThreadPoolExecutor(
|
|
||||||
2,
|
|
||||||
20,
|
|
||||||
30L,
|
|
||||||
TimeUnit.SECONDS,
|
|
||||||
new LinkedBlockingQueue<Runnable>(3000),
|
|
||||||
new ThreadFactory() {
|
|
||||||
@Override
|
|
||||||
public Thread newThread(Runnable r) {
|
|
||||||
return new Thread(r, "xxl-job, admin JobLosedMonitorHelper-callbackThreadPool-" + r.hashCode());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new RejectedExecutionHandler() {
|
|
||||||
@Override
|
|
||||||
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
|
|
||||||
r.run();
|
|
||||||
logger.warn(">>>>>>>>>>> xxl-job, callback too fast, match threadpool rejected handler(run now).");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// for monitor
|
|
||||||
monitorThread = new Thread(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
|
|
||||||
// wait for JobTriggerPoolHelper-init
|
|
||||||
try {
|
|
||||||
TimeUnit.MILLISECONDS.sleep(50);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
if (!toStop) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// monitor
|
|
||||||
while (!toStop) {
|
|
||||||
try {
|
|
||||||
// 任务结果丢失处理:调度记录停留在 "运行中" 状态超过10min,且对应执行器心跳注册失败不在线,则将本地调度主动标记失败;
|
|
||||||
Date losedTime = DateUtil.addMinutes(new Date(), -10);
|
|
||||||
List<Long> losedJobIds = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().findLostJobIds(losedTime);
|
|
||||||
|
|
||||||
if (losedJobIds != null && losedJobIds.size() > 0) {
|
|
||||||
for (Long logId : losedJobIds) {
|
|
||||||
|
|
||||||
XxlJobLog jobLog = new XxlJobLog();
|
|
||||||
jobLog.setId(logId);
|
|
||||||
|
|
||||||
jobLog.setHandleTime(new Date());
|
|
||||||
jobLog.setHandleCode(ReturnT.FAIL_CODE);
|
|
||||||
jobLog.setHandleMsg(I18nUtil.getString("joblog_lost_fail"));
|
|
||||||
|
|
||||||
XxlJobCompleter.updateHandleInfoAndFinish(jobLog);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
if (!toStop) {
|
|
||||||
logger.error(">>>>>>>>>>> xxl-job, job fail monitor thread error:{}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
TimeUnit.SECONDS.sleep(60);
|
|
||||||
} catch (Exception e) {
|
|
||||||
if (!toStop) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info(">>>>>>>>>>> xxl-job, JobLosedMonitorHelper stop");
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
monitorThread.setDaemon(true);
|
|
||||||
monitorThread.setName("xxl-job, admin JobLosedMonitorHelper");
|
|
||||||
monitorThread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void toStop() {
|
|
||||||
toStop = true;
|
|
||||||
|
|
||||||
// stop registryOrRemoveThreadPool
|
|
||||||
callbackThreadPool.shutdownNow();
|
|
||||||
|
|
||||||
// stop monitorThread (interrupt and wait)
|
|
||||||
monitorThread.interrupt();
|
|
||||||
try {
|
|
||||||
monitorThread.join();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------- helper ----------------------
|
|
||||||
|
|
||||||
public ReturnT<String> callback(List<HandleCallbackParam> callbackParamList) {
|
|
||||||
|
|
||||||
callbackThreadPool.execute(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
for (HandleCallbackParam handleCallbackParam : callbackParamList) {
|
|
||||||
ReturnT<String> callbackResult = callback(handleCallbackParam);
|
|
||||||
logger.debug(">>>>>>>>> JobApiController.callback {}, handleCallbackParam={}, callbackResult={}",
|
|
||||||
(callbackResult.getCode() == ReturnT.SUCCESS_CODE ? "success" : "fail"), handleCallbackParam, callbackResult);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return ReturnT.SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ReturnT<String> callback(HandleCallbackParam handleCallbackParam) {
|
|
||||||
// valid log item
|
|
||||||
XxlJobLog log = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().load(handleCallbackParam.getLogId());
|
|
||||||
if (log == null) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, "log item not found.");
|
|
||||||
}
|
|
||||||
if (log.getHandleCode() > 0) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, "log repeate callback."); // avoid repeat callback, trigger child job etc
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle msg
|
|
||||||
StringBuffer handleMsg = new StringBuffer();
|
|
||||||
if (log.getHandleMsg() != null) {
|
|
||||||
handleMsg.append(log.getHandleMsg()).append("<br>");
|
|
||||||
}
|
|
||||||
if (handleCallbackParam.getHandleMsg() != null) {
|
|
||||||
handleMsg.append(handleCallbackParam.getHandleMsg());
|
|
||||||
}
|
|
||||||
|
|
||||||
// success, save log
|
|
||||||
log.setHandleTime(new Date());
|
|
||||||
log.setHandleCode(handleCallbackParam.getHandleCode());
|
|
||||||
log.setHandleMsg(handleMsg.toString());
|
|
||||||
XxlJobCompleter.updateHandleInfoAndFinish(log);
|
|
||||||
|
|
||||||
return ReturnT.SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,112 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.thread;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobLog;
|
|
||||||
import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
|
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* job monitor instance
|
|
||||||
*
|
|
||||||
* @author xuxueli 2015-9-1 18:05:56
|
|
||||||
*/
|
|
||||||
public class JobFailMonitorHelper {
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(JobFailMonitorHelper.class);
|
|
||||||
|
|
||||||
private static JobFailMonitorHelper instance = new JobFailMonitorHelper();
|
|
||||||
|
|
||||||
public static JobFailMonitorHelper getInstance() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------- monitor ----------------------
|
|
||||||
|
|
||||||
private Thread monitorThread;
|
|
||||||
private volatile boolean toStop = false;
|
|
||||||
|
|
||||||
public void start() {
|
|
||||||
monitorThread = new Thread(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
|
|
||||||
// monitor
|
|
||||||
while (!toStop) {
|
|
||||||
try {
|
|
||||||
|
|
||||||
List<Long> failLogIds = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().findFailJobLogIds(1000);
|
|
||||||
if (failLogIds != null && !failLogIds.isEmpty()) {
|
|
||||||
for (long failLogId : failLogIds) {
|
|
||||||
|
|
||||||
// lock log
|
|
||||||
int lockRet = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().updateAlarmStatus(failLogId, 0, -1);
|
|
||||||
if (lockRet < 1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
XxlJobLog log = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().load(failLogId);
|
|
||||||
XxlJobInfo info = XxlJobAdminConfig.getAdminConfig().getXxlJobInfoDao().loadById(log.getJobId());
|
|
||||||
|
|
||||||
// 1、fail retry monitor
|
|
||||||
if (log.getExecutorFailRetryCount() > 0) {
|
|
||||||
JobTriggerPoolHelper.trigger(log.getJobId(), TriggerTypeEnum.RETRY, (log.getExecutorFailRetryCount() - 1), log.getExecutorShardingParam(), log.getExecutorParam(), null);
|
|
||||||
String retryMsg = "<br><br><span style=\"color:#F39C12;\" > >>>>>>>>>>>" + I18nUtil.getString("jobconf_trigger_type_retry") + "<<<<<<<<<<< </span><br>";
|
|
||||||
log.setTriggerMsg(log.getTriggerMsg() + retryMsg);
|
|
||||||
XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().updateTriggerInfo(log);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2、fail alarm monitor
|
|
||||||
int newAlarmStatus = 0; // 告警状态:0-默认、-1=锁定状态、1-无需告警、2-告警成功、3-告警失败
|
|
||||||
if (info != null) {
|
|
||||||
boolean alarmResult = XxlJobAdminConfig.getAdminConfig().getJobAlarmer().alarm(info, log);
|
|
||||||
newAlarmStatus = alarmResult ? 2 : 3;
|
|
||||||
} else {
|
|
||||||
newAlarmStatus = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().updateAlarmStatus(failLogId, -1, newAlarmStatus);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
if (!toStop) {
|
|
||||||
logger.error(">>>>>>>>>>> xxl-job, job fail monitor thread error:{}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
TimeUnit.SECONDS.sleep(10);
|
|
||||||
} catch (Exception e) {
|
|
||||||
if (!toStop) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info(">>>>>>>>>>> xxl-job, job fail monitor thread stop");
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
monitorThread.setDaemon(true);
|
|
||||||
monitorThread.setName("xxl-job, admin JobFailMonitorHelper");
|
|
||||||
monitorThread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void toStop() {
|
|
||||||
toStop = true;
|
|
||||||
// interrupt and wait
|
|
||||||
monitorThread.interrupt();
|
|
||||||
try {
|
|
||||||
monitorThread.join();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,154 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.thread;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobLogReport;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* job log report helper
|
|
||||||
*
|
|
||||||
* @author xuxueli 2019-11-22
|
|
||||||
*/
|
|
||||||
public class JobLogReportHelper {
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(JobLogReportHelper.class);
|
|
||||||
|
|
||||||
private static JobLogReportHelper instance = new JobLogReportHelper();
|
|
||||||
|
|
||||||
public static JobLogReportHelper getInstance() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private Thread logrThread;
|
|
||||||
private volatile boolean toStop = false;
|
|
||||||
|
|
||||||
public void start() {
|
|
||||||
logrThread = new Thread(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
|
|
||||||
// last clean log time
|
|
||||||
long lastCleanLogTime = 0;
|
|
||||||
|
|
||||||
|
|
||||||
while (!toStop) {
|
|
||||||
|
|
||||||
// 1、log-report refresh: refresh log report in 3 days
|
|
||||||
try {
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
|
|
||||||
// today
|
|
||||||
Calendar itemDay = Calendar.getInstance();
|
|
||||||
itemDay.add(Calendar.DAY_OF_MONTH, -i);
|
|
||||||
itemDay.set(Calendar.HOUR_OF_DAY, 0);
|
|
||||||
itemDay.set(Calendar.MINUTE, 0);
|
|
||||||
itemDay.set(Calendar.SECOND, 0);
|
|
||||||
itemDay.set(Calendar.MILLISECOND, 0);
|
|
||||||
|
|
||||||
Date todayFrom = itemDay.getTime();
|
|
||||||
|
|
||||||
itemDay.set(Calendar.HOUR_OF_DAY, 23);
|
|
||||||
itemDay.set(Calendar.MINUTE, 59);
|
|
||||||
itemDay.set(Calendar.SECOND, 59);
|
|
||||||
itemDay.set(Calendar.MILLISECOND, 999);
|
|
||||||
|
|
||||||
Date todayTo = itemDay.getTime();
|
|
||||||
|
|
||||||
// refresh log-report every minute
|
|
||||||
XxlJobLogReport xxlJobLogReport = new XxlJobLogReport();
|
|
||||||
xxlJobLogReport.setTriggerDay(todayFrom);
|
|
||||||
xxlJobLogReport.setRunningCount(0);
|
|
||||||
xxlJobLogReport.setSucCount(0);
|
|
||||||
xxlJobLogReport.setFailCount(0);
|
|
||||||
|
|
||||||
Map<String, Object> triggerCountMap = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().findLogReport(todayFrom, todayTo);
|
|
||||||
if (triggerCountMap != null && triggerCountMap.size() > 0) {
|
|
||||||
int triggerDayCount = triggerCountMap.containsKey("triggerDayCount") ? Integer.valueOf(String.valueOf(triggerCountMap.get("triggerDayCount"))) : 0;
|
|
||||||
int triggerDayCountRunning = triggerCountMap.containsKey("triggerDayCountRunning") ? Integer.valueOf(String.valueOf(triggerCountMap.get("triggerDayCountRunning"))) : 0;
|
|
||||||
int triggerDayCountSuc = triggerCountMap.containsKey("triggerDayCountSuc") ? Integer.valueOf(String.valueOf(triggerCountMap.get("triggerDayCountSuc"))) : 0;
|
|
||||||
int triggerDayCountFail = triggerDayCount - triggerDayCountRunning - triggerDayCountSuc;
|
|
||||||
|
|
||||||
xxlJobLogReport.setRunningCount(triggerDayCountRunning);
|
|
||||||
xxlJobLogReport.setSucCount(triggerDayCountSuc);
|
|
||||||
xxlJobLogReport.setFailCount(triggerDayCountFail);
|
|
||||||
}
|
|
||||||
|
|
||||||
// do refresh
|
|
||||||
int ret = XxlJobAdminConfig.getAdminConfig().getXxlJobLogReportDao().update(xxlJobLogReport);
|
|
||||||
if (ret < 1) {
|
|
||||||
XxlJobAdminConfig.getAdminConfig().getXxlJobLogReportDao().save(xxlJobLogReport);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
if (!toStop) {
|
|
||||||
logger.error(">>>>>>>>>>> xxl-job, job log report thread error:{}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2、log-clean: switch open & once each day
|
|
||||||
if (XxlJobAdminConfig.getAdminConfig().getLogretentiondays() > 0
|
|
||||||
&& System.currentTimeMillis() - lastCleanLogTime > 24 * 60 * 60 * 1000) {
|
|
||||||
|
|
||||||
// expire-time
|
|
||||||
Calendar expiredDay = Calendar.getInstance();
|
|
||||||
expiredDay.add(Calendar.DAY_OF_MONTH, -1 * XxlJobAdminConfig.getAdminConfig().getLogretentiondays());
|
|
||||||
expiredDay.set(Calendar.HOUR_OF_DAY, 0);
|
|
||||||
expiredDay.set(Calendar.MINUTE, 0);
|
|
||||||
expiredDay.set(Calendar.SECOND, 0);
|
|
||||||
expiredDay.set(Calendar.MILLISECOND, 0);
|
|
||||||
Date clearBeforeTime = expiredDay.getTime();
|
|
||||||
|
|
||||||
// clean expired log
|
|
||||||
List<Long> logIds = null;
|
|
||||||
do {
|
|
||||||
logIds = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().findClearLogIds(0, 0, clearBeforeTime, 0, 1000);
|
|
||||||
if (logIds != null && logIds.size() > 0) {
|
|
||||||
XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().clearLog(logIds);
|
|
||||||
}
|
|
||||||
} while (logIds != null && logIds.size() > 0);
|
|
||||||
|
|
||||||
// update clean time
|
|
||||||
lastCleanLogTime = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
TimeUnit.MINUTES.sleep(1);
|
|
||||||
} catch (Exception e) {
|
|
||||||
if (!toStop) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info(">>>>>>>>>>> xxl-job, job log report thread stop");
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
logrThread.setDaemon(true);
|
|
||||||
logrThread.setName("xxl-job, admin JobLogReportHelper");
|
|
||||||
logrThread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void toStop() {
|
|
||||||
toStop = true;
|
|
||||||
// interrupt and wait
|
|
||||||
logrThread.interrupt();
|
|
||||||
try {
|
|
||||||
logrThread.join();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,206 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.thread;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobGroup;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobRegistry;
|
|
||||||
import com.xxl.job.core.biz.model.RegistryParam;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import com.xxl.job.core.enums.RegistryConfig;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* job registry instance
|
|
||||||
*
|
|
||||||
* @author xuxueli 2016-10-02 19:10:24
|
|
||||||
*/
|
|
||||||
public class JobRegistryHelper {
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(JobRegistryHelper.class);
|
|
||||||
|
|
||||||
private static JobRegistryHelper instance = new JobRegistryHelper();
|
|
||||||
|
|
||||||
public static JobRegistryHelper getInstance() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ThreadPoolExecutor registryOrRemoveThreadPool = null;
|
|
||||||
private Thread registryMonitorThread;
|
|
||||||
private volatile boolean toStop = false;
|
|
||||||
|
|
||||||
public void start() {
|
|
||||||
|
|
||||||
// for registry or remove
|
|
||||||
registryOrRemoveThreadPool = new ThreadPoolExecutor(
|
|
||||||
2,
|
|
||||||
10,
|
|
||||||
30L,
|
|
||||||
TimeUnit.SECONDS,
|
|
||||||
new LinkedBlockingQueue<Runnable>(2000),
|
|
||||||
new ThreadFactory() {
|
|
||||||
@Override
|
|
||||||
public Thread newThread(Runnable r) {
|
|
||||||
return new Thread(r, "xxl-job, admin JobRegistryMonitorHelper-registryOrRemoveThreadPool-" + r.hashCode());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new RejectedExecutionHandler() {
|
|
||||||
@Override
|
|
||||||
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
|
|
||||||
r.run();
|
|
||||||
logger.warn(">>>>>>>>>>> xxl-job, registry or remove too fast, match threadpool rejected handler(run now).");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// for monitor
|
|
||||||
registryMonitorThread = new Thread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
while (!toStop) {
|
|
||||||
try {
|
|
||||||
// auto registry group
|
|
||||||
List<XxlJobGroup> groupList = XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().findByAddressType(0);
|
|
||||||
if (groupList != null && !groupList.isEmpty()) {
|
|
||||||
|
|
||||||
// remove dead address (admin/executor)
|
|
||||||
List<Integer> ids = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().findDead(RegistryConfig.DEAD_TIMEOUT, new Date());
|
|
||||||
if (ids != null && ids.size() > 0) {
|
|
||||||
XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().removeDead(ids);
|
|
||||||
}
|
|
||||||
|
|
||||||
// fresh online address (admin/executor)
|
|
||||||
HashMap<String, List<String>> appAddressMap = new HashMap<String, List<String>>();
|
|
||||||
List<XxlJobRegistry> list = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().findAll(RegistryConfig.DEAD_TIMEOUT, new Date());
|
|
||||||
if (list != null) {
|
|
||||||
for (XxlJobRegistry item : list) {
|
|
||||||
if (RegistryConfig.RegistType.EXECUTOR.name().equals(item.getRegistryGroup())) {
|
|
||||||
String appname = item.getRegistryKey();
|
|
||||||
List<String> registryList = appAddressMap.get(appname);
|
|
||||||
if (registryList == null) {
|
|
||||||
registryList = new ArrayList<String>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!registryList.contains(item.getRegistryValue())) {
|
|
||||||
registryList.add(item.getRegistryValue());
|
|
||||||
}
|
|
||||||
appAddressMap.put(appname, registryList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fresh group address
|
|
||||||
for (XxlJobGroup group : groupList) {
|
|
||||||
List<String> registryList = appAddressMap.get(group.getAppname());
|
|
||||||
String addressListStr = null;
|
|
||||||
if (registryList != null && !registryList.isEmpty()) {
|
|
||||||
Collections.sort(registryList);
|
|
||||||
StringBuilder addressListSB = new StringBuilder();
|
|
||||||
for (String item : registryList) {
|
|
||||||
addressListSB.append(item).append(",");
|
|
||||||
}
|
|
||||||
addressListStr = addressListSB.toString();
|
|
||||||
addressListStr = addressListStr.substring(0, addressListStr.length() - 1);
|
|
||||||
}
|
|
||||||
group.setAddressList(addressListStr);
|
|
||||||
group.setUpdateTime(new Date());
|
|
||||||
|
|
||||||
XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().update(group);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
if (!toStop) {
|
|
||||||
logger.error(">>>>>>>>>>> xxl-job, job registry monitor thread error:{}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
TimeUnit.SECONDS.sleep(RegistryConfig.BEAT_TIMEOUT);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
if (!toStop) {
|
|
||||||
logger.error(">>>>>>>>>>> xxl-job, job registry monitor thread error:{}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logger.info(">>>>>>>>>>> xxl-job, job registry monitor thread stop");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
registryMonitorThread.setDaemon(true);
|
|
||||||
registryMonitorThread.setName("xxl-job, admin JobRegistryMonitorHelper-registryMonitorThread");
|
|
||||||
registryMonitorThread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void toStop() {
|
|
||||||
toStop = true;
|
|
||||||
|
|
||||||
// stop registryOrRemoveThreadPool
|
|
||||||
registryOrRemoveThreadPool.shutdownNow();
|
|
||||||
|
|
||||||
// stop monitir (interrupt and wait)
|
|
||||||
registryMonitorThread.interrupt();
|
|
||||||
try {
|
|
||||||
registryMonitorThread.join();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------- helper ----------------------
|
|
||||||
|
|
||||||
public ReturnT<String> registry(RegistryParam registryParam) {
|
|
||||||
|
|
||||||
// valid
|
|
||||||
if (!StringUtils.hasText(registryParam.getRegistryGroup())
|
|
||||||
|| !StringUtils.hasText(registryParam.getRegistryKey())
|
|
||||||
|| !StringUtils.hasText(registryParam.getRegistryValue())) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, "Illegal Argument.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// async execute
|
|
||||||
registryOrRemoveThreadPool.execute(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
int ret = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().registryUpdate(registryParam.getRegistryGroup(), registryParam.getRegistryKey(), registryParam.getRegistryValue(), new Date());
|
|
||||||
if (ret < 1) {
|
|
||||||
XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().registrySave(registryParam.getRegistryGroup(), registryParam.getRegistryKey(), registryParam.getRegistryValue(), new Date());
|
|
||||||
|
|
||||||
// fresh
|
|
||||||
freshGroupRegistryInfo(registryParam);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return ReturnT.SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReturnT<String> registryRemove(RegistryParam registryParam) {
|
|
||||||
|
|
||||||
// valid
|
|
||||||
if (!StringUtils.hasText(registryParam.getRegistryGroup())
|
|
||||||
|| !StringUtils.hasText(registryParam.getRegistryKey())
|
|
||||||
|| !StringUtils.hasText(registryParam.getRegistryValue())) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, "Illegal Argument.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// async execute
|
|
||||||
registryOrRemoveThreadPool.execute(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
int ret = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().registryDelete(registryParam.getRegistryGroup(), registryParam.getRegistryKey(), registryParam.getRegistryValue());
|
|
||||||
if (ret > 0) {
|
|
||||||
// fresh
|
|
||||||
freshGroupRegistryInfo(registryParam);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return ReturnT.SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void freshGroupRegistryInfo(RegistryParam registryParam) {
|
|
||||||
// Under consideration, prevent affecting core tables
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,370 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.thread;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
|
||||||
import com.xxl.job.admin.core.cron.CronExpression;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
|
||||||
import com.xxl.job.admin.core.scheduler.MisfireStrategyEnum;
|
|
||||||
import com.xxl.job.admin.core.scheduler.ScheduleTypeEnum;
|
|
||||||
import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author xuxueli 2019-05-21
|
|
||||||
*/
|
|
||||||
public class JobScheduleHelper {
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(JobScheduleHelper.class);
|
|
||||||
|
|
||||||
private static JobScheduleHelper instance = new JobScheduleHelper();
|
|
||||||
|
|
||||||
public static JobScheduleHelper getInstance() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final long PRE_READ_MS = 5000; // pre read
|
|
||||||
|
|
||||||
private Thread scheduleThread;
|
|
||||||
private Thread ringThread;
|
|
||||||
private volatile boolean scheduleThreadToStop = false;
|
|
||||||
private volatile boolean ringThreadToStop = false;
|
|
||||||
private volatile static Map<Integer, List<Integer>> ringData = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
public void start() {
|
|
||||||
|
|
||||||
// schedule thread
|
|
||||||
scheduleThread = new Thread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
|
|
||||||
try {
|
|
||||||
TimeUnit.MILLISECONDS.sleep(5000 - System.currentTimeMillis() % 1000);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
if (!scheduleThreadToStop) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logger.info(">>>>>>>>> init xxl-job admin scheduler success.");
|
|
||||||
|
|
||||||
// pre-read count: treadpool-size * trigger-qps (each trigger cost 50ms, qps = 1000/50 = 20)
|
|
||||||
int preReadCount = (XxlJobAdminConfig.getAdminConfig().getTriggerPoolFastMax() + XxlJobAdminConfig.getAdminConfig().getTriggerPoolSlowMax()) * 20;
|
|
||||||
|
|
||||||
while (!scheduleThreadToStop) {
|
|
||||||
|
|
||||||
// Scan Job
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
|
|
||||||
Connection conn = null;
|
|
||||||
Boolean connAutoCommit = null;
|
|
||||||
PreparedStatement preparedStatement = null;
|
|
||||||
|
|
||||||
boolean preReadSuc = true;
|
|
||||||
try {
|
|
||||||
|
|
||||||
conn = XxlJobAdminConfig.getAdminConfig().getDataSource().getConnection();
|
|
||||||
connAutoCommit = conn.getAutoCommit();
|
|
||||||
conn.setAutoCommit(false);
|
|
||||||
|
|
||||||
preparedStatement = conn.prepareStatement("select * from xxl_job_lock where lock_name = 'schedule_lock' for update");
|
|
||||||
preparedStatement.execute();
|
|
||||||
|
|
||||||
// tx start
|
|
||||||
|
|
||||||
// 1、pre read
|
|
||||||
long nowTime = System.currentTimeMillis();
|
|
||||||
List<XxlJobInfo> scheduleList = XxlJobAdminConfig.getAdminConfig().getXxlJobInfoDao().scheduleJobQuery(nowTime + PRE_READ_MS, preReadCount);
|
|
||||||
if (scheduleList != null && scheduleList.size() > 0) {
|
|
||||||
// 2、push time-ring
|
|
||||||
for (XxlJobInfo jobInfo : scheduleList) {
|
|
||||||
|
|
||||||
// time-ring jump
|
|
||||||
if (nowTime > jobInfo.getTriggerNextTime() + PRE_READ_MS) {
|
|
||||||
// 2.1、trigger-expire > 5s:pass && make next-trigger-time
|
|
||||||
logger.warn(">>>>>>>>>>> xxl-job, schedule misfire, jobId = " + jobInfo.getId());
|
|
||||||
|
|
||||||
// 1、misfire match
|
|
||||||
MisfireStrategyEnum misfireStrategyEnum = MisfireStrategyEnum.match(jobInfo.getMisfireStrategy(), MisfireStrategyEnum.DO_NOTHING);
|
|
||||||
if (MisfireStrategyEnum.FIRE_ONCE_NOW == misfireStrategyEnum) {
|
|
||||||
// FIRE_ONCE_NOW 》 trigger
|
|
||||||
JobTriggerPoolHelper.trigger(jobInfo.getId(), TriggerTypeEnum.MISFIRE, -1, null, null, null);
|
|
||||||
logger.debug(">>>>>>>>>>> xxl-job, schedule push trigger : jobId = " + jobInfo.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2、fresh next
|
|
||||||
refreshNextValidTime(jobInfo, new Date());
|
|
||||||
|
|
||||||
} else if (nowTime > jobInfo.getTriggerNextTime()) {
|
|
||||||
// 2.2、trigger-expire < 5s:direct-trigger && make next-trigger-time
|
|
||||||
|
|
||||||
// 1、trigger
|
|
||||||
JobTriggerPoolHelper.trigger(jobInfo.getId(), TriggerTypeEnum.CRON, -1, null, null, null);
|
|
||||||
logger.debug(">>>>>>>>>>> xxl-job, schedule push trigger : jobId = " + jobInfo.getId());
|
|
||||||
|
|
||||||
// 2、fresh next
|
|
||||||
refreshNextValidTime(jobInfo, new Date());
|
|
||||||
|
|
||||||
// next-trigger-time in 5s, pre-read again
|
|
||||||
if (jobInfo.getTriggerStatus() == 1 && nowTime + PRE_READ_MS > jobInfo.getTriggerNextTime()) {
|
|
||||||
|
|
||||||
// 1、make ring second
|
|
||||||
int ringSecond = (int) ((jobInfo.getTriggerNextTime() / 1000) % 60);
|
|
||||||
|
|
||||||
// 2、push time ring
|
|
||||||
pushTimeRing(ringSecond, jobInfo.getId());
|
|
||||||
|
|
||||||
// 3、fresh next
|
|
||||||
refreshNextValidTime(jobInfo, new Date(jobInfo.getTriggerNextTime()));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// 2.3、trigger-pre-read:time-ring trigger && make next-trigger-time
|
|
||||||
|
|
||||||
// 1、make ring second
|
|
||||||
int ringSecond = (int) ((jobInfo.getTriggerNextTime() / 1000) % 60);
|
|
||||||
|
|
||||||
// 2、push time ring
|
|
||||||
pushTimeRing(ringSecond, jobInfo.getId());
|
|
||||||
|
|
||||||
// 3、fresh next
|
|
||||||
refreshNextValidTime(jobInfo, new Date(jobInfo.getTriggerNextTime()));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3、update trigger info
|
|
||||||
for (XxlJobInfo jobInfo : scheduleList) {
|
|
||||||
XxlJobAdminConfig.getAdminConfig().getXxlJobInfoDao().scheduleUpdate(jobInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
preReadSuc = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// tx stop
|
|
||||||
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
if (!scheduleThreadToStop) {
|
|
||||||
logger.error(">>>>>>>>>>> xxl-job, JobScheduleHelper#scheduleThread error:{}", e);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
|
|
||||||
// commit
|
|
||||||
if (conn != null) {
|
|
||||||
try {
|
|
||||||
conn.commit();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
if (!scheduleThreadToStop) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
conn.setAutoCommit(connAutoCommit);
|
|
||||||
} catch (SQLException e) {
|
|
||||||
if (!scheduleThreadToStop) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
conn.close();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
if (!scheduleThreadToStop) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// close PreparedStatement
|
|
||||||
if (null != preparedStatement) {
|
|
||||||
try {
|
|
||||||
preparedStatement.close();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
if (!scheduleThreadToStop) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
long cost = System.currentTimeMillis() - start;
|
|
||||||
|
|
||||||
|
|
||||||
// Wait seconds, align second
|
|
||||||
if (cost < 1000) { // scan-overtime, not wait
|
|
||||||
try {
|
|
||||||
// pre-read period: success > scan each second; fail > skip this period;
|
|
||||||
TimeUnit.MILLISECONDS.sleep((preReadSuc ? 1000 : PRE_READ_MS) - System.currentTimeMillis() % 1000);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
if (!scheduleThreadToStop) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info(">>>>>>>>>>> xxl-job, JobScheduleHelper#scheduleThread stop");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
scheduleThread.setDaemon(true);
|
|
||||||
scheduleThread.setName("xxl-job, admin JobScheduleHelper#scheduleThread");
|
|
||||||
scheduleThread.start();
|
|
||||||
|
|
||||||
|
|
||||||
// ring thread
|
|
||||||
ringThread = new Thread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
|
|
||||||
while (!ringThreadToStop) {
|
|
||||||
|
|
||||||
// align second
|
|
||||||
try {
|
|
||||||
TimeUnit.MILLISECONDS.sleep(1000 - System.currentTimeMillis() % 1000);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
if (!ringThreadToStop) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// second data
|
|
||||||
List<Integer> ringItemData = new ArrayList<>();
|
|
||||||
int nowSecond = Calendar.getInstance().get(Calendar.SECOND); // 避免处理耗时太长,跨过刻度,向前校验一个刻度;
|
|
||||||
for (int i = 0; i < 2; i++) {
|
|
||||||
List<Integer> tmpData = ringData.remove((nowSecond + 60 - i) % 60);
|
|
||||||
if (tmpData != null) {
|
|
||||||
ringItemData.addAll(tmpData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ring trigger
|
|
||||||
logger.debug(">>>>>>>>>>> xxl-job, time-ring beat : " + nowSecond + " = " + Arrays.asList(ringItemData));
|
|
||||||
if (ringItemData.size() > 0) {
|
|
||||||
// do trigger
|
|
||||||
for (int jobId : ringItemData) {
|
|
||||||
// do trigger
|
|
||||||
JobTriggerPoolHelper.trigger(jobId, TriggerTypeEnum.CRON, -1, null, null, null);
|
|
||||||
}
|
|
||||||
// clear
|
|
||||||
ringItemData.clear();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
if (!ringThreadToStop) {
|
|
||||||
logger.error(">>>>>>>>>>> xxl-job, JobScheduleHelper#ringThread error:{}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logger.info(">>>>>>>>>>> xxl-job, JobScheduleHelper#ringThread stop");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ringThread.setDaemon(true);
|
|
||||||
ringThread.setName("xxl-job, admin JobScheduleHelper#ringThread");
|
|
||||||
ringThread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refreshNextValidTime(XxlJobInfo jobInfo, Date fromTime) throws Exception {
|
|
||||||
Date nextValidTime = generateNextValidTime(jobInfo, fromTime);
|
|
||||||
if (nextValidTime != null) {
|
|
||||||
jobInfo.setTriggerLastTime(jobInfo.getTriggerNextTime());
|
|
||||||
jobInfo.setTriggerNextTime(nextValidTime.getTime());
|
|
||||||
} else {
|
|
||||||
jobInfo.setTriggerStatus(0);
|
|
||||||
jobInfo.setTriggerLastTime(0);
|
|
||||||
jobInfo.setTriggerNextTime(0);
|
|
||||||
logger.warn(">>>>>>>>>>> xxl-job, refreshNextValidTime fail for job: jobId={}, scheduleType={}, scheduleConf={}",
|
|
||||||
jobInfo.getId(), jobInfo.getScheduleType(), jobInfo.getScheduleConf());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void pushTimeRing(int ringSecond, int jobId) {
|
|
||||||
// push async ring
|
|
||||||
List<Integer> ringItemData = ringData.get(ringSecond);
|
|
||||||
if (ringItemData == null) {
|
|
||||||
ringItemData = new ArrayList<Integer>();
|
|
||||||
ringData.put(ringSecond, ringItemData);
|
|
||||||
}
|
|
||||||
ringItemData.add(jobId);
|
|
||||||
|
|
||||||
logger.debug(">>>>>>>>>>> xxl-job, schedule push time-ring : " + ringSecond + " = " + Arrays.asList(ringItemData));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void toStop() {
|
|
||||||
|
|
||||||
// 1、stop schedule
|
|
||||||
scheduleThreadToStop = true;
|
|
||||||
try {
|
|
||||||
TimeUnit.SECONDS.sleep(1); // wait
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
if (scheduleThread.getState() != Thread.State.TERMINATED) {
|
|
||||||
// interrupt and wait
|
|
||||||
scheduleThread.interrupt();
|
|
||||||
try {
|
|
||||||
scheduleThread.join();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if has ring data
|
|
||||||
boolean hasRingData = false;
|
|
||||||
if (!ringData.isEmpty()) {
|
|
||||||
for (int second : ringData.keySet()) {
|
|
||||||
List<Integer> tmpData = ringData.get(second);
|
|
||||||
if (tmpData != null && tmpData.size() > 0) {
|
|
||||||
hasRingData = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (hasRingData) {
|
|
||||||
try {
|
|
||||||
TimeUnit.SECONDS.sleep(8);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// stop ring (wait job-in-memory stop)
|
|
||||||
ringThreadToStop = true;
|
|
||||||
try {
|
|
||||||
TimeUnit.SECONDS.sleep(1);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
if (ringThread.getState() != Thread.State.TERMINATED) {
|
|
||||||
// interrupt and wait
|
|
||||||
ringThread.interrupt();
|
|
||||||
try {
|
|
||||||
ringThread.join();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info(">>>>>>>>>>> xxl-job, JobScheduleHelper stop");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------- tools ----------------------
|
|
||||||
public static Date generateNextValidTime(XxlJobInfo jobInfo, Date fromTime) throws Exception {
|
|
||||||
ScheduleTypeEnum scheduleTypeEnum = ScheduleTypeEnum.match(jobInfo.getScheduleType(), null);
|
|
||||||
if (ScheduleTypeEnum.CRON == scheduleTypeEnum) {
|
|
||||||
Date nextValidTime = new CronExpression(jobInfo.getScheduleConf()).getNextValidTimeAfter(fromTime);
|
|
||||||
return nextValidTime;
|
|
||||||
} else if (ScheduleTypeEnum.FIX_RATE == scheduleTypeEnum /*|| ScheduleTypeEnum.FIX_DELAY == scheduleTypeEnum*/) {
|
|
||||||
return new Date(fromTime.getTime() + Integer.valueOf(jobInfo.getScheduleConf()) * 1000);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,148 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.thread;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
|
||||||
import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
|
|
||||||
import com.xxl.job.admin.core.trigger.XxlJobTrigger;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.concurrent.*;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* job trigger thread pool helper
|
|
||||||
*
|
|
||||||
* @author xuxueli 2018-07-03 21:08:07
|
|
||||||
*/
|
|
||||||
public class JobTriggerPoolHelper {
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(JobTriggerPoolHelper.class);
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------- trigger pool ----------------------
|
|
||||||
|
|
||||||
// fast/slow thread pool
|
|
||||||
private ThreadPoolExecutor fastTriggerPool = null;
|
|
||||||
private ThreadPoolExecutor slowTriggerPool = null;
|
|
||||||
|
|
||||||
public void start() {
|
|
||||||
fastTriggerPool = new ThreadPoolExecutor(
|
|
||||||
10,
|
|
||||||
XxlJobAdminConfig.getAdminConfig().getTriggerPoolFastMax(),
|
|
||||||
60L,
|
|
||||||
TimeUnit.SECONDS,
|
|
||||||
new LinkedBlockingQueue<Runnable>(1000),
|
|
||||||
new ThreadFactory() {
|
|
||||||
@Override
|
|
||||||
public Thread newThread(Runnable r) {
|
|
||||||
return new Thread(r, "xxl-job, admin JobTriggerPoolHelper-fastTriggerPool-" + r.hashCode());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
slowTriggerPool = new ThreadPoolExecutor(
|
|
||||||
10,
|
|
||||||
XxlJobAdminConfig.getAdminConfig().getTriggerPoolSlowMax(),
|
|
||||||
60L,
|
|
||||||
TimeUnit.SECONDS,
|
|
||||||
new LinkedBlockingQueue<Runnable>(2000),
|
|
||||||
new ThreadFactory() {
|
|
||||||
@Override
|
|
||||||
public Thread newThread(Runnable r) {
|
|
||||||
return new Thread(r, "xxl-job, admin JobTriggerPoolHelper-slowTriggerPool-" + r.hashCode());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void stop() {
|
|
||||||
//triggerPool.shutdown();
|
|
||||||
fastTriggerPool.shutdownNow();
|
|
||||||
slowTriggerPool.shutdownNow();
|
|
||||||
logger.info(">>>>>>>>> xxl-job trigger thread pool shutdown success.");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// job timeout count
|
|
||||||
private volatile long minTim = System.currentTimeMillis() / 60000; // ms > min
|
|
||||||
private volatile ConcurrentMap<Integer, AtomicInteger> jobTimeoutCountMap = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* add trigger
|
|
||||||
*/
|
|
||||||
public void addTrigger(final int jobId,
|
|
||||||
final TriggerTypeEnum triggerType,
|
|
||||||
final int failRetryCount,
|
|
||||||
final String executorShardingParam,
|
|
||||||
final String executorParam,
|
|
||||||
final String addressList) {
|
|
||||||
|
|
||||||
// choose thread pool
|
|
||||||
ThreadPoolExecutor triggerPool_ = fastTriggerPool;
|
|
||||||
AtomicInteger jobTimeoutCount = jobTimeoutCountMap.get(jobId);
|
|
||||||
if (jobTimeoutCount != null && jobTimeoutCount.get() > 10) { // job-timeout 10 times in 1 min
|
|
||||||
triggerPool_ = slowTriggerPool;
|
|
||||||
}
|
|
||||||
|
|
||||||
// trigger
|
|
||||||
triggerPool_.execute(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
|
|
||||||
try {
|
|
||||||
// do trigger
|
|
||||||
XxlJobTrigger.trigger(jobId, triggerType, failRetryCount, executorShardingParam, executorParam, addressList);
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
} finally {
|
|
||||||
|
|
||||||
// check timeout-count-map
|
|
||||||
long minTim_now = System.currentTimeMillis() / 60000;
|
|
||||||
if (minTim != minTim_now) {
|
|
||||||
minTim = minTim_now;
|
|
||||||
jobTimeoutCountMap.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// incr timeout-count-map
|
|
||||||
long cost = System.currentTimeMillis() - start;
|
|
||||||
if (cost > 500) { // ob-timeout threshold 500ms
|
|
||||||
AtomicInteger timeoutCount = jobTimeoutCountMap.putIfAbsent(jobId, new AtomicInteger(1));
|
|
||||||
if (timeoutCount != null) {
|
|
||||||
timeoutCount.incrementAndGet();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------- helper ----------------------
|
|
||||||
|
|
||||||
private static JobTriggerPoolHelper helper = new JobTriggerPoolHelper();
|
|
||||||
|
|
||||||
public static void toStart() {
|
|
||||||
helper.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void toStop() {
|
|
||||||
helper.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param jobId
|
|
||||||
* @param triggerType
|
|
||||||
* @param failRetryCount >=0: use this param
|
|
||||||
* <0: use param from job info config
|
|
||||||
* @param executorShardingParam
|
|
||||||
* @param executorParam null: use job param
|
|
||||||
* not null: cover job param
|
|
||||||
*/
|
|
||||||
public static void trigger(int jobId, TriggerTypeEnum triggerType, int failRetryCount, String executorShardingParam, String executorParam, String addressList) {
|
|
||||||
helper.addTrigger(jobId, triggerType, failRetryCount, executorShardingParam, executorParam, addressList);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.trigger;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* trigger type enum
|
|
||||||
*
|
|
||||||
* @author xuxueli 2018-09-16 04:56:41
|
|
||||||
*/
|
|
||||||
public enum TriggerTypeEnum {
|
|
||||||
|
|
||||||
MANUAL(I18nUtil.getString("jobconf_trigger_type_manual")),
|
|
||||||
CRON(I18nUtil.getString("jobconf_trigger_type_cron")),
|
|
||||||
RETRY(I18nUtil.getString("jobconf_trigger_type_retry")),
|
|
||||||
PARENT(I18nUtil.getString("jobconf_trigger_type_parent")),
|
|
||||||
API(I18nUtil.getString("jobconf_trigger_type_api")),
|
|
||||||
MISFIRE(I18nUtil.getString("jobconf_trigger_type_misfire"));
|
|
||||||
|
|
||||||
private TriggerTypeEnum(String title) {
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String title;
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,224 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.trigger;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobGroup;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobLog;
|
|
||||||
import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;
|
|
||||||
import com.xxl.job.admin.core.scheduler.XxlJobScheduler;
|
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
|
||||||
import com.xxl.job.core.biz.ExecutorBiz;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import com.xxl.job.core.biz.model.TriggerParam;
|
|
||||||
import com.xxl.job.core.enums.ExecutorBlockStrategyEnum;
|
|
||||||
import com.xxl.job.core.util.IpUtil;
|
|
||||||
import com.xxl.job.core.util.ThrowableUtil;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* xxl-job trigger
|
|
||||||
* Created by xuxueli on 17/7/13.
|
|
||||||
*/
|
|
||||||
public class XxlJobTrigger {
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(XxlJobTrigger.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* trigger job
|
|
||||||
*
|
|
||||||
* @param jobId
|
|
||||||
* @param triggerType
|
|
||||||
* @param failRetryCount >=0: use this param
|
|
||||||
* <0: use param from job info config
|
|
||||||
* @param executorShardingParam
|
|
||||||
* @param executorParam null: use job param
|
|
||||||
* not null: cover job param
|
|
||||||
* @param addressList null: use executor addressList
|
|
||||||
* not null: cover
|
|
||||||
*/
|
|
||||||
public static void trigger(int jobId,
|
|
||||||
TriggerTypeEnum triggerType,
|
|
||||||
int failRetryCount,
|
|
||||||
String executorShardingParam,
|
|
||||||
String executorParam,
|
|
||||||
String addressList) {
|
|
||||||
|
|
||||||
// load data
|
|
||||||
XxlJobInfo jobInfo = XxlJobAdminConfig.getAdminConfig().getXxlJobInfoDao().loadById(jobId);
|
|
||||||
if (jobInfo == null) {
|
|
||||||
logger.warn(">>>>>>>>>>>> trigger fail, jobId invalid,jobId={}", jobId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (executorParam != null) {
|
|
||||||
jobInfo.setExecutorParam(executorParam);
|
|
||||||
}
|
|
||||||
int finalFailRetryCount = failRetryCount >= 0 ? failRetryCount : jobInfo.getExecutorFailRetryCount();
|
|
||||||
XxlJobGroup group = XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().load(jobInfo.getJobGroup());
|
|
||||||
|
|
||||||
// cover addressList
|
|
||||||
if (addressList != null && addressList.trim().length() > 0) {
|
|
||||||
group.setAddressType(1);
|
|
||||||
group.setAddressList(addressList.trim());
|
|
||||||
}
|
|
||||||
|
|
||||||
// sharding param
|
|
||||||
int[] shardingParam = null;
|
|
||||||
if (executorShardingParam != null) {
|
|
||||||
String[] shardingArr = executorShardingParam.split("/");
|
|
||||||
if (shardingArr.length == 2 && isNumeric(shardingArr[0]) && isNumeric(shardingArr[1])) {
|
|
||||||
shardingParam = new int[2];
|
|
||||||
shardingParam[0] = Integer.valueOf(shardingArr[0]);
|
|
||||||
shardingParam[1] = Integer.valueOf(shardingArr[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ExecutorRouteStrategyEnum.SHARDING_BROADCAST == ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null)
|
|
||||||
&& group.getRegistryList() != null && !group.getRegistryList().isEmpty()
|
|
||||||
&& shardingParam == null) {
|
|
||||||
for (int i = 0; i < group.getRegistryList().size(); i++) {
|
|
||||||
processTrigger(group, jobInfo, finalFailRetryCount, triggerType, i, group.getRegistryList().size());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (shardingParam == null) {
|
|
||||||
shardingParam = new int[]{0, 1};
|
|
||||||
}
|
|
||||||
processTrigger(group, jobInfo, finalFailRetryCount, triggerType, shardingParam[0], shardingParam[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isNumeric(String str) {
|
|
||||||
try {
|
|
||||||
int result = Integer.valueOf(str);
|
|
||||||
return true;
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param group job group, registry list may be empty
|
|
||||||
* @param jobInfo
|
|
||||||
* @param finalFailRetryCount
|
|
||||||
* @param triggerType
|
|
||||||
* @param index sharding index
|
|
||||||
* @param total sharding index
|
|
||||||
*/
|
|
||||||
private static void processTrigger(XxlJobGroup group, XxlJobInfo jobInfo, int finalFailRetryCount, TriggerTypeEnum triggerType, int index, int total) {
|
|
||||||
|
|
||||||
// param
|
|
||||||
ExecutorBlockStrategyEnum blockStrategy = ExecutorBlockStrategyEnum.match(jobInfo.getExecutorBlockStrategy(), ExecutorBlockStrategyEnum.SERIAL_EXECUTION); // block strategy
|
|
||||||
ExecutorRouteStrategyEnum executorRouteStrategyEnum = ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null); // route strategy
|
|
||||||
String shardingParam = (ExecutorRouteStrategyEnum.SHARDING_BROADCAST == executorRouteStrategyEnum) ? String.valueOf(index).concat("/").concat(String.valueOf(total)) : null;
|
|
||||||
|
|
||||||
// 1、save log-id
|
|
||||||
XxlJobLog jobLog = new XxlJobLog();
|
|
||||||
jobLog.setJobGroup(jobInfo.getJobGroup());
|
|
||||||
jobLog.setJobId(jobInfo.getId());
|
|
||||||
jobLog.setTriggerTime(new Date());
|
|
||||||
XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().save(jobLog);
|
|
||||||
logger.debug(">>>>>>>>>>> xxl-job trigger start, jobId:{}", jobLog.getId());
|
|
||||||
|
|
||||||
// 2、init trigger-param
|
|
||||||
TriggerParam triggerParam = new TriggerParam();
|
|
||||||
triggerParam.setJobId(jobInfo.getId());
|
|
||||||
triggerParam.setExecutorHandler(jobInfo.getExecutorHandler());
|
|
||||||
triggerParam.setExecutorParams(jobInfo.getExecutorParam());
|
|
||||||
triggerParam.setExecutorBlockStrategy(jobInfo.getExecutorBlockStrategy());
|
|
||||||
triggerParam.setExecutorTimeout(jobInfo.getExecutorTimeout());
|
|
||||||
triggerParam.setLogId(jobLog.getId());
|
|
||||||
triggerParam.setLogDateTime(jobLog.getTriggerTime().getTime());
|
|
||||||
triggerParam.setGlueType(jobInfo.getGlueType());
|
|
||||||
triggerParam.setGlueSource(jobInfo.getGlueSource());
|
|
||||||
triggerParam.setGlueUpdatetime(jobInfo.getGlueUpdatetime().getTime());
|
|
||||||
triggerParam.setBroadcastIndex(index);
|
|
||||||
triggerParam.setBroadcastTotal(total);
|
|
||||||
|
|
||||||
// 3、init address
|
|
||||||
String address = null;
|
|
||||||
ReturnT<String> routeAddressResult = null;
|
|
||||||
if (group.getRegistryList() != null && !group.getRegistryList().isEmpty()) {
|
|
||||||
if (ExecutorRouteStrategyEnum.SHARDING_BROADCAST == executorRouteStrategyEnum) {
|
|
||||||
if (index < group.getRegistryList().size()) {
|
|
||||||
address = group.getRegistryList().get(index);
|
|
||||||
} else {
|
|
||||||
address = group.getRegistryList().get(0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
routeAddressResult = executorRouteStrategyEnum.getRouter().route(triggerParam, group.getRegistryList());
|
|
||||||
if (routeAddressResult.getCode() == ReturnT.SUCCESS_CODE) {
|
|
||||||
address = routeAddressResult.getContent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
routeAddressResult = new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("jobconf_trigger_address_empty"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4、trigger remote executor
|
|
||||||
ReturnT<String> triggerResult = null;
|
|
||||||
if (address != null) {
|
|
||||||
triggerResult = runExecutor(triggerParam, address);
|
|
||||||
} else {
|
|
||||||
triggerResult = new ReturnT<String>(ReturnT.FAIL_CODE, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5、collection trigger info
|
|
||||||
StringBuffer triggerMsgSb = new StringBuffer();
|
|
||||||
triggerMsgSb.append(I18nUtil.getString("jobconf_trigger_type")).append(":").append(triggerType.getTitle());
|
|
||||||
triggerMsgSb.append("<br>").append(I18nUtil.getString("jobconf_trigger_admin_adress")).append(":").append(IpUtil.getIp());
|
|
||||||
triggerMsgSb.append("<br>").append(I18nUtil.getString("jobconf_trigger_exe_regtype")).append(":")
|
|
||||||
.append((group.getAddressType() == 0) ? I18nUtil.getString("jobgroup_field_addressType_0") : I18nUtil.getString("jobgroup_field_addressType_1"));
|
|
||||||
triggerMsgSb.append("<br>").append(I18nUtil.getString("jobconf_trigger_exe_regaddress")).append(":").append(group.getRegistryList());
|
|
||||||
triggerMsgSb.append("<br>").append(I18nUtil.getString("jobinfo_field_executorRouteStrategy")).append(":").append(executorRouteStrategyEnum.getTitle());
|
|
||||||
if (shardingParam != null) {
|
|
||||||
triggerMsgSb.append("(" + shardingParam + ")");
|
|
||||||
}
|
|
||||||
triggerMsgSb.append("<br>").append(I18nUtil.getString("jobinfo_field_executorBlockStrategy")).append(":").append(blockStrategy.getTitle());
|
|
||||||
triggerMsgSb.append("<br>").append(I18nUtil.getString("jobinfo_field_timeout")).append(":").append(jobInfo.getExecutorTimeout());
|
|
||||||
triggerMsgSb.append("<br>").append(I18nUtil.getString("jobinfo_field_executorFailRetryCount")).append(":").append(finalFailRetryCount);
|
|
||||||
|
|
||||||
triggerMsgSb.append("<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>" + I18nUtil.getString("jobconf_trigger_run") + "<<<<<<<<<<< </span><br>")
|
|
||||||
.append((routeAddressResult != null && routeAddressResult.getMsg() != null) ? routeAddressResult.getMsg() + "<br><br>" : "").append(triggerResult.getMsg() != null ? triggerResult.getMsg() : "");
|
|
||||||
|
|
||||||
// 6、save log trigger-info
|
|
||||||
jobLog.setExecutorAddress(address);
|
|
||||||
jobLog.setExecutorHandler(jobInfo.getExecutorHandler());
|
|
||||||
jobLog.setExecutorParam(jobInfo.getExecutorParam());
|
|
||||||
jobLog.setExecutorShardingParam(shardingParam);
|
|
||||||
jobLog.setExecutorFailRetryCount(finalFailRetryCount);
|
|
||||||
//jobLog.setTriggerTime();
|
|
||||||
jobLog.setTriggerCode(triggerResult.getCode());
|
|
||||||
jobLog.setTriggerMsg(triggerMsgSb.toString());
|
|
||||||
XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().updateTriggerInfo(jobLog);
|
|
||||||
|
|
||||||
logger.debug(">>>>>>>>>>> xxl-job trigger end, jobId:{}", jobLog.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* run executor
|
|
||||||
*
|
|
||||||
* @param triggerParam
|
|
||||||
* @param address
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static ReturnT<String> runExecutor(TriggerParam triggerParam, String address) {
|
|
||||||
ReturnT<String> runResult = null;
|
|
||||||
try {
|
|
||||||
ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(address);
|
|
||||||
runResult = executorBiz.run(triggerParam);
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error(">>>>>>>>>>> xxl-job trigger error, please check if the executor[{}] is running.", address, e);
|
|
||||||
runResult = new ReturnT<String>(ReturnT.FAIL_CODE, ThrowableUtil.toString(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuffer runResultSB = new StringBuffer(I18nUtil.getString("jobconf_trigger_run") + ":");
|
|
||||||
runResultSB.append("<br>address:").append(address);
|
|
||||||
runResultSB.append("<br>code:").append(runResult.getCode());
|
|
||||||
runResultSB.append("<br>msg:").append(runResult.getMsg());
|
|
||||||
|
|
||||||
runResult.setMsg(runResultSB.toString());
|
|
||||||
return runResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,98 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.util;
|
|
||||||
|
|
||||||
import javax.servlet.http.Cookie;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cookie.Util
|
|
||||||
*
|
|
||||||
* @author xuxueli 2015-12-12 18:01:06
|
|
||||||
*/
|
|
||||||
public class CookieUtil {
|
|
||||||
|
|
||||||
// 默认缓存时间,单位/秒, 2H
|
|
||||||
private static final int COOKIE_MAX_AGE = Integer.MAX_VALUE;
|
|
||||||
// 保存路径,根路径
|
|
||||||
private static final String COOKIE_PATH = "/";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存
|
|
||||||
*
|
|
||||||
* @param response
|
|
||||||
* @param key
|
|
||||||
* @param value
|
|
||||||
* @param ifRemember
|
|
||||||
*/
|
|
||||||
public static void set(HttpServletResponse response, String key, String value, boolean ifRemember) {
|
|
||||||
int age = ifRemember ? COOKIE_MAX_AGE : -1;
|
|
||||||
set(response, key, value, null, COOKIE_PATH, age, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存
|
|
||||||
*
|
|
||||||
* @param response
|
|
||||||
* @param key
|
|
||||||
* @param value
|
|
||||||
* @param maxAge
|
|
||||||
*/
|
|
||||||
private static void set(HttpServletResponse response, String key, String value, String domain, String path, int maxAge, boolean isHttpOnly) {
|
|
||||||
Cookie cookie = new Cookie(key, value);
|
|
||||||
if (domain != null) {
|
|
||||||
cookie.setDomain(domain);
|
|
||||||
}
|
|
||||||
cookie.setPath(path);
|
|
||||||
cookie.setMaxAge(maxAge);
|
|
||||||
cookie.setHttpOnly(isHttpOnly);
|
|
||||||
response.addCookie(cookie);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询value
|
|
||||||
*
|
|
||||||
* @param request
|
|
||||||
* @param key
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String getValue(HttpServletRequest request, String key) {
|
|
||||||
Cookie cookie = get(request, key);
|
|
||||||
if (cookie != null) {
|
|
||||||
return cookie.getValue();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询Cookie
|
|
||||||
*
|
|
||||||
* @param request
|
|
||||||
* @param key
|
|
||||||
*/
|
|
||||||
private static Cookie get(HttpServletRequest request, String key) {
|
|
||||||
Cookie[] arr_cookie = request.getCookies();
|
|
||||||
if (arr_cookie != null && arr_cookie.length > 0) {
|
|
||||||
for (Cookie cookie : arr_cookie) {
|
|
||||||
if (cookie.getName().equals(key)) {
|
|
||||||
return cookie;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除Cookie
|
|
||||||
*
|
|
||||||
* @param request
|
|
||||||
* @param response
|
|
||||||
* @param key
|
|
||||||
*/
|
|
||||||
public static void remove(HttpServletRequest request, HttpServletResponse response, String key) {
|
|
||||||
Cookie cookie = get(request, key);
|
|
||||||
if (cookie != null) {
|
|
||||||
set(response, key, "", null, COOKIE_PATH, 0, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.util;
|
|
||||||
|
|
||||||
import freemarker.ext.beans.BeansWrapper;
|
|
||||||
import freemarker.ext.beans.BeansWrapperBuilder;
|
|
||||||
import freemarker.template.Configuration;
|
|
||||||
import freemarker.template.TemplateHashModel;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ftl util
|
|
||||||
*
|
|
||||||
* @author xuxueli 2018-01-17 20:37:48
|
|
||||||
*/
|
|
||||||
public class FtlUtil {
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(FtlUtil.class);
|
|
||||||
|
|
||||||
private static BeansWrapper wrapper = new BeansWrapperBuilder(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS).build(); //BeansWrapper.getDefaultInstance();
|
|
||||||
|
|
||||||
public static TemplateHashModel generateStaticModel(String packageName) {
|
|
||||||
try {
|
|
||||||
TemplateHashModel staticModels = wrapper.getStaticModels();
|
|
||||||
TemplateHashModel fileStatics = (TemplateHashModel) staticModels.get(packageName);
|
|
||||||
return fileStatics;
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,80 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.util;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.core.io.ClassPathResource;
|
|
||||||
import org.springframework.core.io.Resource;
|
|
||||||
import org.springframework.core.io.support.EncodedResource;
|
|
||||||
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.text.MessageFormat;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* i18n util
|
|
||||||
*
|
|
||||||
* @author xuxueli 2018-01-17 20:39:06
|
|
||||||
*/
|
|
||||||
public class I18nUtil {
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(I18nUtil.class);
|
|
||||||
|
|
||||||
private static Properties prop = null;
|
|
||||||
|
|
||||||
public static Properties loadI18nProp() {
|
|
||||||
if (prop != null) {
|
|
||||||
return prop;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
// build i18n prop
|
|
||||||
String i18n = XxlJobAdminConfig.getAdminConfig().getI18n();
|
|
||||||
String i18nFile = MessageFormat.format("i18n/message_{0}.properties", i18n);
|
|
||||||
|
|
||||||
// load prop
|
|
||||||
Resource resource = new ClassPathResource(i18nFile);
|
|
||||||
EncodedResource encodedResource = new EncodedResource(resource, "UTF-8");
|
|
||||||
prop = PropertiesLoaderUtils.loadProperties(encodedResource);
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
return prop;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get val of i18n key
|
|
||||||
*
|
|
||||||
* @param key
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String getString(String key) {
|
|
||||||
return loadI18nProp().getProperty(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get mult val of i18n mult key, as json
|
|
||||||
*
|
|
||||||
* @param keys
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String getMultString(String... keys) {
|
|
||||||
Map<String, String> map = new HashMap<String, String>();
|
|
||||||
|
|
||||||
Properties prop = loadI18nProp();
|
|
||||||
if (keys != null && keys.length > 0) {
|
|
||||||
for (String key : keys) {
|
|
||||||
map.put(key, prop.getProperty(key));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (String key : prop.stringPropertyNames()) {
|
|
||||||
map.put(key, prop.getProperty(key));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String json = JacksonUtil.writeValueAsString(map);
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,93 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.util;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonGenerationException;
|
|
||||||
import com.fasterxml.jackson.core.JsonParseException;
|
|
||||||
import com.fasterxml.jackson.databind.JavaType;
|
|
||||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Jackson util
|
|
||||||
* <p>
|
|
||||||
* 1、obj need private and set/get;
|
|
||||||
* 2、do not support inner class;
|
|
||||||
*
|
|
||||||
* @author xuxueli 2015-9-25 18:02:56
|
|
||||||
*/
|
|
||||||
public class JacksonUtil {
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(JacksonUtil.class);
|
|
||||||
|
|
||||||
private final static ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
|
||||||
|
|
||||||
public static ObjectMapper getInstance() {
|
|
||||||
return OBJECT_MAPPER;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* bean、array、List、Map --> json
|
|
||||||
*
|
|
||||||
* @param obj
|
|
||||||
* @return json string
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public static String writeValueAsString(Object obj) {
|
|
||||||
try {
|
|
||||||
return getInstance().writeValueAsString(obj);
|
|
||||||
} catch (JsonGenerationException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
} catch (JsonMappingException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* string --> bean、Map、List(array)
|
|
||||||
*
|
|
||||||
* @param jsonStr
|
|
||||||
* @param clazz
|
|
||||||
* @return obj
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public static <T> T readValue(String jsonStr, Class<T> clazz) {
|
|
||||||
try {
|
|
||||||
return getInstance().readValue(jsonStr, clazz);
|
|
||||||
} catch (JsonParseException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
} catch (JsonMappingException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* string --> List<Bean>...
|
|
||||||
*
|
|
||||||
* @param jsonStr
|
|
||||||
* @param parametrized
|
|
||||||
* @param parameterClasses
|
|
||||||
* @param <T>
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static <T> T readValue(String jsonStr, Class<?> parametrized, Class<?>... parameterClasses) {
|
|
||||||
try {
|
|
||||||
JavaType javaType = getInstance().getTypeFactory().constructParametricType(parametrized, parameterClasses);
|
|
||||||
return getInstance().readValue(jsonStr, javaType);
|
|
||||||
} catch (JsonParseException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
} catch (JsonMappingException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,134 +0,0 @@
|
|||||||
package com.xxl.job.admin.core.util;
|
|
||||||
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* local cache tool
|
|
||||||
*
|
|
||||||
* @author xuxueli 2018-01-22 21:37:34
|
|
||||||
*/
|
|
||||||
public class LocalCacheUtil {
|
|
||||||
|
|
||||||
private static ConcurrentMap<String, LocalCacheData> cacheRepository = new ConcurrentHashMap<String, LocalCacheData>(); // 类型建议用抽象父类,兼容性更好;
|
|
||||||
|
|
||||||
private static class LocalCacheData {
|
|
||||||
private String key;
|
|
||||||
private Object val;
|
|
||||||
private long timeoutTime;
|
|
||||||
|
|
||||||
public LocalCacheData() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public LocalCacheData(String key, Object val, long timeoutTime) {
|
|
||||||
this.key = key;
|
|
||||||
this.val = val;
|
|
||||||
this.timeoutTime = timeoutTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getKey() {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKey(String key) {
|
|
||||||
this.key = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getVal() {
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setVal(Object val) {
|
|
||||||
this.val = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTimeoutTime() {
|
|
||||||
return timeoutTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTimeoutTime(long timeoutTime) {
|
|
||||||
this.timeoutTime = timeoutTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set cache
|
|
||||||
*
|
|
||||||
* @param key
|
|
||||||
* @param val
|
|
||||||
* @param cacheTime
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static boolean set(String key, Object val, long cacheTime) {
|
|
||||||
|
|
||||||
// clean timeout cache, before set new cache (avoid cache too much)
|
|
||||||
cleanTimeoutCache();
|
|
||||||
|
|
||||||
// set new cache
|
|
||||||
if (key == null || key.trim().length() == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (val == null) {
|
|
||||||
remove(key);
|
|
||||||
}
|
|
||||||
if (cacheTime <= 0) {
|
|
||||||
remove(key);
|
|
||||||
}
|
|
||||||
long timeoutTime = System.currentTimeMillis() + cacheTime;
|
|
||||||
LocalCacheData localCacheData = new LocalCacheData(key, val, timeoutTime);
|
|
||||||
cacheRepository.put(localCacheData.getKey(), localCacheData);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* remove cache
|
|
||||||
*
|
|
||||||
* @param key
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static boolean remove(String key) {
|
|
||||||
if (key == null || key.trim().length() == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
cacheRepository.remove(key);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get cache
|
|
||||||
*
|
|
||||||
* @param key
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static Object get(String key) {
|
|
||||||
if (key == null || key.trim().length() == 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
LocalCacheData localCacheData = cacheRepository.get(key);
|
|
||||||
if (localCacheData != null && System.currentTimeMillis() < localCacheData.getTimeoutTime()) {
|
|
||||||
return localCacheData.getVal();
|
|
||||||
} else {
|
|
||||||
remove(key);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clean timeout cache
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static boolean cleanTimeoutCache() {
|
|
||||||
if (!cacheRepository.keySet().isEmpty()) {
|
|
||||||
for (String key : cacheRepository.keySet()) {
|
|
||||||
LocalCacheData localCacheData = cacheRepository.get(key);
|
|
||||||
if (localCacheData != null && System.currentTimeMillis() >= localCacheData.getTimeoutTime()) {
|
|
||||||
cacheRepository.remove(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
package com.xxl.job.admin.dao;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobGroup;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by xuxueli on 16/9/30.
|
|
||||||
*/
|
|
||||||
@Mapper
|
|
||||||
public interface XxlJobGroupDao {
|
|
||||||
|
|
||||||
public List<XxlJobGroup> findAll();
|
|
||||||
|
|
||||||
public List<XxlJobGroup> findByAddressType(@Param("addressType") int addressType);
|
|
||||||
|
|
||||||
public int save(XxlJobGroup xxlJobGroup);
|
|
||||||
|
|
||||||
public int update(XxlJobGroup xxlJobGroup);
|
|
||||||
|
|
||||||
public int remove(@Param("id") int id);
|
|
||||||
|
|
||||||
public XxlJobGroup load(@Param("id") int id);
|
|
||||||
|
|
||||||
public List<XxlJobGroup> pageList(@Param("offset") int offset,
|
|
||||||
@Param("pagesize") int pagesize,
|
|
||||||
@Param("appname") String appname,
|
|
||||||
@Param("title") String title);
|
|
||||||
|
|
||||||
public int pageListCount(@Param("offset") int offset,
|
|
||||||
@Param("pagesize") int pagesize,
|
|
||||||
@Param("appname") String appname,
|
|
||||||
@Param("title") String title);
|
|
||||||
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
package com.xxl.job.admin.dao;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* job info
|
|
||||||
*
|
|
||||||
* @author xuxueli 2016-1-12 18:03:45
|
|
||||||
*/
|
|
||||||
@Mapper
|
|
||||||
public interface XxlJobInfoDao {
|
|
||||||
|
|
||||||
public List<XxlJobInfo> pageList(@Param("offset") int offset,
|
|
||||||
@Param("pagesize") int pagesize,
|
|
||||||
@Param("jobGroup") int jobGroup,
|
|
||||||
@Param("triggerStatus") int triggerStatus,
|
|
||||||
@Param("jobDesc") String jobDesc,
|
|
||||||
@Param("executorHandler") String executorHandler,
|
|
||||||
@Param("author") String author);
|
|
||||||
|
|
||||||
public int pageListCount(@Param("offset") int offset,
|
|
||||||
@Param("pagesize") int pagesize,
|
|
||||||
@Param("jobGroup") int jobGroup,
|
|
||||||
@Param("triggerStatus") int triggerStatus,
|
|
||||||
@Param("jobDesc") String jobDesc,
|
|
||||||
@Param("executorHandler") String executorHandler,
|
|
||||||
@Param("author") String author);
|
|
||||||
|
|
||||||
public int save(XxlJobInfo info);
|
|
||||||
|
|
||||||
public XxlJobInfo loadById(@Param("id") int id);
|
|
||||||
|
|
||||||
public int update(XxlJobInfo xxlJobInfo);
|
|
||||||
|
|
||||||
public int delete(@Param("id") long id);
|
|
||||||
|
|
||||||
public List<XxlJobInfo> getJobsByGroup(@Param("jobGroup") int jobGroup);
|
|
||||||
|
|
||||||
public int findAllCount();
|
|
||||||
|
|
||||||
public List<XxlJobInfo> scheduleJobQuery(@Param("maxNextTime") long maxNextTime, @Param("pagesize") int pagesize);
|
|
||||||
|
|
||||||
public int scheduleUpdate(XxlJobInfo xxlJobInfo);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
package com.xxl.job.admin.dao;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobLog;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* job log
|
|
||||||
*
|
|
||||||
* @author xuxueli 2016-1-12 18:03:06
|
|
||||||
*/
|
|
||||||
@Mapper
|
|
||||||
public interface XxlJobLogDao {
|
|
||||||
|
|
||||||
// exist jobId not use jobGroup, not exist use jobGroup
|
|
||||||
public List<XxlJobLog> pageList(@Param("offset") int offset,
|
|
||||||
@Param("pagesize") int pagesize,
|
|
||||||
@Param("jobGroup") int jobGroup,
|
|
||||||
@Param("jobId") int jobId,
|
|
||||||
@Param("triggerTimeStart") Date triggerTimeStart,
|
|
||||||
@Param("triggerTimeEnd") Date triggerTimeEnd,
|
|
||||||
@Param("logStatus") int logStatus);
|
|
||||||
|
|
||||||
public int pageListCount(@Param("offset") int offset,
|
|
||||||
@Param("pagesize") int pagesize,
|
|
||||||
@Param("jobGroup") int jobGroup,
|
|
||||||
@Param("jobId") int jobId,
|
|
||||||
@Param("triggerTimeStart") Date triggerTimeStart,
|
|
||||||
@Param("triggerTimeEnd") Date triggerTimeEnd,
|
|
||||||
@Param("logStatus") int logStatus);
|
|
||||||
|
|
||||||
public XxlJobLog load(@Param("id") long id);
|
|
||||||
|
|
||||||
public long save(XxlJobLog xxlJobLog);
|
|
||||||
|
|
||||||
public int updateTriggerInfo(XxlJobLog xxlJobLog);
|
|
||||||
|
|
||||||
public int updateHandleInfo(XxlJobLog xxlJobLog);
|
|
||||||
|
|
||||||
public int delete(@Param("jobId") int jobId);
|
|
||||||
|
|
||||||
public Map<String, Object> findLogReport(@Param("from") Date from,
|
|
||||||
@Param("to") Date to);
|
|
||||||
|
|
||||||
public List<Long> findClearLogIds(@Param("jobGroup") int jobGroup,
|
|
||||||
@Param("jobId") int jobId,
|
|
||||||
@Param("clearBeforeTime") Date clearBeforeTime,
|
|
||||||
@Param("clearBeforeNum") int clearBeforeNum,
|
|
||||||
@Param("pagesize") int pagesize);
|
|
||||||
|
|
||||||
public int clearLog(@Param("logIds") List<Long> logIds);
|
|
||||||
|
|
||||||
public List<Long> findFailJobLogIds(@Param("pagesize") int pagesize);
|
|
||||||
|
|
||||||
public int updateAlarmStatus(@Param("logId") long logId,
|
|
||||||
@Param("oldAlarmStatus") int oldAlarmStatus,
|
|
||||||
@Param("newAlarmStatus") int newAlarmStatus);
|
|
||||||
|
|
||||||
public List<Long> findLostJobIds(@Param("losedTime") Date losedTime);
|
|
||||||
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package com.xxl.job.admin.dao;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobLogGlue;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* job log for glue
|
|
||||||
*
|
|
||||||
* @author xuxueli 2016-5-19 18:04:56
|
|
||||||
*/
|
|
||||||
@Mapper
|
|
||||||
public interface XxlJobLogGlueDao {
|
|
||||||
|
|
||||||
public int save(XxlJobLogGlue xxlJobLogGlue);
|
|
||||||
|
|
||||||
public List<XxlJobLogGlue> findByJobId(@Param("jobId") int jobId);
|
|
||||||
|
|
||||||
public int removeOld(@Param("jobId") int jobId, @Param("limit") int limit);
|
|
||||||
|
|
||||||
public int deleteByJobId(@Param("jobId") int jobId);
|
|
||||||
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
package com.xxl.job.admin.dao;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobLogReport;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* job log
|
|
||||||
*
|
|
||||||
* @author xuxueli 2019-11-22
|
|
||||||
*/
|
|
||||||
@Mapper
|
|
||||||
public interface XxlJobLogReportDao {
|
|
||||||
|
|
||||||
public int save(XxlJobLogReport xxlJobLogReport);
|
|
||||||
|
|
||||||
public int update(XxlJobLogReport xxlJobLogReport);
|
|
||||||
|
|
||||||
public List<XxlJobLogReport> queryLogReport(@Param("triggerDayFrom") Date triggerDayFrom,
|
|
||||||
@Param("triggerDayTo") Date triggerDayTo);
|
|
||||||
|
|
||||||
public XxlJobLogReport queryLogReportTotal();
|
|
||||||
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
package com.xxl.job.admin.dao;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobRegistry;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by xuxueli on 16/9/30.
|
|
||||||
*/
|
|
||||||
@Mapper
|
|
||||||
public interface XxlJobRegistryDao {
|
|
||||||
|
|
||||||
public List<Integer> findDead(@Param("timeout") int timeout,
|
|
||||||
@Param("nowTime") Date nowTime);
|
|
||||||
|
|
||||||
public int removeDead(@Param("ids") List<Integer> ids);
|
|
||||||
|
|
||||||
public List<XxlJobRegistry> findAll(@Param("timeout") int timeout,
|
|
||||||
@Param("nowTime") Date nowTime);
|
|
||||||
|
|
||||||
public int registryUpdate(@Param("registryGroup") String registryGroup,
|
|
||||||
@Param("registryKey") String registryKey,
|
|
||||||
@Param("registryValue") String registryValue,
|
|
||||||
@Param("updateTime") Date updateTime);
|
|
||||||
|
|
||||||
public int registrySave(@Param("registryGroup") String registryGroup,
|
|
||||||
@Param("registryKey") String registryKey,
|
|
||||||
@Param("registryValue") String registryValue,
|
|
||||||
@Param("updateTime") Date updateTime);
|
|
||||||
|
|
||||||
public int registryDelete(@Param("registryGroup") String registryGroup,
|
|
||||||
@Param("registryKey") String registryKey,
|
|
||||||
@Param("registryValue") String registryValue);
|
|
||||||
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
package com.xxl.job.admin.dao;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobUser;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author xuxueli 2019-05-04 16:44:59
|
|
||||||
*/
|
|
||||||
@Mapper
|
|
||||||
public interface XxlJobUserDao {
|
|
||||||
|
|
||||||
public List<XxlJobUser> pageList(@Param("offset") int offset,
|
|
||||||
@Param("pagesize") int pagesize,
|
|
||||||
@Param("username") String username,
|
|
||||||
@Param("role") int role);
|
|
||||||
|
|
||||||
public int pageListCount(@Param("offset") int offset,
|
|
||||||
@Param("pagesize") int pagesize,
|
|
||||||
@Param("username") String username,
|
|
||||||
@Param("role") int role);
|
|
||||||
|
|
||||||
public XxlJobUser loadByUserName(@Param("username") String username);
|
|
||||||
|
|
||||||
public int save(XxlJobUser xxlJobUser);
|
|
||||||
|
|
||||||
public int update(XxlJobUser xxlJobUser);
|
|
||||||
|
|
||||||
public int delete(@Param("id") int id);
|
|
||||||
|
|
||||||
}
|
|
@ -1,108 +0,0 @@
|
|||||||
package com.xxl.job.admin.service;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobUser;
|
|
||||||
import com.xxl.job.admin.core.util.CookieUtil;
|
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
|
||||||
import com.xxl.job.admin.core.util.JacksonUtil;
|
|
||||||
import com.xxl.job.admin.dao.XxlJobUserDao;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.util.DigestUtils;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author xuxueli 2019-05-04 22:13:264
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
public class LoginService {
|
|
||||||
|
|
||||||
public static final String LOGIN_IDENTITY_KEY = "XXL_JOB_LOGIN_IDENTITY";
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private XxlJobUserDao xxlJobUserDao;
|
|
||||||
|
|
||||||
|
|
||||||
private String makeToken(XxlJobUser xxlJobUser) {
|
|
||||||
String tokenJson = JacksonUtil.writeValueAsString(xxlJobUser);
|
|
||||||
String tokenHex = new BigInteger(tokenJson.getBytes()).toString(16);
|
|
||||||
return tokenHex;
|
|
||||||
}
|
|
||||||
|
|
||||||
private XxlJobUser parseToken(String tokenHex) {
|
|
||||||
XxlJobUser xxlJobUser = null;
|
|
||||||
if (tokenHex != null) {
|
|
||||||
String tokenJson = new String(new BigInteger(tokenHex, 16).toByteArray()); // username_password(md5)
|
|
||||||
xxlJobUser = JacksonUtil.readValue(tokenJson, XxlJobUser.class);
|
|
||||||
}
|
|
||||||
return xxlJobUser;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public ReturnT<String> login(HttpServletRequest request, HttpServletResponse response, String username, String password, boolean ifRemember) {
|
|
||||||
|
|
||||||
// param
|
|
||||||
if (username == null || username.trim().length() == 0 || password == null || password.trim().length() == 0) {
|
|
||||||
return new ReturnT<String>(500, I18nUtil.getString("login_param_empty"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// valid passowrd
|
|
||||||
XxlJobUser xxlJobUser = xxlJobUserDao.loadByUserName(username);
|
|
||||||
if (xxlJobUser == null) {
|
|
||||||
return new ReturnT<String>(500, I18nUtil.getString("login_param_unvalid"));
|
|
||||||
}
|
|
||||||
String passwordMd5 = DigestUtils.md5DigestAsHex(password.getBytes());
|
|
||||||
if (!passwordMd5.equals(xxlJobUser.getPassword())) {
|
|
||||||
return new ReturnT<String>(500, I18nUtil.getString("login_param_unvalid"));
|
|
||||||
}
|
|
||||||
|
|
||||||
String loginToken = makeToken(xxlJobUser);
|
|
||||||
|
|
||||||
// do login
|
|
||||||
CookieUtil.set(response, LOGIN_IDENTITY_KEY, loginToken, ifRemember);
|
|
||||||
return ReturnT.SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* logout
|
|
||||||
*
|
|
||||||
* @param request
|
|
||||||
* @param response
|
|
||||||
*/
|
|
||||||
public ReturnT<String> logout(HttpServletRequest request, HttpServletResponse response) {
|
|
||||||
CookieUtil.remove(request, response, LOGIN_IDENTITY_KEY);
|
|
||||||
return ReturnT.SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* logout
|
|
||||||
*
|
|
||||||
* @param request
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public XxlJobUser ifLogin(HttpServletRequest request, HttpServletResponse response) {
|
|
||||||
String cookieToken = CookieUtil.getValue(request, LOGIN_IDENTITY_KEY);
|
|
||||||
if (cookieToken != null) {
|
|
||||||
XxlJobUser cookieUser = null;
|
|
||||||
try {
|
|
||||||
cookieUser = parseToken(cookieToken);
|
|
||||||
} catch (Exception e) {
|
|
||||||
logout(request, response);
|
|
||||||
}
|
|
||||||
if (cookieUser != null) {
|
|
||||||
XxlJobUser dbUser = xxlJobUserDao.loadByUserName(cookieUser.getUsername());
|
|
||||||
if (dbUser != null) {
|
|
||||||
if (cookieUser.getPassword().equals(dbUser.getPassword())) {
|
|
||||||
return dbUser;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,87 +0,0 @@
|
|||||||
package com.xxl.job.admin.service;
|
|
||||||
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* core job action for xxl-job
|
|
||||||
*
|
|
||||||
* @author xuxueli 2016-5-28 15:30:33
|
|
||||||
*/
|
|
||||||
public interface XxlJobService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* page list
|
|
||||||
*
|
|
||||||
* @param start
|
|
||||||
* @param length
|
|
||||||
* @param jobGroup
|
|
||||||
* @param jobDesc
|
|
||||||
* @param executorHandler
|
|
||||||
* @param author
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Map<String, Object> pageList(int start, int length, int jobGroup, int triggerStatus, String jobDesc, String executorHandler, String author);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* add job
|
|
||||||
*
|
|
||||||
* @param jobInfo
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public ReturnT<String> add(XxlJobInfo jobInfo);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* update job
|
|
||||||
*
|
|
||||||
* @param jobInfo
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public ReturnT<String> update(XxlJobInfo jobInfo);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* remove job
|
|
||||||
* *
|
|
||||||
*
|
|
||||||
* @param id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public ReturnT<String> remove(int id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* start job
|
|
||||||
*
|
|
||||||
* @param id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public ReturnT<String> start(int id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* stop job
|
|
||||||
*
|
|
||||||
* @param id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public ReturnT<String> stop(int id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* dashboard info
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Map<String, Object> dashboardInfo();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* chart info
|
|
||||||
*
|
|
||||||
* @param startDate
|
|
||||||
* @param endDate
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public ReturnT<Map<String, Object>> chartInfo(Date startDate, Date endDate);
|
|
||||||
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
package com.xxl.job.admin.service.impl;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.thread.JobCompleteHelper;
|
|
||||||
import com.xxl.job.admin.core.thread.JobRegistryHelper;
|
|
||||||
import com.xxl.job.core.biz.AdminBiz;
|
|
||||||
import com.xxl.job.core.biz.model.HandleCallbackParam;
|
|
||||||
import com.xxl.job.core.biz.model.RegistryParam;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author xuxueli 2017-07-27 21:54:20
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
public class AdminBizImpl implements AdminBiz {
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReturnT<String> callback(List<HandleCallbackParam> callbackParamList) {
|
|
||||||
return JobCompleteHelper.getInstance().callback(callbackParamList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReturnT<String> registry(RegistryParam registryParam) {
|
|
||||||
return JobRegistryHelper.getInstance().registry(registryParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReturnT<String> registryRemove(RegistryParam registryParam) {
|
|
||||||
return JobRegistryHelper.getInstance().registryRemove(registryParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,435 +0,0 @@
|
|||||||
package com.xxl.job.admin.service.impl;
|
|
||||||
|
|
||||||
import com.xxl.job.admin.core.cron.CronExpression;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobGroup;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobLogReport;
|
|
||||||
import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;
|
|
||||||
import com.xxl.job.admin.core.scheduler.MisfireStrategyEnum;
|
|
||||||
import com.xxl.job.admin.core.scheduler.ScheduleTypeEnum;
|
|
||||||
import com.xxl.job.admin.core.thread.JobScheduleHelper;
|
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
|
||||||
import com.xxl.job.admin.dao.*;
|
|
||||||
import com.xxl.job.admin.service.XxlJobService;
|
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import com.xxl.job.core.enums.ExecutorBlockStrategyEnum;
|
|
||||||
import com.xxl.job.core.glue.GlueTypeEnum;
|
|
||||||
import com.xxl.job.core.util.DateUtil;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import java.text.MessageFormat;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* core job action for xxl-job
|
|
||||||
*
|
|
||||||
* @author xuxueli 2016-5-28 15:30:33
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
public class XxlJobServiceImpl implements XxlJobService {
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(XxlJobServiceImpl.class);
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private XxlJobGroupDao xxlJobGroupDao;
|
|
||||||
@Resource
|
|
||||||
private XxlJobInfoDao xxlJobInfoDao;
|
|
||||||
@Resource
|
|
||||||
public XxlJobLogDao xxlJobLogDao;
|
|
||||||
@Resource
|
|
||||||
private XxlJobLogGlueDao xxlJobLogGlueDao;
|
|
||||||
@Resource
|
|
||||||
private XxlJobLogReportDao xxlJobLogReportDao;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Object> pageList(int start, int length, int jobGroup, int triggerStatus, String jobDesc, String executorHandler, String author) {
|
|
||||||
|
|
||||||
// page list
|
|
||||||
List<XxlJobInfo> list = xxlJobInfoDao.pageList(start, length, jobGroup, triggerStatus, jobDesc, executorHandler, author);
|
|
||||||
int list_count = xxlJobInfoDao.pageListCount(start, length, jobGroup, triggerStatus, jobDesc, executorHandler, author);
|
|
||||||
|
|
||||||
// package result
|
|
||||||
Map<String, Object> maps = new HashMap<String, Object>();
|
|
||||||
maps.put("recordsTotal", list_count); // 总记录数
|
|
||||||
maps.put("recordsFiltered", list_count); // 过滤后的总记录数
|
|
||||||
maps.put("data", list); // 分页列表
|
|
||||||
return maps;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReturnT<String> add(XxlJobInfo jobInfo) {
|
|
||||||
|
|
||||||
// valid base
|
|
||||||
XxlJobGroup group = xxlJobGroupDao.load(jobInfo.getJobGroup());
|
|
||||||
if (group == null) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_choose") + I18nUtil.getString("jobinfo_field_jobgroup")));
|
|
||||||
}
|
|
||||||
if (jobInfo.getJobDesc() == null || jobInfo.getJobDesc().trim().length() == 0) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input") + I18nUtil.getString("jobinfo_field_jobdesc")));
|
|
||||||
}
|
|
||||||
if (jobInfo.getAuthor() == null || jobInfo.getAuthor().trim().length() == 0) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input") + I18nUtil.getString("jobinfo_field_author")));
|
|
||||||
}
|
|
||||||
|
|
||||||
// valid trigger
|
|
||||||
ScheduleTypeEnum scheduleTypeEnum = ScheduleTypeEnum.match(jobInfo.getScheduleType(), null);
|
|
||||||
if (scheduleTypeEnum == null) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")));
|
|
||||||
}
|
|
||||||
if (scheduleTypeEnum == ScheduleTypeEnum.CRON) {
|
|
||||||
if (jobInfo.getScheduleConf() == null || !CronExpression.isValidExpression(jobInfo.getScheduleConf())) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, "Cron" + I18nUtil.getString("system_unvalid"));
|
|
||||||
}
|
|
||||||
} else if (scheduleTypeEnum == ScheduleTypeEnum.FIX_RATE/* || scheduleTypeEnum == ScheduleTypeEnum.FIX_DELAY*/) {
|
|
||||||
if (jobInfo.getScheduleConf() == null) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")));
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
int fixSecond = Integer.valueOf(jobInfo.getScheduleConf());
|
|
||||||
if (fixSecond < 1) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")));
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// valid job
|
|
||||||
if (GlueTypeEnum.match(jobInfo.getGlueType()) == null) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_gluetype") + I18nUtil.getString("system_unvalid")));
|
|
||||||
}
|
|
||||||
if (GlueTypeEnum.BEAN == GlueTypeEnum.match(jobInfo.getGlueType()) && (jobInfo.getExecutorHandler() == null || jobInfo.getExecutorHandler().trim().length() == 0)) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input") + "JobHandler"));
|
|
||||||
}
|
|
||||||
// 》fix "\r" in shell
|
|
||||||
if (GlueTypeEnum.GLUE_SHELL == GlueTypeEnum.match(jobInfo.getGlueType()) && jobInfo.getGlueSource() != null) {
|
|
||||||
jobInfo.setGlueSource(jobInfo.getGlueSource().replaceAll("\r", ""));
|
|
||||||
}
|
|
||||||
|
|
||||||
// valid advanced
|
|
||||||
if (ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null) == null) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_executorRouteStrategy") + I18nUtil.getString("system_unvalid")));
|
|
||||||
}
|
|
||||||
if (MisfireStrategyEnum.match(jobInfo.getMisfireStrategy(), null) == null) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("misfire_strategy") + I18nUtil.getString("system_unvalid")));
|
|
||||||
}
|
|
||||||
if (ExecutorBlockStrategyEnum.match(jobInfo.getExecutorBlockStrategy(), null) == null) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_executorBlockStrategy") + I18nUtil.getString("system_unvalid")));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 》ChildJobId valid
|
|
||||||
if (jobInfo.getChildJobId() != null && jobInfo.getChildJobId().trim().length() > 0) {
|
|
||||||
String[] childJobIds = jobInfo.getChildJobId().split(",");
|
|
||||||
for (String childJobIdItem : childJobIds) {
|
|
||||||
if (childJobIdItem != null && childJobIdItem.trim().length() > 0 && isNumeric(childJobIdItem)) {
|
|
||||||
XxlJobInfo childJobInfo = xxlJobInfoDao.loadById(Integer.parseInt(childJobIdItem));
|
|
||||||
if (childJobInfo == null) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE,
|
|
||||||
MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId") + "({0})" + I18nUtil.getString("system_not_found")), childJobIdItem));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE,
|
|
||||||
MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId") + "({0})" + I18nUtil.getString("system_unvalid")), childJobIdItem));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// join , avoid "xxx,,"
|
|
||||||
String temp = "";
|
|
||||||
for (String item : childJobIds) {
|
|
||||||
temp += item + ",";
|
|
||||||
}
|
|
||||||
temp = temp.substring(0, temp.length() - 1);
|
|
||||||
|
|
||||||
jobInfo.setChildJobId(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add in db
|
|
||||||
jobInfo.setAddTime(new Date());
|
|
||||||
jobInfo.setUpdateTime(new Date());
|
|
||||||
jobInfo.setGlueUpdatetime(new Date());
|
|
||||||
xxlJobInfoDao.save(jobInfo);
|
|
||||||
if (jobInfo.getId() < 1) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_add") + I18nUtil.getString("system_fail")));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ReturnT<String>(String.valueOf(jobInfo.getId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isNumeric(String str) {
|
|
||||||
try {
|
|
||||||
int result = Integer.valueOf(str);
|
|
||||||
return true;
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReturnT<String> update(XxlJobInfo jobInfo) {
|
|
||||||
|
|
||||||
// valid base
|
|
||||||
if (jobInfo.getJobDesc() == null || jobInfo.getJobDesc().trim().length() == 0) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input") + I18nUtil.getString("jobinfo_field_jobdesc")));
|
|
||||||
}
|
|
||||||
if (jobInfo.getAuthor() == null || jobInfo.getAuthor().trim().length() == 0) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input") + I18nUtil.getString("jobinfo_field_author")));
|
|
||||||
}
|
|
||||||
|
|
||||||
// valid trigger
|
|
||||||
ScheduleTypeEnum scheduleTypeEnum = ScheduleTypeEnum.match(jobInfo.getScheduleType(), null);
|
|
||||||
if (scheduleTypeEnum == null) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")));
|
|
||||||
}
|
|
||||||
if (scheduleTypeEnum == ScheduleTypeEnum.CRON) {
|
|
||||||
if (jobInfo.getScheduleConf() == null || !CronExpression.isValidExpression(jobInfo.getScheduleConf())) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, "Cron" + I18nUtil.getString("system_unvalid"));
|
|
||||||
}
|
|
||||||
} else if (scheduleTypeEnum == ScheduleTypeEnum.FIX_RATE /*|| scheduleTypeEnum == ScheduleTypeEnum.FIX_DELAY*/) {
|
|
||||||
if (jobInfo.getScheduleConf() == null) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")));
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
int fixSecond = Integer.valueOf(jobInfo.getScheduleConf());
|
|
||||||
if (fixSecond < 1) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")));
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// valid advanced
|
|
||||||
if (ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null) == null) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_executorRouteStrategy") + I18nUtil.getString("system_unvalid")));
|
|
||||||
}
|
|
||||||
if (MisfireStrategyEnum.match(jobInfo.getMisfireStrategy(), null) == null) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("misfire_strategy") + I18nUtil.getString("system_unvalid")));
|
|
||||||
}
|
|
||||||
if (ExecutorBlockStrategyEnum.match(jobInfo.getExecutorBlockStrategy(), null) == null) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_executorBlockStrategy") + I18nUtil.getString("system_unvalid")));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 》ChildJobId valid
|
|
||||||
if (jobInfo.getChildJobId() != null && jobInfo.getChildJobId().trim().length() > 0) {
|
|
||||||
String[] childJobIds = jobInfo.getChildJobId().split(",");
|
|
||||||
for (String childJobIdItem : childJobIds) {
|
|
||||||
if (childJobIdItem != null && childJobIdItem.trim().length() > 0 && isNumeric(childJobIdItem)) {
|
|
||||||
XxlJobInfo childJobInfo = xxlJobInfoDao.loadById(Integer.parseInt(childJobIdItem));
|
|
||||||
if (childJobInfo == null) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE,
|
|
||||||
MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId") + "({0})" + I18nUtil.getString("system_not_found")), childJobIdItem));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE,
|
|
||||||
MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId") + "({0})" + I18nUtil.getString("system_unvalid")), childJobIdItem));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// join , avoid "xxx,,"
|
|
||||||
String temp = "";
|
|
||||||
for (String item : childJobIds) {
|
|
||||||
temp += item + ",";
|
|
||||||
}
|
|
||||||
temp = temp.substring(0, temp.length() - 1);
|
|
||||||
|
|
||||||
jobInfo.setChildJobId(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// group valid
|
|
||||||
XxlJobGroup jobGroup = xxlJobGroupDao.load(jobInfo.getJobGroup());
|
|
||||||
if (jobGroup == null) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_jobgroup") + I18nUtil.getString("system_unvalid")));
|
|
||||||
}
|
|
||||||
|
|
||||||
// stage job info
|
|
||||||
XxlJobInfo exists_jobInfo = xxlJobInfoDao.loadById(jobInfo.getId());
|
|
||||||
if (exists_jobInfo == null) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_id") + I18nUtil.getString("system_not_found")));
|
|
||||||
}
|
|
||||||
|
|
||||||
// next trigger time (5s后生效,避开预读周期)
|
|
||||||
long nextTriggerTime = exists_jobInfo.getTriggerNextTime();
|
|
||||||
boolean scheduleDataNotChanged = jobInfo.getScheduleType().equals(exists_jobInfo.getScheduleType()) && jobInfo.getScheduleConf().equals(exists_jobInfo.getScheduleConf());
|
|
||||||
if (exists_jobInfo.getTriggerStatus() == 1 && !scheduleDataNotChanged) {
|
|
||||||
try {
|
|
||||||
Date nextValidTime = JobScheduleHelper.generateNextValidTime(jobInfo, new Date(System.currentTimeMillis() + JobScheduleHelper.PRE_READ_MS));
|
|
||||||
if (nextValidTime == null) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")));
|
|
||||||
}
|
|
||||||
nextTriggerTime = nextValidTime.getTime();
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exists_jobInfo.setJobGroup(jobInfo.getJobGroup());
|
|
||||||
exists_jobInfo.setJobDesc(jobInfo.getJobDesc());
|
|
||||||
exists_jobInfo.setAuthor(jobInfo.getAuthor());
|
|
||||||
exists_jobInfo.setAlarmEmail(jobInfo.getAlarmEmail());
|
|
||||||
exists_jobInfo.setScheduleType(jobInfo.getScheduleType());
|
|
||||||
exists_jobInfo.setScheduleConf(jobInfo.getScheduleConf());
|
|
||||||
exists_jobInfo.setMisfireStrategy(jobInfo.getMisfireStrategy());
|
|
||||||
exists_jobInfo.setExecutorRouteStrategy(jobInfo.getExecutorRouteStrategy());
|
|
||||||
exists_jobInfo.setExecutorHandler(jobInfo.getExecutorHandler());
|
|
||||||
exists_jobInfo.setExecutorParam(jobInfo.getExecutorParam());
|
|
||||||
exists_jobInfo.setExecutorBlockStrategy(jobInfo.getExecutorBlockStrategy());
|
|
||||||
exists_jobInfo.setExecutorTimeout(jobInfo.getExecutorTimeout());
|
|
||||||
exists_jobInfo.setExecutorFailRetryCount(jobInfo.getExecutorFailRetryCount());
|
|
||||||
exists_jobInfo.setChildJobId(jobInfo.getChildJobId());
|
|
||||||
exists_jobInfo.setTriggerNextTime(nextTriggerTime);
|
|
||||||
|
|
||||||
exists_jobInfo.setUpdateTime(new Date());
|
|
||||||
xxlJobInfoDao.update(exists_jobInfo);
|
|
||||||
|
|
||||||
|
|
||||||
return ReturnT.SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReturnT<String> remove(int id) {
|
|
||||||
XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);
|
|
||||||
if (xxlJobInfo == null) {
|
|
||||||
return ReturnT.SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
xxlJobInfoDao.delete(id);
|
|
||||||
xxlJobLogDao.delete(id);
|
|
||||||
xxlJobLogGlueDao.deleteByJobId(id);
|
|
||||||
return ReturnT.SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReturnT<String> start(int id) {
|
|
||||||
XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);
|
|
||||||
|
|
||||||
// valid
|
|
||||||
ScheduleTypeEnum scheduleTypeEnum = ScheduleTypeEnum.match(xxlJobInfo.getScheduleType(), ScheduleTypeEnum.NONE);
|
|
||||||
if (ScheduleTypeEnum.NONE == scheduleTypeEnum) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type_none_limit_start")));
|
|
||||||
}
|
|
||||||
|
|
||||||
// next trigger time (5s后生效,避开预读周期)
|
|
||||||
long nextTriggerTime = 0;
|
|
||||||
try {
|
|
||||||
Date nextValidTime = JobScheduleHelper.generateNextValidTime(xxlJobInfo, new Date(System.currentTimeMillis() + JobScheduleHelper.PRE_READ_MS));
|
|
||||||
if (nextValidTime == null) {
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")));
|
|
||||||
}
|
|
||||||
nextTriggerTime = nextValidTime.getTime();
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")));
|
|
||||||
}
|
|
||||||
|
|
||||||
xxlJobInfo.setTriggerStatus(1);
|
|
||||||
xxlJobInfo.setTriggerLastTime(0);
|
|
||||||
xxlJobInfo.setTriggerNextTime(nextTriggerTime);
|
|
||||||
|
|
||||||
xxlJobInfo.setUpdateTime(new Date());
|
|
||||||
xxlJobInfoDao.update(xxlJobInfo);
|
|
||||||
return ReturnT.SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReturnT<String> stop(int id) {
|
|
||||||
XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);
|
|
||||||
|
|
||||||
xxlJobInfo.setTriggerStatus(0);
|
|
||||||
xxlJobInfo.setTriggerLastTime(0);
|
|
||||||
xxlJobInfo.setTriggerNextTime(0);
|
|
||||||
|
|
||||||
xxlJobInfo.setUpdateTime(new Date());
|
|
||||||
xxlJobInfoDao.update(xxlJobInfo);
|
|
||||||
return ReturnT.SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Object> dashboardInfo() {
|
|
||||||
|
|
||||||
int jobInfoCount = xxlJobInfoDao.findAllCount();
|
|
||||||
int jobLogCount = 0;
|
|
||||||
int jobLogSuccessCount = 0;
|
|
||||||
XxlJobLogReport xxlJobLogReport = xxlJobLogReportDao.queryLogReportTotal();
|
|
||||||
if (xxlJobLogReport != null) {
|
|
||||||
jobLogCount = xxlJobLogReport.getRunningCount() + xxlJobLogReport.getSucCount() + xxlJobLogReport.getFailCount();
|
|
||||||
jobLogSuccessCount = xxlJobLogReport.getSucCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
// executor count
|
|
||||||
Set<String> executorAddressSet = new HashSet<String>();
|
|
||||||
List<XxlJobGroup> groupList = xxlJobGroupDao.findAll();
|
|
||||||
|
|
||||||
if (groupList != null && !groupList.isEmpty()) {
|
|
||||||
for (XxlJobGroup group : groupList) {
|
|
||||||
if (group.getRegistryList() != null && !group.getRegistryList().isEmpty()) {
|
|
||||||
executorAddressSet.addAll(group.getRegistryList());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int executorCount = executorAddressSet.size();
|
|
||||||
|
|
||||||
Map<String, Object> dashboardMap = new HashMap<String, Object>();
|
|
||||||
dashboardMap.put("jobInfoCount", jobInfoCount);
|
|
||||||
dashboardMap.put("jobLogCount", jobLogCount);
|
|
||||||
dashboardMap.put("jobLogSuccessCount", jobLogSuccessCount);
|
|
||||||
dashboardMap.put("executorCount", executorCount);
|
|
||||||
return dashboardMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReturnT<Map<String, Object>> chartInfo(Date startDate, Date endDate) {
|
|
||||||
|
|
||||||
// process
|
|
||||||
List<String> triggerDayList = new ArrayList<String>();
|
|
||||||
List<Integer> triggerDayCountRunningList = new ArrayList<Integer>();
|
|
||||||
List<Integer> triggerDayCountSucList = new ArrayList<Integer>();
|
|
||||||
List<Integer> triggerDayCountFailList = new ArrayList<Integer>();
|
|
||||||
int triggerCountRunningTotal = 0;
|
|
||||||
int triggerCountSucTotal = 0;
|
|
||||||
int triggerCountFailTotal = 0;
|
|
||||||
|
|
||||||
List<XxlJobLogReport> logReportList = xxlJobLogReportDao.queryLogReport(startDate, endDate);
|
|
||||||
|
|
||||||
if (logReportList != null && logReportList.size() > 0) {
|
|
||||||
for (XxlJobLogReport item : logReportList) {
|
|
||||||
String day = DateUtil.formatDate(item.getTriggerDay());
|
|
||||||
int triggerDayCountRunning = item.getRunningCount();
|
|
||||||
int triggerDayCountSuc = item.getSucCount();
|
|
||||||
int triggerDayCountFail = item.getFailCount();
|
|
||||||
|
|
||||||
triggerDayList.add(day);
|
|
||||||
triggerDayCountRunningList.add(triggerDayCountRunning);
|
|
||||||
triggerDayCountSucList.add(triggerDayCountSuc);
|
|
||||||
triggerDayCountFailList.add(triggerDayCountFail);
|
|
||||||
|
|
||||||
triggerCountRunningTotal += triggerDayCountRunning;
|
|
||||||
triggerCountSucTotal += triggerDayCountSuc;
|
|
||||||
triggerCountFailTotal += triggerDayCountFail;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i = -6; i <= 0; i++) {
|
|
||||||
triggerDayList.add(DateUtil.formatDate(DateUtil.addDays(new Date(), i)));
|
|
||||||
triggerDayCountRunningList.add(0);
|
|
||||||
triggerDayCountSucList.add(0);
|
|
||||||
triggerDayCountFailList.add(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, Object> result = new HashMap<String, Object>();
|
|
||||||
result.put("triggerDayList", triggerDayList);
|
|
||||||
result.put("triggerDayCountRunningList", triggerDayCountRunningList);
|
|
||||||
result.put("triggerDayCountSucList", triggerDayCountSucList);
|
|
||||||
result.put("triggerDayCountFailList", triggerDayCountFailList);
|
|
||||||
|
|
||||||
result.put("triggerCountRunningTotal", triggerCountRunningTotal);
|
|
||||||
result.put("triggerCountSucTotal", triggerCountSucTotal);
|
|
||||||
result.put("triggerCountFailTotal", triggerCountFailTotal);
|
|
||||||
|
|
||||||
return new ReturnT<Map<String, Object>>(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
--- # 监控配置
|
|
||||||
spring.boot.admin.client:
|
|
||||||
# 增加客户端开关
|
|
||||||
enabled: true
|
|
||||||
# 设置 Spring Boot Admin Server 地址
|
|
||||||
url: http://localhost:9090/admin
|
|
||||||
instance:
|
|
||||||
service-host-type: IP
|
|
||||||
username: ruoyi
|
|
||||||
password: 123456
|
|
||||||
|
|
||||||
--- # 数据库配置
|
|
||||||
spring:
|
|
||||||
datasource:
|
|
||||||
type: com.zaxxer.hikari.HikariDataSource
|
|
||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
|
||||||
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
|
|
||||||
username: root
|
|
||||||
password: root
|
|
||||||
hikari:
|
|
||||||
auto-commit: true
|
|
||||||
connection-test-query: SELECT 1
|
|
||||||
connection-timeout: 10000
|
|
||||||
idle-timeout: 30000
|
|
||||||
max-lifetime: 900000
|
|
||||||
maximum-pool-size: 30
|
|
||||||
minimum-idle: 10
|
|
||||||
pool-name: HikariCP
|
|
||||||
validation-timeout: 1000
|
|
||||||
|
|
||||||
--- # 邮件配置
|
|
||||||
spring:
|
|
||||||
mail:
|
|
||||||
from: xxx@qq.com
|
|
||||||
host: smtp.qq.com
|
|
||||||
username: xxx@qq.com
|
|
||||||
password: xxx
|
|
||||||
port: 25
|
|
||||||
properties:
|
|
||||||
mail:
|
|
||||||
smtp:
|
|
||||||
auth: true
|
|
||||||
socketFactory:
|
|
||||||
class: javax.net.ssl.SSLSocketFactory
|
|
||||||
starttls:
|
|
||||||
enable: true
|
|
||||||
required: true
|
|
@ -1,47 +0,0 @@
|
|||||||
--- # 监控配置
|
|
||||||
spring.boot.admin.client:
|
|
||||||
# 增加客户端开关
|
|
||||||
enabled: true
|
|
||||||
# 设置 Spring Boot Admin Server 地址
|
|
||||||
url: http://localhost:9090/admin
|
|
||||||
instance:
|
|
||||||
service-host-type: IP
|
|
||||||
username: ruoyi
|
|
||||||
password: 123456
|
|
||||||
|
|
||||||
--- # 数据库配置
|
|
||||||
spring:
|
|
||||||
datasource:
|
|
||||||
type: com.zaxxer.hikari.HikariDataSource
|
|
||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
|
||||||
url: jdbc:mysql://127.0.0.1:3306/ry-vue?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
|
|
||||||
username: root
|
|
||||||
password: root
|
|
||||||
hikari:
|
|
||||||
auto-commit: true
|
|
||||||
connection-test-query: SELECT 1
|
|
||||||
connection-timeout: 10000
|
|
||||||
idle-timeout: 30000
|
|
||||||
max-lifetime: 900000
|
|
||||||
maximum-pool-size: 30
|
|
||||||
minimum-idle: 10
|
|
||||||
pool-name: HikariCP
|
|
||||||
validation-timeout: 1000
|
|
||||||
|
|
||||||
--- # 邮件配置
|
|
||||||
spring:
|
|
||||||
mail:
|
|
||||||
from: xxx@qq.com
|
|
||||||
host: smtp.qq.com
|
|
||||||
username: xxx@qq.com
|
|
||||||
password: xxx
|
|
||||||
port: 25
|
|
||||||
properties:
|
|
||||||
mail:
|
|
||||||
smtp:
|
|
||||||
auth: true
|
|
||||||
socketFactory:
|
|
||||||
class: javax.net.ssl.SSLSocketFactory
|
|
||||||
starttls:
|
|
||||||
enable: true
|
|
||||||
required: true
|
|
@ -1,64 +0,0 @@
|
|||||||
--- # server 配置
|
|
||||||
server:
|
|
||||||
port: 9100
|
|
||||||
servlet:
|
|
||||||
context-path: /xxl-job-admin
|
|
||||||
spring:
|
|
||||||
application:
|
|
||||||
name: ruoyi-xxl-job-admin
|
|
||||||
profiles:
|
|
||||||
active: @profiles.active@
|
|
||||||
mvc:
|
|
||||||
servlet:
|
|
||||||
load-on-startup: 0
|
|
||||||
static-path-pattern: /static/**
|
|
||||||
web:
|
|
||||||
resources:
|
|
||||||
static-locations: classpath:/static/
|
|
||||||
|
|
||||||
logging:
|
|
||||||
config: classpath:logback-plus.xml
|
|
||||||
|
|
||||||
--- # mybatis 配置
|
|
||||||
mybatis:
|
|
||||||
mapper-locations: classpath:/mybatis-mapper/*Mapper.xml
|
|
||||||
|
|
||||||
--- # 页面配置
|
|
||||||
spring:
|
|
||||||
freemarker:
|
|
||||||
charset: UTF-8
|
|
||||||
request-context-attribute: request
|
|
||||||
settings:
|
|
||||||
number_format: 0.##########
|
|
||||||
suffix: .ftl
|
|
||||||
templateLoaderPath: classpath:/templates/
|
|
||||||
|
|
||||||
--- # Actuator 监控端点的配置项
|
|
||||||
management:
|
|
||||||
health:
|
|
||||||
mail:
|
|
||||||
enabled: false
|
|
||||||
endpoints:
|
|
||||||
web:
|
|
||||||
exposure:
|
|
||||||
include: '*'
|
|
||||||
endpoint:
|
|
||||||
health:
|
|
||||||
show-details: ALWAYS
|
|
||||||
logfile:
|
|
||||||
external-file: ./logs/ruoyi-xxl-job-admin.log
|
|
||||||
|
|
||||||
--- # xxljob系统配置
|
|
||||||
xxl:
|
|
||||||
job:
|
|
||||||
# 鉴权token
|
|
||||||
accessToken: xxl-job
|
|
||||||
# 国际化
|
|
||||||
i18n: zh_CN
|
|
||||||
# 日志清理
|
|
||||||
logretentiondays: 30
|
|
||||||
triggerpool:
|
|
||||||
fast:
|
|
||||||
max: 200
|
|
||||||
slow:
|
|
||||||
max: 100
|
|
@ -1,8 +0,0 @@
|
|||||||
Application Version: ${revision}
|
|
||||||
Spring Boot Version: ${spring-boot.version}
|
|
||||||
__ __ _ _ _ _ _
|
|
||||||
\ \ / / | | | | | | /\ | | (_)
|
|
||||||
\ V / __ _| |______ | | ___ | |__ ______ / \ __| |_ __ ___ _ _ __
|
|
||||||
> < \ \/ / |______| | |/ _ \| '_ \______/ /\ \ / _` | '_ ` _ \| | '_ \
|
|
||||||
/ . \ > <| | | |__| | (_) | |_) | / ____ \ (_| | | | | | | | | | |
|
|
||||||
/_/ \_\/_/\_\_| \____/ \___/|_.__/ /_/ \_\__,_|_| |_| |_|_|_| |_|
|
|
@ -1,276 +0,0 @@
|
|||||||
admin_name=Scheduling Center
|
|
||||||
admin_name_full=Distributed Task Scheduling Platform XXL-JOB
|
|
||||||
admin_version=2.4.0
|
|
||||||
admin_i18n=en
|
|
||||||
|
|
||||||
## system
|
|
||||||
system_tips=System message
|
|
||||||
system_ok=Confirm
|
|
||||||
system_close=Close
|
|
||||||
system_save=Save
|
|
||||||
system_cancel=Cancel
|
|
||||||
system_search=Search
|
|
||||||
system_status=Status
|
|
||||||
system_opt=Operate
|
|
||||||
system_please_input=please input
|
|
||||||
system_please_choose=please choose
|
|
||||||
system_success=success
|
|
||||||
system_fail=fail
|
|
||||||
system_add_suc=add success
|
|
||||||
system_add_fail=add fail
|
|
||||||
system_update_suc=update success
|
|
||||||
system_update_fail=update fail
|
|
||||||
system_all=All
|
|
||||||
system_api_error=net error
|
|
||||||
system_show=Show
|
|
||||||
system_empty=Empty
|
|
||||||
system_opt_suc=operate success
|
|
||||||
system_opt_fail=operate fail
|
|
||||||
system_opt_edit=Edit
|
|
||||||
system_opt_del=Delete
|
|
||||||
system_opt_copy=Copy
|
|
||||||
system_unvalid=illegal
|
|
||||||
system_not_found=not exist
|
|
||||||
system_nav=Navigation
|
|
||||||
system_digits=digits
|
|
||||||
system_lengh_limit=Length limit
|
|
||||||
system_permission_limit=Permission limit
|
|
||||||
system_welcome=Welcome
|
|
||||||
|
|
||||||
## daterangepicker
|
|
||||||
daterangepicker_ranges_recent_hour=recent one hour
|
|
||||||
daterangepicker_ranges_today=today
|
|
||||||
daterangepicker_ranges_yesterday=yesterday
|
|
||||||
daterangepicker_ranges_this_month=this month
|
|
||||||
daterangepicker_ranges_last_month=last month
|
|
||||||
daterangepicker_ranges_recent_week=recent one week
|
|
||||||
daterangepicker_ranges_recent_month=recent one month
|
|
||||||
daterangepicker_custom_name=custom
|
|
||||||
daterangepicker_custom_starttime=start time
|
|
||||||
daterangepicker_custom_endtime=end time
|
|
||||||
daterangepicker_custom_daysofweek=Sun,Mon,Tue,Wed,Thu,Fri,Sat
|
|
||||||
daterangepicker_custom_monthnames=Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec
|
|
||||||
|
|
||||||
## dataTable
|
|
||||||
dataTable_sProcessing=processing...
|
|
||||||
dataTable_sLengthMenu= _MENU_ records per page
|
|
||||||
dataTable_sZeroRecords=No matching results
|
|
||||||
dataTable_sInfo=page _PAGE_ ( Total _PAGES_ pages,_TOTAL_ records )
|
|
||||||
dataTable_sInfoEmpty=No Record
|
|
||||||
dataTable_sInfoFiltered=(Filtered by _MAX_ results)
|
|
||||||
dataTable_sSearch=Search
|
|
||||||
dataTable_sEmptyTable=Table data is empty
|
|
||||||
dataTable_sLoadingRecords=Loading...
|
|
||||||
dataTable_sFirst=FIRST PAGE
|
|
||||||
dataTable_sPrevious=Previous Page
|
|
||||||
dataTable_sNext=Next Page
|
|
||||||
dataTable_sLast=LAST PAGE
|
|
||||||
dataTable_sSortAscending=: Rank this column in ascending order
|
|
||||||
dataTable_sSortDescending=: Rank this column in descending order
|
|
||||||
|
|
||||||
## login
|
|
||||||
login_btn=Login
|
|
||||||
login_remember_me=Remember Me
|
|
||||||
login_username_placeholder=Please enter username
|
|
||||||
login_password_placeholder=Please enter password
|
|
||||||
login_username_empty=Please enter username
|
|
||||||
login_username_lt_4=Username length should not be less than 4
|
|
||||||
login_password_empty=Please enter password
|
|
||||||
login_password_lt_4=Password length should not be less than 4
|
|
||||||
login_success=Login success
|
|
||||||
login_fail=Login fail
|
|
||||||
login_param_empty=Username or password is empty
|
|
||||||
login_param_unvalid=Username or password error
|
|
||||||
|
|
||||||
## logout
|
|
||||||
logout_btn=Logout
|
|
||||||
logout_confirm=Confirm logout?
|
|
||||||
logout_success=Logout success
|
|
||||||
logout_fail=Logout fail
|
|
||||||
|
|
||||||
## change pwd
|
|
||||||
change_pwd=Change password
|
|
||||||
change_pwd_suc_to_logout=Change password successful, about to log out login
|
|
||||||
change_pwd_field_newpwd=new password
|
|
||||||
|
|
||||||
## dashboard
|
|
||||||
job_dashboard_name=Run report
|
|
||||||
job_dashboard_job_num=Job number
|
|
||||||
job_dashboard_job_num_tip=The number of tasks running in the scheduling center
|
|
||||||
job_dashboard_trigger_num=trigger number
|
|
||||||
job_dashboard_trigger_num_tip=The number of trigger record scheduled by the scheduling center
|
|
||||||
job_dashboard_jobgroup_num=Executor number
|
|
||||||
job_dashboard_jobgroup_num_tip=The number of online executor machines perceived by the scheduling center
|
|
||||||
job_dashboard_report=Scheduling report
|
|
||||||
job_dashboard_report_loaddata_fail=Scheduling report load data error
|
|
||||||
job_dashboard_date_report=Date distribution
|
|
||||||
job_dashboard_rate_report=Percentage distribution
|
|
||||||
|
|
||||||
## job info
|
|
||||||
jobinfo_name=Job Manage
|
|
||||||
jobinfo_job=Job
|
|
||||||
jobinfo_field_add=Add Job
|
|
||||||
jobinfo_field_update=Edit Job
|
|
||||||
jobinfo_field_id=Job ID
|
|
||||||
jobinfo_field_jobgroup=Executor
|
|
||||||
jobinfo_field_jobdesc=Job description
|
|
||||||
jobinfo_field_timeout=Job timeout period
|
|
||||||
jobinfo_field_gluetype=GLUE Type
|
|
||||||
jobinfo_field_executorparam=Param
|
|
||||||
jobinfo_field_author=Author
|
|
||||||
jobinfo_field_alarmemail=Alarm email
|
|
||||||
jobinfo_field_alarmemail_placeholder=Please enter alarm mail, if there are more than one comma separated
|
|
||||||
jobinfo_field_executorRouteStrategy=Route Strategy
|
|
||||||
jobinfo_field_childJobId=Child Job ID
|
|
||||||
jobinfo_field_childJobId_placeholder=Please enter the Child job ID, if there are more than one comma separated
|
|
||||||
jobinfo_field_executorBlockStrategy=Block Strategy
|
|
||||||
jobinfo_field_executorFailRetryCount=Fail Retry Count
|
|
||||||
jobinfo_field_executorFailRetryCount_placeholder=Fail Retry Count. effect if greater than zero
|
|
||||||
jobinfo_script_location=Script location
|
|
||||||
jobinfo_shard_index=Shard index
|
|
||||||
jobinfo_shard_total=Shard total
|
|
||||||
jobinfo_opt_stop=Stop
|
|
||||||
jobinfo_opt_start=Start
|
|
||||||
jobinfo_opt_log=Query Log
|
|
||||||
jobinfo_opt_run=Run Once
|
|
||||||
jobinfo_opt_run_tips=Please input the address for this trigger. Null will be obtained from the executor
|
|
||||||
jobinfo_opt_registryinfo=Registry Info
|
|
||||||
jobinfo_opt_next_time=Next trigger time
|
|
||||||
jobinfo_glue_remark=Resource Remark
|
|
||||||
jobinfo_glue_remark_limit=Resource Remark length is limited to 4~100
|
|
||||||
jobinfo_glue_rollback=Version Backtrack
|
|
||||||
jobinfo_glue_jobid_unvalid=Job ID is illegal
|
|
||||||
jobinfo_glue_gluetype_unvalid=The job is not GLUE Type
|
|
||||||
jobinfo_field_executorTimeout_placeholder=Job Timeout period,in seconds. effect if greater than zero
|
|
||||||
schedule_type=Schedule Type
|
|
||||||
schedule_type_none=None
|
|
||||||
schedule_type_cron=Cron
|
|
||||||
schedule_type_fix_rate=Fix rate
|
|
||||||
schedule_type_fix_delay=Fix delay
|
|
||||||
schedule_type_none_limit_start=The current schedule type disables startup
|
|
||||||
misfire_strategy=Misfire strategy
|
|
||||||
misfire_strategy_do_nothing=Do nothing
|
|
||||||
misfire_strategy_fire_once_now=Fire once now
|
|
||||||
jobinfo_conf_base=Base configuration
|
|
||||||
jobinfo_conf_schedule=Schedule configuration
|
|
||||||
jobinfo_conf_job=Job configuration
|
|
||||||
jobinfo_conf_advanced=Advanced configuration
|
|
||||||
|
|
||||||
## job log
|
|
||||||
joblog_name=Trigger Log
|
|
||||||
joblog_status=Status
|
|
||||||
joblog_status_all=All
|
|
||||||
joblog_status_suc=Success
|
|
||||||
joblog_status_fail=Fail
|
|
||||||
joblog_status_running=Running
|
|
||||||
joblog_field_triggerTime=Trigger Time
|
|
||||||
joblog_field_triggerCode=Trigger Result
|
|
||||||
joblog_field_triggerMsg=Trigger Msg
|
|
||||||
joblog_field_handleTime=Handle Time
|
|
||||||
joblog_field_handleCode=Handle Result
|
|
||||||
joblog_field_handleMsg=Trigger Msg
|
|
||||||
joblog_field_executorAddress=Executor Address
|
|
||||||
joblog_clean=Clean
|
|
||||||
joblog_clean_log=Clean Log
|
|
||||||
joblog_clean_type=Clean Type
|
|
||||||
joblog_clean_type_1=Clean up log data a month ago
|
|
||||||
joblog_clean_type_2=Clean up log data three month ago
|
|
||||||
joblog_clean_type_3=Clean up log data six month ago
|
|
||||||
joblog_clean_type_4=Clean up log data a year ago
|
|
||||||
joblog_clean_type_5=Clean up log data a thousand record ago
|
|
||||||
joblog_clean_type_6=Clean up log data ten thousand record ago
|
|
||||||
joblog_clean_type_7=Clean up log data thirty thousand record ago
|
|
||||||
joblog_clean_type_8=Clean up log data hundred thousand record ago
|
|
||||||
joblog_clean_type_9=Clean up all log data
|
|
||||||
joblog_clean_type_unvalid=Clean type is illegal
|
|
||||||
joblog_handleCode_200=Success
|
|
||||||
joblog_handleCode_500=Fail
|
|
||||||
joblog_handleCode_502=Timeout
|
|
||||||
joblog_kill_log=Kill Job
|
|
||||||
joblog_kill_log_limit=Trigger Fail, can not kill job
|
|
||||||
joblog_kill_log_byman=Manual operation, kill job
|
|
||||||
joblog_lost_fail=Job result lost, marked as failure
|
|
||||||
joblog_rolling_log=Rolling log
|
|
||||||
joblog_rolling_log_refresh=Refresh
|
|
||||||
joblog_rolling_log_triggerfail=The job trigger fail, can not view the rolling log
|
|
||||||
joblog_rolling_log_failoften=The request for the Rolling log is terminated, the number of failed requests exceeds the limit, Reload the log on the refresh page
|
|
||||||
joblog_logid_unvalid=Log ID is illegal
|
|
||||||
|
|
||||||
## job group
|
|
||||||
jobgroup_name=Executor Manage
|
|
||||||
jobgroup_list=Executor List
|
|
||||||
jobgroup_add=Add Executor
|
|
||||||
jobgroup_edit=Edit Executor
|
|
||||||
jobgroup_del=Delete Executor
|
|
||||||
jobgroup_field_title=Title
|
|
||||||
jobgroup_field_addressType=Registry Type
|
|
||||||
jobgroup_field_addressType_0=Automatic registration
|
|
||||||
jobgroup_field_addressType_1=Manual registration
|
|
||||||
jobgroup_field_addressType_limit=Manually registration type, the machine address must not be empty
|
|
||||||
jobgroup_field_registryList=machine address
|
|
||||||
jobgroup_field_registryList_unvalid=registry machine address is illegal
|
|
||||||
jobgroup_field_registryList_placeholder=Please enter the machine address, if there are more than one comma separated
|
|
||||||
jobgroup_field_appname_limit=Limit the beginning of a lowercase letter, consists of lowercase letters、number and hyphen.
|
|
||||||
jobgroup_field_appname_length=AppName length is limited to 4~64
|
|
||||||
jobgroup_field_title_length=Title length is limited to 4~12
|
|
||||||
jobgroup_field_order_digits=Please enter a positive integer
|
|
||||||
jobgroup_field_orderrange=Order is limited to 1~1000
|
|
||||||
jobgroup_del_limit_0=Refuse to delete, the executor is being used
|
|
||||||
jobgroup_del_limit_1=Refuses to delete, the system retains at least one executor
|
|
||||||
jobgroup_empty=There is no valid executor. Please contact the administrator
|
|
||||||
|
|
||||||
## job conf
|
|
||||||
jobconf_block_SERIAL_EXECUTION=Serial execution
|
|
||||||
jobconf_block_DISCARD_LATER=Discard Later
|
|
||||||
jobconf_block_COVER_EARLY=Cover Early
|
|
||||||
jobconf_route_first=First
|
|
||||||
jobconf_route_last=Last
|
|
||||||
jobconf_route_round=Round
|
|
||||||
jobconf_route_random=Random
|
|
||||||
jobconf_route_consistenthash=Consistent Hash
|
|
||||||
jobconf_route_lfu=Least Frequently Used
|
|
||||||
jobconf_route_lru=Least Recently Used
|
|
||||||
jobconf_route_failover=Failover
|
|
||||||
jobconf_route_busyover=Busyover
|
|
||||||
jobconf_route_shard=Sharding Broadcast
|
|
||||||
jobconf_idleBeat=Idle check
|
|
||||||
jobconf_beat=Heartbeats
|
|
||||||
jobconf_monitor=Task Scheduling Center monitor alarm
|
|
||||||
jobconf_monitor_detail=monitor alarm details
|
|
||||||
jobconf_monitor_alarm_title=Alarm Type
|
|
||||||
jobconf_monitor_alarm_type=Trigger Fail
|
|
||||||
jobconf_monitor_alarm_content=Alarm Content
|
|
||||||
jobconf_trigger_admin_adress=Trigger machine address
|
|
||||||
jobconf_trigger_exe_regtype=Execotor-Registry Type
|
|
||||||
jobconf_trigger_exe_regaddress=Execotor-Registry Address
|
|
||||||
jobconf_trigger_address_empty=Trigger Fail:registry address is empty
|
|
||||||
jobconf_trigger_run=Trigger Job
|
|
||||||
jobconf_trigger_child_run=Trigger child job
|
|
||||||
jobconf_callback_child_msg1={0}/{1} [Job ID={2}], Trigger {3}, Trigger msg: {4} <br>
|
|
||||||
jobconf_callback_child_msg2={0}/{1} [Job ID={2}], Trigger Fail, Trigger msg: Job ID is illegal <br>
|
|
||||||
jobconf_trigger_type=Job trigger type
|
|
||||||
jobconf_trigger_type_cron=Cron trigger
|
|
||||||
jobconf_trigger_type_manual=Manual trigger
|
|
||||||
jobconf_trigger_type_parent=Parent job trigger
|
|
||||||
jobconf_trigger_type_api=Api trigger
|
|
||||||
jobconf_trigger_type_retry=Fail retry trigger
|
|
||||||
jobconf_trigger_type_misfire=Misfire compensation trigger
|
|
||||||
|
|
||||||
## user
|
|
||||||
user_manage=User Manage
|
|
||||||
user_username=Username
|
|
||||||
user_password=Password
|
|
||||||
user_role=Role
|
|
||||||
user_role_admin=Admin User
|
|
||||||
user_role_normal=Normal User
|
|
||||||
user_permission=Permission
|
|
||||||
user_add=Add User
|
|
||||||
user_update=Edit User
|
|
||||||
user_username_repeat=Username Repeat
|
|
||||||
user_username_valid=Restrictions start with a lowercase letter and consist of lowercase letters and Numbers
|
|
||||||
user_password_update_placeholder=Please input password, empty means not update
|
|
||||||
user_update_loginuser_limit=Operation of current login account is not allowed
|
|
||||||
|
|
||||||
## help
|
|
||||||
job_help=Tutorial
|
|
||||||
job_help_document=Official Document
|
|
@ -1,276 +0,0 @@
|
|||||||
admin_name=任务调度中心
|
|
||||||
admin_name_full=分布式任务调度平台XXL-JOB
|
|
||||||
admin_version=2.4.0
|
|
||||||
admin_i18n=
|
|
||||||
|
|
||||||
## system
|
|
||||||
system_tips=系统提示
|
|
||||||
system_ok=确定
|
|
||||||
system_close=关闭
|
|
||||||
system_save=保存
|
|
||||||
system_cancel=取消
|
|
||||||
system_search=搜索
|
|
||||||
system_status=状态
|
|
||||||
system_opt=操作
|
|
||||||
system_please_input=请输入
|
|
||||||
system_please_choose=请选择
|
|
||||||
system_success=成功
|
|
||||||
system_fail=失败
|
|
||||||
system_add_suc=新增成功
|
|
||||||
system_add_fail=新增失败
|
|
||||||
system_update_suc=更新成功
|
|
||||||
system_update_fail=更新失败
|
|
||||||
system_all=全部
|
|
||||||
system_api_error=接口异常
|
|
||||||
system_show=查看
|
|
||||||
system_empty=无
|
|
||||||
system_opt_suc=操作成功
|
|
||||||
system_opt_fail=操作失败
|
|
||||||
system_opt_edit=编辑
|
|
||||||
system_opt_del=删除
|
|
||||||
system_opt_copy=复制
|
|
||||||
system_unvalid=非法
|
|
||||||
system_not_found=不存在
|
|
||||||
system_nav=导航
|
|
||||||
system_digits=整数
|
|
||||||
system_lengh_limit=长度限制
|
|
||||||
system_permission_limit=权限拦截
|
|
||||||
system_welcome=欢迎
|
|
||||||
|
|
||||||
## daterangepicker
|
|
||||||
daterangepicker_ranges_recent_hour=最近一小时
|
|
||||||
daterangepicker_ranges_today=今日
|
|
||||||
daterangepicker_ranges_yesterday=昨日
|
|
||||||
daterangepicker_ranges_this_month=本月
|
|
||||||
daterangepicker_ranges_last_month=上个月
|
|
||||||
daterangepicker_ranges_recent_week=最近一周
|
|
||||||
daterangepicker_ranges_recent_month=最近一月
|
|
||||||
daterangepicker_custom_name=自定义
|
|
||||||
daterangepicker_custom_starttime=起始时间
|
|
||||||
daterangepicker_custom_endtime=结束时间
|
|
||||||
daterangepicker_custom_daysofweek=日,一,二,三,四,五,六
|
|
||||||
daterangepicker_custom_monthnames=一月,二月,三月,四月,五月,六月,七月,八月,九月,十月,十一月,十二月
|
|
||||||
|
|
||||||
## dataTable
|
|
||||||
dataTable_sProcessing=处理中...
|
|
||||||
dataTable_sLengthMenu=每页 _MENU_ 条记录
|
|
||||||
dataTable_sZeroRecords=没有匹配结果
|
|
||||||
dataTable_sInfo=第 _PAGE_ 页 ( 总共 _PAGES_ 页,_TOTAL_ 条记录 )
|
|
||||||
dataTable_sInfoEmpty=无记录
|
|
||||||
dataTable_sInfoFiltered=(由 _MAX_ 项结果过滤)
|
|
||||||
dataTable_sSearch=搜索
|
|
||||||
dataTable_sEmptyTable=表中数据为空
|
|
||||||
dataTable_sLoadingRecords=载入中...
|
|
||||||
dataTable_sFirst=首页
|
|
||||||
dataTable_sPrevious=上页
|
|
||||||
dataTable_sNext=下页
|
|
||||||
dataTable_sLast=末页
|
|
||||||
dataTable_sSortAscending=: 以升序排列此列
|
|
||||||
dataTable_sSortDescending=: 以降序排列此列
|
|
||||||
|
|
||||||
## login
|
|
||||||
login_btn=登录
|
|
||||||
login_remember_me=记住密码
|
|
||||||
login_username_placeholder=请输入登录账号
|
|
||||||
login_password_placeholder=请输入登录密码
|
|
||||||
login_username_empty=请输入登录账号
|
|
||||||
login_username_lt_4=登录账号不应低于4位
|
|
||||||
login_password_empty=请输入登录密码
|
|
||||||
login_password_lt_4=登录密码不应低于4位
|
|
||||||
login_success=登录成功
|
|
||||||
login_fail=登录失败
|
|
||||||
login_param_empty=账号或密码为空
|
|
||||||
login_param_unvalid=账号或密码错误
|
|
||||||
|
|
||||||
## logout
|
|
||||||
logout_btn=注销
|
|
||||||
logout_confirm=确认注销登录?
|
|
||||||
logout_success=注销成功
|
|
||||||
logout_fail=注销失败
|
|
||||||
|
|
||||||
## change pwd
|
|
||||||
change_pwd=修改密码
|
|
||||||
change_pwd_suc_to_logout=修改密码成功,即将注销登陆
|
|
||||||
change_pwd_field_newpwd=新密码
|
|
||||||
|
|
||||||
## dashboard
|
|
||||||
job_dashboard_name=运行报表
|
|
||||||
job_dashboard_job_num=任务数量
|
|
||||||
job_dashboard_job_num_tip=调度中心运行的任务数量
|
|
||||||
job_dashboard_trigger_num=调度次数
|
|
||||||
job_dashboard_trigger_num_tip=调度中心触发的调度次数
|
|
||||||
job_dashboard_jobgroup_num=执行器数量
|
|
||||||
job_dashboard_jobgroup_num_tip=调度中心在线的执行器机器数量
|
|
||||||
job_dashboard_report=调度报表
|
|
||||||
job_dashboard_report_loaddata_fail=调度报表数据加载异常
|
|
||||||
job_dashboard_date_report=日期分布图
|
|
||||||
job_dashboard_rate_report=成功比例图
|
|
||||||
|
|
||||||
## job info
|
|
||||||
jobinfo_name=任务管理
|
|
||||||
jobinfo_job=任务
|
|
||||||
jobinfo_field_add=新增
|
|
||||||
jobinfo_field_update=更新任务
|
|
||||||
jobinfo_field_id=任务ID
|
|
||||||
jobinfo_field_jobgroup=执行器
|
|
||||||
jobinfo_field_jobdesc=任务描述
|
|
||||||
jobinfo_field_gluetype=运行模式
|
|
||||||
jobinfo_field_executorparam=任务参数
|
|
||||||
jobinfo_field_author=负责人
|
|
||||||
jobinfo_field_timeout=任务超时时间
|
|
||||||
jobinfo_field_alarmemail=报警邮件
|
|
||||||
jobinfo_field_alarmemail_placeholder=请输入报警邮件,多个邮件地址则逗号分隔
|
|
||||||
jobinfo_field_executorRouteStrategy=路由策略
|
|
||||||
jobinfo_field_childJobId=子任务ID
|
|
||||||
jobinfo_field_childJobId_placeholder=请输入子任务的任务ID,如存在多个则逗号分隔
|
|
||||||
jobinfo_field_executorBlockStrategy=阻塞处理策略
|
|
||||||
jobinfo_field_executorFailRetryCount=失败重试次数
|
|
||||||
jobinfo_field_executorFailRetryCount_placeholder=失败重试次数,大于零时生效
|
|
||||||
jobinfo_script_location=脚本位置
|
|
||||||
jobinfo_shard_index=分片序号
|
|
||||||
jobinfo_shard_total=分片总数
|
|
||||||
jobinfo_opt_stop=停止
|
|
||||||
jobinfo_opt_start=启动
|
|
||||||
jobinfo_opt_log=查询日志
|
|
||||||
jobinfo_opt_run=执行一次
|
|
||||||
jobinfo_opt_run_tips=请输入本次执行的机器地址,为空则从执行器获取
|
|
||||||
jobinfo_opt_registryinfo=注册节点
|
|
||||||
jobinfo_opt_next_time=下次执行时间
|
|
||||||
jobinfo_glue_remark=源码备注
|
|
||||||
jobinfo_glue_remark_limit=源码备注长度限制为4~100
|
|
||||||
jobinfo_glue_rollback=版本回溯
|
|
||||||
jobinfo_glue_jobid_unvalid=任务ID非法
|
|
||||||
jobinfo_glue_gluetype_unvalid=该任务非GLUE模式
|
|
||||||
jobinfo_field_executorTimeout_placeholder=任务超时时间,单位秒,大于零时生效
|
|
||||||
schedule_type=调度类型
|
|
||||||
schedule_type_none=无
|
|
||||||
schedule_type_cron=CRON
|
|
||||||
schedule_type_fix_rate=固定速度
|
|
||||||
schedule_type_fix_delay=固定延迟
|
|
||||||
schedule_type_none_limit_start=当前调度类型禁止启动
|
|
||||||
misfire_strategy=调度过期策略
|
|
||||||
misfire_strategy_do_nothing=忽略
|
|
||||||
misfire_strategy_fire_once_now=立即执行一次
|
|
||||||
jobinfo_conf_base=基础配置
|
|
||||||
jobinfo_conf_schedule=调度配置
|
|
||||||
jobinfo_conf_job=任务配置
|
|
||||||
jobinfo_conf_advanced=高级配置
|
|
||||||
|
|
||||||
## job log
|
|
||||||
joblog_name=调度日志
|
|
||||||
joblog_status=状态
|
|
||||||
joblog_status_all=全部
|
|
||||||
joblog_status_suc=成功
|
|
||||||
joblog_status_fail=失败
|
|
||||||
joblog_status_running=进行中
|
|
||||||
joblog_field_triggerTime=调度时间
|
|
||||||
joblog_field_triggerCode=调度结果
|
|
||||||
joblog_field_triggerMsg=调度备注
|
|
||||||
joblog_field_handleTime=执行时间
|
|
||||||
joblog_field_handleCode=执行结果
|
|
||||||
joblog_field_handleMsg=执行备注
|
|
||||||
joblog_field_executorAddress=执行器地址
|
|
||||||
joblog_clean=清理
|
|
||||||
joblog_clean_log=日志清理
|
|
||||||
joblog_clean_type=清理方式
|
|
||||||
joblog_clean_type_1=清理一个月之前日志数据
|
|
||||||
joblog_clean_type_2=清理三个月之前日志数据
|
|
||||||
joblog_clean_type_3=清理六个月之前日志数据
|
|
||||||
joblog_clean_type_4=清理一年之前日志数据
|
|
||||||
joblog_clean_type_5=清理一千条以前日志数据
|
|
||||||
joblog_clean_type_6=清理一万条以前日志数据
|
|
||||||
joblog_clean_type_7=清理三万条以前日志数据
|
|
||||||
joblog_clean_type_8=清理十万条以前日志数据
|
|
||||||
joblog_clean_type_9=清理所有日志数据
|
|
||||||
joblog_clean_type_unvalid=清理类型参数异常
|
|
||||||
joblog_handleCode_200=成功
|
|
||||||
joblog_handleCode_500=失败
|
|
||||||
joblog_handleCode_502=失败(超时)
|
|
||||||
joblog_kill_log=终止任务
|
|
||||||
joblog_kill_log_limit=调度失败,无法终止日志
|
|
||||||
joblog_kill_log_byman=人为操作,主动终止
|
|
||||||
joblog_lost_fail=任务结果丢失,标记失败
|
|
||||||
joblog_rolling_log=执行日志
|
|
||||||
joblog_rolling_log_refresh=刷新
|
|
||||||
joblog_rolling_log_triggerfail=任务发起调度失败,无法查看执行日志
|
|
||||||
joblog_rolling_log_failoften=终止请求Rolling日志,请求失败次数超上限,可刷新页面重新加载日志
|
|
||||||
joblog_logid_unvalid=日志ID非法
|
|
||||||
|
|
||||||
## job group
|
|
||||||
jobgroup_name=执行器管理
|
|
||||||
jobgroup_list=执行器列表
|
|
||||||
jobgroup_add=新增执行器
|
|
||||||
jobgroup_edit=编辑执行器
|
|
||||||
jobgroup_del=删除执行器
|
|
||||||
jobgroup_field_title=名称
|
|
||||||
jobgroup_field_addressType=注册方式
|
|
||||||
jobgroup_field_addressType_0=自动注册
|
|
||||||
jobgroup_field_addressType_1=手动录入
|
|
||||||
jobgroup_field_addressType_limit=手动录入注册方式,机器地址不可为空
|
|
||||||
jobgroup_field_registryList=机器地址
|
|
||||||
jobgroup_field_registryList_unvalid=机器地址格式非法
|
|
||||||
jobgroup_field_registryList_placeholder=请输入执行器地址列表,多地址逗号分隔
|
|
||||||
jobgroup_field_appname_limit=限制以小写字母开头,由小写字母、数字和中划线组成
|
|
||||||
jobgroup_field_appname_length=AppName长度限制为4~64
|
|
||||||
jobgroup_field_title_length=名称长度限制为4~12
|
|
||||||
jobgroup_field_order_digits=请输入整数
|
|
||||||
jobgroup_field_orderrange=取值范围为1~1000
|
|
||||||
jobgroup_del_limit_0=拒绝删除,该执行器使用中
|
|
||||||
jobgroup_del_limit_1=拒绝删除, 系统至少保留一个执行器
|
|
||||||
jobgroup_empty=不存在有效执行器,请联系管理员
|
|
||||||
|
|
||||||
## job conf
|
|
||||||
jobconf_block_SERIAL_EXECUTION=单机串行
|
|
||||||
jobconf_block_DISCARD_LATER=丢弃后续调度
|
|
||||||
jobconf_block_COVER_EARLY=覆盖之前调度
|
|
||||||
jobconf_route_first=第一个
|
|
||||||
jobconf_route_last=最后一个
|
|
||||||
jobconf_route_round=轮询
|
|
||||||
jobconf_route_random=随机
|
|
||||||
jobconf_route_consistenthash=一致性HASH
|
|
||||||
jobconf_route_lfu=最不经常使用
|
|
||||||
jobconf_route_lru=最近最久未使用
|
|
||||||
jobconf_route_failover=故障转移
|
|
||||||
jobconf_route_busyover=忙碌转移
|
|
||||||
jobconf_route_shard=分片广播
|
|
||||||
jobconf_idleBeat=空闲检测
|
|
||||||
jobconf_beat=心跳检测
|
|
||||||
jobconf_monitor=任务调度中心监控报警
|
|
||||||
jobconf_monitor_detail=监控告警明细
|
|
||||||
jobconf_monitor_alarm_title=告警类型
|
|
||||||
jobconf_monitor_alarm_type=调度失败
|
|
||||||
jobconf_monitor_alarm_content=告警内容
|
|
||||||
jobconf_trigger_admin_adress=调度机器
|
|
||||||
jobconf_trigger_exe_regtype=执行器-注册方式
|
|
||||||
jobconf_trigger_exe_regaddress=执行器-地址列表
|
|
||||||
jobconf_trigger_address_empty=调度失败:执行器地址为空
|
|
||||||
jobconf_trigger_run=触发调度
|
|
||||||
jobconf_trigger_child_run=触发子任务
|
|
||||||
jobconf_callback_child_msg1={0}/{1} [任务ID={2}], 触发{3}, 触发备注: {4} <br>
|
|
||||||
jobconf_callback_child_msg2={0}/{1} [任务ID={2}], 触发失败, 触发备注: 任务ID格式错误 <br>
|
|
||||||
jobconf_trigger_type=任务触发类型
|
|
||||||
jobconf_trigger_type_cron=Cron触发
|
|
||||||
jobconf_trigger_type_manual=手动触发
|
|
||||||
jobconf_trigger_type_parent=父任务触发
|
|
||||||
jobconf_trigger_type_api=API触发
|
|
||||||
jobconf_trigger_type_retry=失败重试触发
|
|
||||||
jobconf_trigger_type_misfire=调度过期补偿
|
|
||||||
|
|
||||||
## user
|
|
||||||
user_manage=用户管理
|
|
||||||
user_username=账号
|
|
||||||
user_password=密码
|
|
||||||
user_role=角色
|
|
||||||
user_role_admin=管理员
|
|
||||||
user_role_normal=普通用户
|
|
||||||
user_permission=权限
|
|
||||||
user_add=新增用户
|
|
||||||
user_update=更新用户
|
|
||||||
user_username_repeat=账号重复
|
|
||||||
user_username_valid=限制以小写字母开头,由小写字母、数字组成
|
|
||||||
user_password_update_placeholder=请输入新密码,为空则不更新密码
|
|
||||||
user_update_loginuser_limit=禁止操作当前登录账号
|
|
||||||
|
|
||||||
## help
|
|
||||||
job_help=使用教程
|
|
||||||
job_help_document=官方文档
|
|
@ -1,276 +0,0 @@
|
|||||||
admin_name=任務調度中心
|
|
||||||
admin_name_full=分布式任務調度平臺XXL-JOB
|
|
||||||
admin_version=2.4.0
|
|
||||||
admin_i18n=
|
|
||||||
|
|
||||||
## system
|
|
||||||
system_tips=系統提示
|
|
||||||
system_ok=確定
|
|
||||||
system_close=關閉
|
|
||||||
system_save=儲存
|
|
||||||
system_cancel=取消
|
|
||||||
system_search=搜尋
|
|
||||||
system_status=狀態
|
|
||||||
system_opt=操作
|
|
||||||
system_please_input=請輸入
|
|
||||||
system_please_choose=请選擇
|
|
||||||
system_success=成功
|
|
||||||
system_fail=失敗
|
|
||||||
system_add_suc=新增成功
|
|
||||||
system_add_fail=新增失敗
|
|
||||||
system_update_suc=更新成功
|
|
||||||
system_update_fail=更新失敗
|
|
||||||
system_all=全部
|
|
||||||
system_api_error=API錯誤
|
|
||||||
system_show=查看
|
|
||||||
system_empty=無
|
|
||||||
system_opt_suc=操作成功
|
|
||||||
system_opt_fail=操作失敗
|
|
||||||
system_opt_edit=編輯
|
|
||||||
system_opt_del=刪除
|
|
||||||
system_opt_copy=復制
|
|
||||||
system_unvalid=非法
|
|
||||||
system_not_found=不存在
|
|
||||||
system_nav=導航
|
|
||||||
system_digits=整數
|
|
||||||
system_lengh_limit=長度限制
|
|
||||||
system_permission_limit=權限控管
|
|
||||||
system_welcome=歡迎
|
|
||||||
|
|
||||||
## daterangepicker
|
|
||||||
daterangepicker_ranges_recent_hour=最近一小時
|
|
||||||
daterangepicker_ranges_today=今日
|
|
||||||
daterangepicker_ranges_yesterday=昨日
|
|
||||||
daterangepicker_ranges_this_month=本月
|
|
||||||
daterangepicker_ranges_last_month=上個月
|
|
||||||
daterangepicker_ranges_recent_week=最近一周
|
|
||||||
daterangepicker_ranges_recent_month=最近一月
|
|
||||||
daterangepicker_custom_name=自定義
|
|
||||||
daterangepicker_custom_starttime=起始時間
|
|
||||||
daterangepicker_custom_endtime=結束時間
|
|
||||||
daterangepicker_custom_daysofweek=日,一,二,三,四,五,六
|
|
||||||
daterangepicker_custom_monthnames=一月,二月,三月,四月,五月,六月,七月,八月,九月,十月,十一月,十二月
|
|
||||||
|
|
||||||
## dataTable
|
|
||||||
dataTable_sProcessing=處理中...
|
|
||||||
dataTable_sLengthMenu=每頁 _MENU_ 條記錄
|
|
||||||
dataTable_sZeroRecords=沒有相符合記錄
|
|
||||||
dataTable_sInfo=第 _PAGE_ 頁 ( 總共 _PAGES_ 頁,_TOTAL_ 條記錄 )
|
|
||||||
dataTable_sInfoEmpty=無記錄
|
|
||||||
dataTable_sInfoFiltered=(由 _MAX_ 項結果過濾)
|
|
||||||
dataTable_sSearch=搜尋
|
|
||||||
dataTable_sEmptyTable=表中資料為空
|
|
||||||
dataTable_sLoadingRecords=載入中...
|
|
||||||
dataTable_sFirst=首頁
|
|
||||||
dataTable_sPrevious=上頁
|
|
||||||
dataTable_sNext=下頁
|
|
||||||
dataTable_sLast=末頁
|
|
||||||
dataTable_sSortAscending=: 以升幂排序此列
|
|
||||||
dataTable_sSortDescending=: 以降幂排序此列
|
|
||||||
|
|
||||||
## login
|
|
||||||
login_btn=登入
|
|
||||||
login_remember_me=記住密碼
|
|
||||||
login_username_placeholder=請輸入登入帳號
|
|
||||||
login_password_placeholder=請輸入登入密碼
|
|
||||||
login_username_empty=請輸入登入帳號
|
|
||||||
login_username_lt_4=登入帳號不應低於4位數
|
|
||||||
login_password_empty=請輸入登入密碼
|
|
||||||
login_password_lt_4=登入密碼不應低於4位數
|
|
||||||
login_success=登入成功
|
|
||||||
login_fail=登入失敗
|
|
||||||
login_param_empty=帳號或密碼為空值
|
|
||||||
login_param_unvalid=帳號或密碼錯誤
|
|
||||||
|
|
||||||
## logout
|
|
||||||
logout_btn=登出
|
|
||||||
logout_confirm=確認登出?
|
|
||||||
logout_success=登出成功
|
|
||||||
logout_fail=登出失敗
|
|
||||||
|
|
||||||
## change pwd
|
|
||||||
change_pwd=修改密碼
|
|
||||||
change_pwd_suc_to_logout=修改密碼成功,即將登出
|
|
||||||
change_pwd_field_newpwd=新密碼
|
|
||||||
|
|
||||||
## dashboard
|
|
||||||
job_dashboard_name=運行報表
|
|
||||||
job_dashboard_job_num=任務數量
|
|
||||||
job_dashboard_job_num_tip=調度中心運行的任務數量
|
|
||||||
job_dashboard_trigger_num=調度次數
|
|
||||||
job_dashboard_trigger_num_tip=調度中心觸發的調度次數
|
|
||||||
job_dashboard_jobgroup_num=執行器數量
|
|
||||||
job_dashboard_jobgroup_num_tip=調度中心在線的執行器機器數量
|
|
||||||
job_dashboard_report=調度報表
|
|
||||||
job_dashboard_report_loaddata_fail=調度報表資料加載異常
|
|
||||||
job_dashboard_date_report=日期分布圖
|
|
||||||
job_dashboard_rate_report=成功比例圖
|
|
||||||
|
|
||||||
## job info
|
|
||||||
jobinfo_name=任務管理
|
|
||||||
jobinfo_job=任務
|
|
||||||
jobinfo_field_add=新增
|
|
||||||
jobinfo_field_update=更新任務
|
|
||||||
jobinfo_field_id=任務ID
|
|
||||||
jobinfo_field_jobgroup=執行器
|
|
||||||
jobinfo_field_jobdesc=任務描述
|
|
||||||
jobinfo_field_gluetype=運行模式
|
|
||||||
jobinfo_field_executorparam=任務參數
|
|
||||||
jobinfo_field_author=負責人
|
|
||||||
jobinfo_field_timeout=任務超時秒數
|
|
||||||
jobinfo_field_alarmemail=告警郵件
|
|
||||||
jobinfo_field_alarmemail_placeholder=輸入多個告警郵件地址,請以逗號分隔
|
|
||||||
jobinfo_field_executorRouteStrategy=路由策略
|
|
||||||
jobinfo_field_childJobId=子任務ID
|
|
||||||
jobinfo_field_childJobId_placeholder=輸入子任務ID,如有多個請以逗號分隔
|
|
||||||
jobinfo_field_executorBlockStrategy=阻塞處理策略
|
|
||||||
jobinfo_field_executorFailRetryCount=失敗重試次數
|
|
||||||
jobinfo_field_executorFailRetryCount_placeholder=失敗重試次數,大於零時生效
|
|
||||||
jobinfo_script_location=腳本位置
|
|
||||||
jobinfo_shard_index=分片序號
|
|
||||||
jobinfo_shard_total=分片總數
|
|
||||||
jobinfo_opt_stop=停止
|
|
||||||
jobinfo_opt_start=啟動
|
|
||||||
jobinfo_opt_log=查詢日誌
|
|
||||||
jobinfo_opt_run=執行一次
|
|
||||||
jobinfo_opt_run_tips=請輸入本次執行的機器地址,為空則從執行器獲取
|
|
||||||
jobinfo_opt_registryinfo=注冊節點
|
|
||||||
jobinfo_opt_next_time=下次執行時間
|
|
||||||
jobinfo_glue_remark=源碼備註
|
|
||||||
jobinfo_glue_remark_limit=源碼備註長度限制為4~100
|
|
||||||
jobinfo_glue_rollback=版本回復
|
|
||||||
jobinfo_glue_jobid_unvalid=任務ID非法
|
|
||||||
jobinfo_glue_gluetype_unvalid=該任務非GLUE模式
|
|
||||||
jobinfo_field_executorTimeout_placeholder=任務超時時間,單位秒,大於零時生效
|
|
||||||
schedule_type=調度類型
|
|
||||||
schedule_type_none=無
|
|
||||||
schedule_type_cron=CRON
|
|
||||||
schedule_type_fix_rate=固定速度
|
|
||||||
schedule_type_fix_delay=固定延遲
|
|
||||||
schedule_type_none_limit_start=當前調度類型禁止啟動
|
|
||||||
misfire_strategy=調度過期策略
|
|
||||||
misfire_strategy_do_nothing=忽略
|
|
||||||
misfire_strategy_fire_once_now=立即執行壹次
|
|
||||||
jobinfo_conf_base=基礎配置
|
|
||||||
jobinfo_conf_schedule=調度配置
|
|
||||||
jobinfo_conf_job=任務配置
|
|
||||||
jobinfo_conf_advanced=高級配置
|
|
||||||
|
|
||||||
## job log
|
|
||||||
joblog_name=調度日誌
|
|
||||||
joblog_status=狀態
|
|
||||||
joblog_status_all=全部
|
|
||||||
joblog_status_suc=成功
|
|
||||||
joblog_status_fail=失敗
|
|
||||||
joblog_status_running=進行中
|
|
||||||
joblog_field_triggerTime=調度時間
|
|
||||||
joblog_field_triggerCode=調度結果
|
|
||||||
joblog_field_triggerMsg=調度備註
|
|
||||||
joblog_field_handleTime=執行時間
|
|
||||||
joblog_field_handleCode=執行结果
|
|
||||||
joblog_field_handleMsg=執行備註
|
|
||||||
joblog_field_executorAddress=執行器地址
|
|
||||||
joblog_clean=清理
|
|
||||||
joblog_clean_log=日誌清理
|
|
||||||
joblog_clean_type=清理方式
|
|
||||||
joblog_clean_type_1=清理一個月之前日誌資料
|
|
||||||
joblog_clean_type_2=清理三個月之前日誌資料
|
|
||||||
joblog_clean_type_3=清理六個月之前日誌資料
|
|
||||||
joblog_clean_type_4=清理一年之前日誌資料
|
|
||||||
joblog_clean_type_5=清理一千條以前日誌資料
|
|
||||||
joblog_clean_type_6=清理一萬條以前日誌資料
|
|
||||||
joblog_clean_type_7=清理三萬條以前日誌資料
|
|
||||||
joblog_clean_type_8=清理十萬條以前日誌資料
|
|
||||||
joblog_clean_type_9=清理所有日誌資料
|
|
||||||
joblog_clean_type_unvalid=清理類型參数異常
|
|
||||||
joblog_handleCode_200=成功
|
|
||||||
joblog_handleCode_500=失敗
|
|
||||||
joblog_handleCode_502=失敗(超時)
|
|
||||||
joblog_kill_log=终止任務
|
|
||||||
joblog_kill_log_limit=調度失敗,無法终止日誌
|
|
||||||
joblog_kill_log_byman=人為操作,主動終止
|
|
||||||
joblog_lost_fail=任務結果丟失,標記失敗
|
|
||||||
joblog_rolling_log=執行日誌
|
|
||||||
joblog_rolling_log_refresh=更新
|
|
||||||
joblog_rolling_log_triggerfail=任務發起調度失敗,無法查看執行日誌
|
|
||||||
joblog_rolling_log_failoften=終止請求Rolling日誌,請求失敗次數超上限,可刷新頁面重新加載日誌
|
|
||||||
joblog_logid_unvalid=日誌ID非法
|
|
||||||
|
|
||||||
## job group
|
|
||||||
jobgroup_name=執行器管理
|
|
||||||
jobgroup_list=執行器列表
|
|
||||||
jobgroup_add=新增執行器
|
|
||||||
jobgroup_edit=編輯執行器
|
|
||||||
jobgroup_del=刪除執行器
|
|
||||||
jobgroup_field_title=名稱
|
|
||||||
jobgroup_field_addressType=注冊方式
|
|
||||||
jobgroup_field_addressType_0=自動注冊
|
|
||||||
jobgroup_field_addressType_1=手動登錄
|
|
||||||
jobgroup_field_addressType_limit=手動登錄注冊方式,機器地址不可為空
|
|
||||||
jobgroup_field_registryList=機器地址
|
|
||||||
jobgroup_field_registryList_unvalid=機器地址格式非法
|
|
||||||
jobgroup_field_registryList_placeholder=請輸入執行器地址列表,多個地址請以逗號分隔
|
|
||||||
jobgroup_field_appname_limit=限制以小寫字母開頭,由小寫字母、數字和中划線組成
|
|
||||||
jobgroup_field_appname_length=AppName長度限制為4~64
|
|
||||||
jobgroup_field_title_length=名稱長度限制為4~12
|
|
||||||
jobgroup_field_order_digits=請輸入整數
|
|
||||||
jobgroup_field_orderrange=取值範圍為1~1000
|
|
||||||
jobgroup_del_limit_0=拒絕刪除,該執行器使用中
|
|
||||||
jobgroup_del_limit_1=拒絕删除,系统至少保留一個執行器
|
|
||||||
jobgroup_empty=不存在有效執行器,請聯絡系統管理員
|
|
||||||
|
|
||||||
## job conf
|
|
||||||
jobconf_block_SERIAL_EXECUTION=單機串行
|
|
||||||
jobconf_block_DISCARD_LATER=丢棄后續調度
|
|
||||||
jobconf_block_COVER_EARLY=覆蓋之前調度
|
|
||||||
jobconf_route_first=第一個
|
|
||||||
jobconf_route_last=最後一個
|
|
||||||
jobconf_route_round=輪詢
|
|
||||||
jobconf_route_random=隨機
|
|
||||||
jobconf_route_consistenthash=一致性HASH
|
|
||||||
jobconf_route_lfu=最不經常使用
|
|
||||||
jobconf_route_lru=最近最久未使用
|
|
||||||
jobconf_route_failover=故障轉移
|
|
||||||
jobconf_route_busyover=忙碌轉移
|
|
||||||
jobconf_route_shard=分片廣播
|
|
||||||
jobconf_idleBeat=空閒檢測
|
|
||||||
jobconf_beat=心跳檢測
|
|
||||||
jobconf_monitor=任務調度中心監控告警
|
|
||||||
jobconf_monitor_detail=監控告警明细
|
|
||||||
jobconf_monitor_alarm_title=告警類型
|
|
||||||
jobconf_monitor_alarm_type=調度失敗
|
|
||||||
jobconf_monitor_alarm_content=告警内容
|
|
||||||
jobconf_trigger_admin_adress=調度機器
|
|
||||||
jobconf_trigger_exe_regtype=執行器-注冊方式
|
|
||||||
jobconf_trigger_exe_regaddress=執行器-地址列表
|
|
||||||
jobconf_trigger_address_empty=調度失敗:執行器地址為空
|
|
||||||
jobconf_trigger_run=觸發調度
|
|
||||||
jobconf_trigger_child_run=觸發子任務
|
|
||||||
jobconf_callback_child_msg1={0}/{1} [任務ID={2}], 觸發{3}, 觸發備註: {4} <br>
|
|
||||||
jobconf_callback_child_msg2={0}/{1} [任務ID={2}], 觸發失败, 觸發備註: 任務ID格式錯誤 <br>
|
|
||||||
jobconf_trigger_type=任務觸發類型
|
|
||||||
jobconf_trigger_type_cron=Cron觸發
|
|
||||||
jobconf_trigger_type_manual=手動觸發
|
|
||||||
jobconf_trigger_type_parent=父任務觸發
|
|
||||||
jobconf_trigger_type_api=API觸發
|
|
||||||
jobconf_trigger_type_retry=失敗重試觸發
|
|
||||||
jobconf_trigger_type_misfire=調度過期補償
|
|
||||||
|
|
||||||
## user
|
|
||||||
user_manage=用户管理
|
|
||||||
user_username=帳號
|
|
||||||
user_password=密碼
|
|
||||||
user_role=角色
|
|
||||||
user_role_admin=管理員
|
|
||||||
user_role_normal=普通用戶
|
|
||||||
user_permission=權限
|
|
||||||
user_add=新增用戶
|
|
||||||
user_update=更新用戶
|
|
||||||
user_username_repeat=帳號重複
|
|
||||||
user_username_valid=限制以小寫字母開頭,由小寫字母、數字組成
|
|
||||||
user_password_update_placeholder=請輸入新密碼,為空則不更新密碼
|
|
||||||
user_update_loginuser_limit=禁止操作當前登入帳號
|
|
||||||
|
|
||||||
## help
|
|
||||||
job_help=使用教程
|
|
||||||
job_help_document=官方文件
|
|
@ -1,34 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<configuration debug="false" scan="true" scanPeriod="1 seconds">
|
|
||||||
|
|
||||||
<contextName>logback</contextName>
|
|
||||||
<property name="log.path" value="./logs/ruoyi-xxl-job-admin"/>
|
|
||||||
<property name="console.log.pattern"
|
|
||||||
value="%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/>
|
|
||||||
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"/>
|
|
||||||
|
|
||||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
|
||||||
<encoder>
|
|
||||||
<pattern>${console.log.pattern}</pattern>
|
|
||||||
<charset>utf-8</charset>
|
|
||||||
</encoder>
|
|
||||||
</appender>
|
|
||||||
|
|
||||||
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
|
||||||
<file>${log.path}.log</file>
|
|
||||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
|
||||||
<fileNamePattern>${log.path}.%d{yyyy-MM-dd}.log</fileNamePattern>
|
|
||||||
<!-- 日志最大的历史 60天 -->
|
|
||||||
<maxHistory>60</maxHistory>
|
|
||||||
</rollingPolicy>
|
|
||||||
<encoder>
|
|
||||||
<pattern>${log.pattern}</pattern>
|
|
||||||
</encoder>
|
|
||||||
</appender>
|
|
||||||
|
|
||||||
<root level="info">
|
|
||||||
<appender-ref ref="console"/>
|
|
||||||
<appender-ref ref="file"/>
|
|
||||||
</root>
|
|
||||||
|
|
||||||
</configuration>
|
|
@ -1,91 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|
||||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
|
||||||
<mapper namespace="com.xxl.job.admin.dao.XxlJobGroupDao">
|
|
||||||
|
|
||||||
<resultMap id="XxlJobGroup" type="com.xxl.job.admin.core.model.XxlJobGroup" >
|
|
||||||
<result column="id" property="id" />
|
|
||||||
<result column="app_name" property="appname" />
|
|
||||||
<result column="title" property="title" />
|
|
||||||
<result column="address_type" property="addressType" />
|
|
||||||
<result column="address_list" property="addressList" />
|
|
||||||
<result column="update_time" property="updateTime" />
|
|
||||||
</resultMap>
|
|
||||||
|
|
||||||
<sql id="Base_Column_List">
|
|
||||||
t.id,
|
|
||||||
t.app_name,
|
|
||||||
t.title,
|
|
||||||
t.address_type,
|
|
||||||
t.address_list,
|
|
||||||
t.update_time
|
|
||||||
</sql>
|
|
||||||
|
|
||||||
<select id="findAll" resultMap="XxlJobGroup">
|
|
||||||
SELECT <include refid="Base_Column_List" />
|
|
||||||
FROM xxl_job_group AS t
|
|
||||||
ORDER BY t.app_name, t.title, t.id ASC
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="findByAddressType" parameterType="java.lang.Integer" resultMap="XxlJobGroup">
|
|
||||||
SELECT <include refid="Base_Column_List" />
|
|
||||||
FROM xxl_job_group AS t
|
|
||||||
WHERE t.address_type = #{addressType}
|
|
||||||
ORDER BY t.app_name, t.title, t.id ASC
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<insert id="save" parameterType="com.xxl.job.admin.core.model.XxlJobGroup" useGeneratedKeys="true" keyProperty="id" >
|
|
||||||
INSERT INTO xxl_job_group ( `app_name`, `title`, `address_type`, `address_list`, `update_time`)
|
|
||||||
values ( #{appname}, #{title}, #{addressType}, #{addressList}, #{updateTime} );
|
|
||||||
</insert>
|
|
||||||
|
|
||||||
<update id="update" parameterType="com.xxl.job.admin.core.model.XxlJobGroup" >
|
|
||||||
UPDATE xxl_job_group
|
|
||||||
SET `app_name` = #{appname},
|
|
||||||
`title` = #{title},
|
|
||||||
`address_type` = #{addressType},
|
|
||||||
`address_list` = #{addressList},
|
|
||||||
`update_time` = #{updateTime}
|
|
||||||
WHERE id = #{id}
|
|
||||||
</update>
|
|
||||||
|
|
||||||
<delete id="remove" parameterType="java.lang.Integer" >
|
|
||||||
DELETE FROM xxl_job_group
|
|
||||||
WHERE id = #{id}
|
|
||||||
</delete>
|
|
||||||
|
|
||||||
<select id="load" parameterType="java.lang.Integer" resultMap="XxlJobGroup">
|
|
||||||
SELECT <include refid="Base_Column_List" />
|
|
||||||
FROM xxl_job_group AS t
|
|
||||||
WHERE t.id = #{id}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="pageList" parameterType="java.util.HashMap" resultMap="XxlJobGroup">
|
|
||||||
SELECT <include refid="Base_Column_List" />
|
|
||||||
FROM xxl_job_group AS t
|
|
||||||
<trim prefix="WHERE" prefixOverrides="AND | OR" >
|
|
||||||
<if test="appname != null and appname != ''">
|
|
||||||
AND t.app_name like CONCAT(CONCAT('%', #{appname}), '%')
|
|
||||||
</if>
|
|
||||||
<if test="title != null and title != ''">
|
|
||||||
AND t.title like CONCAT(CONCAT('%', #{title}), '%')
|
|
||||||
</if>
|
|
||||||
</trim>
|
|
||||||
ORDER BY t.app_name, t.title, t.id ASC
|
|
||||||
LIMIT #{offset}, #{pagesize}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="pageListCount" parameterType="java.util.HashMap" resultType="int">
|
|
||||||
SELECT count(1)
|
|
||||||
FROM xxl_job_group AS t
|
|
||||||
<trim prefix="WHERE" prefixOverrides="AND | OR" >
|
|
||||||
<if test="appname != null and appname != ''">
|
|
||||||
AND t.app_name like CONCAT(CONCAT('%', #{appname}), '%')
|
|
||||||
</if>
|
|
||||||
<if test="title != null and title != ''">
|
|
||||||
AND t.title like CONCAT(CONCAT('%', #{title}), '%')
|
|
||||||
</if>
|
|
||||||
</trim>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
</mapper>
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user