This commit is contained in:
kk
2026-07-07 18:05:54 +08:00
commit d4ef46bf97
743 changed files with 159169 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
FROM bladex/alpine-java:openjdk17_cn_slim
LABEL maintainer="bladejava@qq.com"
RUN mkdir -p /blade/job
WORKDIR /blade/job
EXPOSE 7770
COPY ./target/blade-job.jar ./app.jar
ENTRYPOINT ["java", "--add-opens", "java.base/java.lang=ALL-UNNAMED", "--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
CMD ["--spring.profiles.active=test"]

View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>blade-ops</artifactId>
<groupId>org.springblade</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>blade-job</artifactId>
<name>${project.artifactId}</name>
<packaging>jar</packaging>
<dependencies>
<!--Blade-->
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-common</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-core-boot</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-http</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-swagger</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-powerjob</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<configuration>
<skip>${docker.fabric.skip}</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,44 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job;
import org.springblade.core.cloud.client.BladeCloudApplication;
import org.springblade.core.launch.BladeApplication;
import org.springblade.core.launch.constant.AppConstant;
/**
* 任务服务
*
* @author Chill
*/
@BladeCloudApplication
public class JobApplication {
public static void main(String[] args) {
BladeApplication.run(AppConstant.APPLICATION_JOB_NAME, JobApplication.class, args);
}
}

View File

@@ -0,0 +1,166 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.IsAdmin;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.job.pojo.entity.JobInfo;
import org.springblade.job.pojo.vo.JobInfoVO;
import org.springblade.job.service.IJobInfoService;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* 任务信息表 控制器
*
* @author BladeX
*/
@RestController
@AllArgsConstructor
@IsAdmin
@RequestMapping("/job-info")
@Tag(name = "任务信息表", description = "任务信息表接口")
public class JobInfoController extends BladeController {
private final IJobInfoService jobInfoService;
/**
* 任务信息表 详情
*/
@GetMapping("/detail")
@ApiOperationSupport(order = 1)
@Operation(summary = "详情", description = "传入jobInfo")
public R<JobInfo> detail(JobInfo jobInfo) {
JobInfo detail = jobInfoService.getOne(Condition.getQueryWrapper(jobInfo));
return R.data(detail);
}
/**
* 任务信息表 分页
*/
@GetMapping("/list")
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "传入jobInfo")
public R<IPage<JobInfo>> list(@Parameter(hidden = true) @RequestParam Map<String, Object> jobInfo, Query query) {
IPage<JobInfo> pages = jobInfoService.page(Condition.getPage(query), Condition.getQueryWrapper(jobInfo, JobInfo.class));
return R.data(pages);
}
/**
* 任务信息表 自定义分页
*/
@GetMapping("/page")
@ApiOperationSupport(order = 3)
@Operation(summary = "分页", description = "传入jobInfo")
public R<IPage<JobInfoVO>> page(JobInfoVO jobInfo, Query query) {
IPage<JobInfoVO> pages = jobInfoService.selectJobInfoPage(Condition.getPage(query), jobInfo);
return R.data(pages);
}
/**
* 任务信息表 新增
*/
@PostMapping("/save")
@ApiOperationSupport(order = 4)
@Operation(summary = "新增", description = "传入jobInfo")
public R save(@Valid @RequestBody JobInfo jobInfo) {
return R.status(jobInfoService.save(jobInfo));
}
/**
* 任务信息表 修改
*/
@PostMapping("/update")
@ApiOperationSupport(order = 5)
@Operation(summary = "修改", description = "传入jobInfo")
public R update(@Valid @RequestBody JobInfo jobInfo) {
return R.status(jobInfoService.updateById(jobInfo));
}
/**
* 任务信息表 新增或修改
*/
@PostMapping("/submit")
@ApiOperationSupport(order = 6)
@Operation(summary = "新增或修改", description = "传入jobInfo")
public R submit(@Valid @RequestBody JobInfo jobInfo) {
return R.status(jobInfoService.submitAndSync(jobInfo));
}
/**
* 任务信息表 删除
*/
@PostMapping("/remove")
@ApiOperationSupport(order = 7)
@Operation(summary = "删除", description = "传入ids")
public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.status(jobInfoService.removeAndSync(Func.toLongList(ids)));
}
/**
* 任务信息表 变更状态
*/
@PostMapping("/change")
@ApiOperationSupport(order = 8)
@Operation(summary = "变更状态", description = "传入id与status")
public R change(@Parameter(description = "主键", required = true) @RequestParam Long id, @Parameter(description = "是否启用", required = true) @RequestParam Integer enable) {
return R.status(jobInfoService.changeServerJob(id, enable));
}
/**
* 运行服务
*/
@PostMapping("run")
@ApiOperationSupport(order = 9)
@Operation(summary = "运行服务", description = "传入jobInfoId")
public R run(@Parameter(description = "主键", required = true) @RequestParam Long id) {
return R.status(jobInfoService.runServerJob(id));
}
/**
* 任务信息数据同步
*/
@PostMapping("sync")
@ApiOperationSupport(order = 10)
@Operation(summary = "任务信息数据同步", description = "任务信息数据同步")
public R sync() {
return R.status(jobInfoService.sync());
}
}

View File

@@ -0,0 +1,164 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.IsAdmin;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.job.pojo.entity.JobServer;
import org.springblade.job.pojo.vo.JobServerVO;
import org.springblade.job.service.IJobServerService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
* 任务服务表 控制器
*
* @author BladeX
*/
@RestController
@AllArgsConstructor
@IsAdmin
@RequestMapping("/job-server")
@Tag(name = "任务服务表", description = "任务服务表接口")
public class JobServerController extends BladeController {
private final IJobServerService jobServerService;
/**
* 任务服务表 详情
*/
@GetMapping("/detail")
@ApiOperationSupport(order = 1)
@Operation(summary = "详情", description = "传入jobServer")
public R<JobServer> detail(JobServer jobServer) {
JobServer detail = jobServerService.getOne(Condition.getQueryWrapper(jobServer));
return R.data(detail);
}
/**
* 任务服务表 分页
*/
@GetMapping("/list")
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "传入jobServer")
public R<IPage<JobServer>> list(@Parameter(hidden = true) @RequestParam Map<String, Object> jobServer, Query query) {
IPage<JobServer> pages = jobServerService.page(Condition.getPage(query), Condition.getQueryWrapper(jobServer, JobServer.class));
return R.data(pages);
}
/**
* 任务服务表 自定义分页
*/
@GetMapping("/page")
@ApiOperationSupport(order = 3)
@Operation(summary = "分页", description = "传入jobServer")
public R<IPage<JobServerVO>> page(JobServerVO jobServer, Query query) {
IPage<JobServerVO> pages = jobServerService.selectJobServerPage(Condition.getPage(query), jobServer);
return R.data(pages);
}
/**
* 任务服务表 新增
*/
@PostMapping("/save")
@ApiOperationSupport(order = 4)
@Operation(summary = "新增", description = "传入jobServer")
public R save(@Valid @RequestBody JobServer jobServer) {
return R.status(jobServerService.save(jobServer));
}
/**
* 任务服务表 修改
*/
@PostMapping("/update")
@ApiOperationSupport(order = 5)
@Operation(summary = "修改", description = "传入jobServer")
public R update(@Valid @RequestBody JobServer jobServer) {
return R.status(jobServerService.updateById(jobServer));
}
/**
* 任务服务表 新增或修改
*/
@PostMapping("/submit")
@ApiOperationSupport(order = 6)
@Operation(summary = "新增或修改", description = "传入jobServer")
public R submit(@Valid @RequestBody JobServer jobServer) {
return R.status(jobServerService.submitAndSync(jobServer));
}
/**
* 任务服务表 删除
*/
@PostMapping("/remove")
@ApiOperationSupport(order = 7)
@Operation(summary = "逻辑删除", description = "传入ids")
public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.status(jobServerService.deleteLogic(Func.toLongList(ids)));
}
/**
* 应用服务信息 列表
*/
@GetMapping("/select")
@ApiOperationSupport(order = 8)
@Operation(summary = "应用服务信息", description = "应用服务信息")
public R select() {
List<JobServer> list = jobServerService.list();
list.forEach(jobServer -> jobServer.setJobAppName(
jobServer.getJobAppName() + StringPool.COLON + StringPool.SPACE + StringPool.LEFT_BRACKET +
jobServer.getJobServerName() + StringPool.SPACE + StringPool.DASH + StringPool.SPACE + jobServer.getJobServerUrl() + StringPool.RIGHT_BRACKET)
);
return R.data(list);
}
/**
* 任务服务数据同步
*/
@PostMapping("sync")
@ApiOperationSupport(order = 9)
@Operation(summary = "任务服务数据同步", description = "任务服务数据同步")
public R sync() {
jobServerService.list().forEach(jobServerService::sync);
return R.success("同步完毕");
}
}

View File

@@ -0,0 +1,51 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.job.pojo.entity.JobInfo;
import org.springblade.job.pojo.vo.JobInfoVO;
import java.util.List;
/**
* 任务信息表 Mapper 接口
*
* @author BladeX
*/
public interface JobInfoMapper extends BaseMapper<JobInfo> {
/**
* 自定义分页
*
* @param page
* @param jobInfo
* @return
*/
List<JobInfoVO> selectJobInfoPage(IPage page, JobInfoVO jobInfo);
}

View File

@@ -0,0 +1,52 @@
<?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="org.springblade.job.mapper.JobInfoMapper">
<!-- 通用查询映射结果 -->
<resultMap id="jobInfoResultMap" type="org.springblade.job.pojo.entity.JobInfo">
<result column="id" property="id"/>
<result column="job_server_id" property="jobServerId"/>
<result column="job_id" property="jobId"/>
<result column="job_name" property="jobName"/>
<result column="job_description" property="jobDescription"/>
<result column="job_params" property="jobParams"/>
<result column="time_expression_type" property="timeExpressionType"/>
<result column="time_expression" property="timeExpression"/>
<result column="execute_type" property="executeType"/>
<result column="processor_type" property="processorType"/>
<result column="processor_info" property="processorInfo"/>
<result column="max_instance_num" property="maxInstanceNum"/>
<result column="concurrency" property="concurrency"/>
<result column="instance_time_limit" property="instanceTimeLimit"/>
<result column="instance_retry_num" property="instanceRetryNum"/>
<result column="task_retry_num" property="taskRetryNum"/>
<result column="min_cpu_cores" property="minCpuCores"/>
<result column="min_memory_space" property="minMemorySpace"/>
<result column="min_disk_space" property="minDiskSpace"/>
<result column="designated_workers" property="designatedWorkers"/>
<result column="max_worker_count" property="maxWorkerCount"/>
<result column="notify_user_ids" property="notifyUserIds"/>
<result column="enable" property="enable"/>
<result column="dispatch_strategy" property="dispatchStrategy"/>
<result column="lifecycle" property="lifecycle"/>
<result column="alert_threshold" property="alertThreshold"/>
<result column="statistic_window_len" property="statisticWindowLen"/>
<result column="silence_window_len" property="silenceWindowLen"/>
<result column="log_type" property="logType"/>
<result column="log_level" property="logLevel"/>
<result column="extra" property="extra"/>
<result column="create_user" property="createUser"/>
<result column="create_dept" property="createDept"/>
<result column="create_time" property="createTime"/>
<result column="update_user" property="updateUser"/>
<result column="update_time" property="updateTime"/>
<result column="status" property="status"/>
<result column="is_deleted" property="isDeleted"/>
</resultMap>
<select id="selectJobInfoPage" resultMap="jobInfoResultMap">
select * from blade_job_info where is_deleted = 0
</select>
</mapper>

View File

@@ -0,0 +1,51 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.job.pojo.entity.JobServer;
import org.springblade.job.pojo.vo.JobServerVO;
import java.util.List;
/**
* 任务服务表 Mapper 接口
*
* @author BladeX
*/
public interface JobServerMapper extends BaseMapper<JobServer> {
/**
* 自定义分页
*
* @param page
* @param jobServer
* @return
*/
List<JobServerVO> selectJobServerPage(IPage page, JobServerVO jobServer);
}

View File

@@ -0,0 +1,27 @@
<?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="org.springblade.job.mapper.JobServerMapper">
<!-- 通用查询映射结果 -->
<resultMap id="jobServerResultMap" type="org.springblade.job.pojo.entity.JobServer">
<result column="id" property="id"/>
<result column="job_server_name" property="jobServerName"/>
<result column="job_server_url" property="jobServerUrl"/>
<result column="job_app_name" property="jobAppName"/>
<result column="job_app_password" property="jobAppPassword"/>
<result column="job_remark" property="jobRemark"/>
<result column="create_user" property="createUser"/>
<result column="create_dept" property="createDept"/>
<result column="create_time" property="createTime"/>
<result column="update_user" property="updateUser"/>
<result column="update_time" property="updateTime"/>
<result column="status" property="status"/>
<result column="is_deleted" property="isDeleted"/>
</resultMap>
<select id="selectJobServerPage" resultMap="jobServerResultMap">
select * from blade_job_server where is_deleted = 0
</select>
</mapper>

View File

@@ -0,0 +1,56 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job.pojo.dto;
import lombok.Data;
import org.springblade.job.pojo.entity.JobInfo;
import org.springblade.job.pojo.entity.JobServer;
import tech.powerjob.client.PowerJobClient;
/**
* 任务数据DTO
*
* @author Chill
*/
@Data
public class JobDTO {
/**
* 任务信息类
*/
private JobInfo jobInfo;
/**
* 任务服务类
*/
private JobServer jobServer;
/**
* 任务客户端类
*/
private PowerJobClient powerJobClient;
}

View File

@@ -0,0 +1,202 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job.pojo.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.core.mp.base.BaseEntity;
import java.io.Serial;
import java.math.BigDecimal;
/**
* 任务信息表 实体类
*
* @author BladeX
*/
@Data
@TableName("blade_job_info")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "任务信息表")
public class JobInfo extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 任务服务ID
*/
@Schema(description = "任务服务ID")
private Long jobServerId;
/**
* 任务 ID可选null 代表创建任务,否则填写需要修改的任务 ID
*/
@Schema(description = "任务 ID可选null 代表创建任务,否则填写需要修改的任务 ID")
private Long jobId;
/**
* 任务名称
*/
@Schema(description = "任务名称")
private String jobName;
/**
* 任务描述
*/
@Schema(description = "任务描述")
private String jobDescription;
/**
* 任务参数Processor#process 方法入参 TaskContext 对象的 jobParams 字段
*/
@Schema(description = "任务参数Processor#process 方法入参 TaskContext 对象的 jobParams 字段")
private String jobParams;
/**
* 时间表达式类型,枚举值
*/
@Schema(description = "时间表达式类型,枚举值")
private Integer timeExpressionType;
/**
* 时间表达式,填写类型由 timeExpressionType 决定,比如 CRON 需要填写 CRON 表达式
*/
@Schema(description = "时间表达式,填写类型由 timeExpressionType 决定,比如 CRON 需要填写 CRON 表达式")
private String timeExpression;
/**
* 执行类型,枚举值
*/
@Schema(description = "执行类型,枚举值")
private Integer executeType;
/**
* 处理器类型,枚举值
*/
@Schema(description = "处理器类型,枚举值")
private Integer processorType;
/**
* 处理器参数,填写类型由 processorType 决定如Java 处理器需要填写全限定类名com.github.kfcfans.oms.processors.demo.MapReduceProcessorDemo
*/
@Schema(description = "处理器参数,填写类型由 processorType 决定如Java 处理器需要填写全限定类名com.github.kfcfans.oms.processors.demo.MapReduceProcessorDemo")
private String processorInfo;
/**
* 最大实例数,该任务同时执行的数量(任务和实例就像是类和对象的关系,任务被调度执行后被称为实例)
*/
@Schema(description = "最大实例数,该任务同时执行的数量(任务和实例就像是类和对象的关系,任务被调度执行后被称为实例)")
private Integer maxInstanceNum;
/**
* 单机线程并发数表示该实例执行过程中每个Worker 使用的线程数量
*/
@Schema(description = "单机线程并发数表示该实例执行过程中每个Worker 使用的线程数量")
private Integer concurrency;
/**
* 任务实例运行时间限制0 代表无任何限制,超时会被打断并判定为执行失败
*/
@Schema(description = "任务实例运行时间限制0 代表无任何限制,超时会被打断并判定为执行失败")
private Long instanceTimeLimit;
/**
* instanceRetryNum 任务实例重试次数,整个任务失败时重试,代价大,不推荐使用
*/
@Schema(description = "instanceRetryNum 任务实例重试次数,整个任务失败时重试,代价大,不推荐使用")
private Integer instanceRetryNum;
/**
* taskRetryNum Task 重试次数,每个子 Task 失败后单独重试,代价小,推荐使用
*/
@Schema(description = "taskRetryNum Task 重试次数,每个子 Task 失败后单独重试,代价小,推荐使用")
private Integer taskRetryNum;
/**
* minCpuCores 最小可用 CPU 核心数CPU 可用核心数小于该值的 Worker 将不会执行该任务0 代表无任何限制
*/
@Schema(description = "minCpuCores 最小可用 CPU 核心数CPU 可用核心数小于该值的 Worker 将不会执行该任务0 代表无任何限制")
private BigDecimal minCpuCores;
/**
* 最小内存大小GB可用内存小于该值的Worker 将不会执行该任务0 代表无任何限制
*/
@Schema(description = "最小内存大小GB可用内存小于该值的Worker 将不会执行该任务0 代表无任何限制")
private BigDecimal minMemorySpace;
/**
* 最小磁盘大小GB可用磁盘空间小于该值的Worker 将不会执行该任务0 代表无任何限制
*/
@Schema(description = "最小磁盘大小GB可用磁盘空间小于该值的Worker 将不会执行该任务0 代表无任何限制")
private BigDecimal minDiskSpace;
/**
* 指定机器执行,设置该参数后只有列表中的机器允许执行该任务,空代表不指定机器
*/
@Schema(description = "指定机器执行,设置该参数后只有列表中的机器允许执行该任务,空代表不指定机器")
private String designatedWorkers;
/**
* 最大执行机器数量限定调动执行的机器数量0代表无限制
*/
@Schema(description = "最大执行机器数量限定调动执行的机器数量0代表无限制")
private Integer maxWorkerCount;
/**
* 接收报警的用户 ID 列表
*/
@Schema(description = "接收报警的用户 ID 列表")
private String notifyUserIds;
/**
* 是否启用该任务,未启用的任务不会被调度
*/
@Schema(description = "是否启用该任务,未启用的任务不会被调度")
private Integer enable;
/**
* 调度策略枚举目前支持随机RANDOM和 健康度优先HEALTH_FIRST
*/
@Schema(description = "调度策略枚举目前支持随机RANDOM和 健康度优先HEALTH_FIRST")
private Integer dispatchStrategy;
/**
* lifecycle 生命周期(预留,用于指定定时调度任务的生效时间范围)
*/
@Schema(description = "lifecycle 生命周期(预留,用于指定定时调度任务的生效时间范围)")
private String lifecycle;
/**
* 错误阈值0代表不限制
*/
@Schema(description = "错误阈值0代表不限制")
private Integer alertThreshold;
/**
* 统计的窗口长度(s)0代表不限制
*/
@Schema(description = "统计的窗口长度(s)0代表不限制")
private Integer statisticWindowLen;
/**
* 沉默时间窗口(s)0代表不限制
*/
@Schema(description = "沉默时间窗口(s)0代表不限制")
private Integer silenceWindowLen;
/**
* 日志配置
*/
@Schema(description = "日志配置")
private Integer logType;
/**
* 日志配置
*/
@Schema(description = "日志级别")
private Integer logLevel;
/**
* 扩展字段供开发者使用用于功能扩展powerjob 自身不会使用该字段)
*/
@Schema(description = "扩展字段供开发者使用用于功能扩展powerjob 自身不会使用该字段)")
private String extra;
}

View File

@@ -0,0 +1,76 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job.pojo.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.core.mp.base.BaseEntity;
import java.io.Serial;
/**
* 任务服务表 实体类
*
* @author BladeX
*/
@Data
@TableName("blade_job_server")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "任务服务表")
public class JobServer extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 任务服务名称
*/
@Schema(description = "任务服务名称")
private String jobServerName;
/**
* 任务服务器地址
*/
@Schema(description = "任务服务器地址")
private String jobServerUrl;
/**
* 任务应用名称
*/
@Schema(description = "任务应用名称")
private String jobAppName;
/**
* 任务应用密码
*/
@Schema(description = "任务应用密码")
private String jobAppPassword;
/**
* 任务备注
*/
@Schema(description = "任务备注")
private String jobRemark;
}

View File

@@ -0,0 +1,45 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job.pojo.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.job.pojo.entity.JobInfo;
import java.io.Serial;
/**
* 任务信息表 视图实体类
*
* @author BladeX
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class JobInfoVO extends JobInfo {
@Serial
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,45 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job.pojo.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.job.pojo.entity.JobServer;
import java.io.Serial;
/**
* 任务服务表 视图实体类
*
* @author BladeX
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class JobServerVO extends JobServer {
@Serial
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,35 @@
package org.springblade.job.processor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import tech.powerjob.worker.core.processor.ProcessResult;
import tech.powerjob.worker.core.processor.TaskContext;
import tech.powerjob.worker.core.processor.sdk.BasicProcessor;
import tech.powerjob.worker.log.OmsLogger;
// 支持 SpringBean 的形式
@Slf4j
@Component
public class ProcessorDemo implements BasicProcessor {
@Override
public ProcessResult process(TaskContext context) {
// 在线日志功能,可以直接在控制台查看任务日志,非常便捷
OmsLogger omsLogger = context.getOmsLogger();
omsLogger.info("BasicProcessorDemo start to process, current JobParams is {}.", context.getJobParams());
// TaskContext为任务的上下文信息包含了在控制台录入的任务元数据常用字段为
// jobParams任务参数在控制台录入instanceParams任务实例参数通过 OpenAPI 触发的任务实例才可能存在该参数)
// 进行实际处理...
log.info("============== ProcessorDemo#process ==============");
log.info("hello blade");
log.info("============== ProcessorDemo#process ==============");
// 返回结果,该结果会被持久化到数据库,在前端页面直接查看,极为方便
return new ProcessResult(true, "result is success");
}
}

View File

@@ -0,0 +1,88 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.mp.base.BaseService;
import org.springblade.job.pojo.entity.JobInfo;
import org.springblade.job.pojo.vo.JobInfoVO;
import java.util.List;
/**
* 任务信息表 服务类
*
* @author BladeX
*/
public interface IJobInfoService extends BaseService<JobInfo> {
/**
* 自定义分页
*
* @param page
* @param jobInfo
* @return
*/
IPage<JobInfoVO> selectJobInfoPage(IPage<JobInfoVO> page, JobInfoVO jobInfo);
/**
* 保存并同步
*
* @return
*/
Boolean submitAndSync(JobInfo jobInfo);
/**
* 删除并同步
*
* @return
*/
Boolean removeAndSync(List<Long> ids);
/**
* 启用禁用服务
*
* @param id 任务服务ID
* @param enable 是否启用
* @return
*/
Boolean changeServerJob(Long id, Integer enable);
/**
* 运行服务
*
* @param id 任务服务ID
* @return
*/
Boolean runServerJob(Long id);
/**
* 数据同步
*
* @return
*/
Boolean sync();
}

View File

@@ -0,0 +1,64 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.mp.base.BaseService;
import org.springblade.job.pojo.entity.JobServer;
import org.springblade.job.pojo.vo.JobServerVO;
/**
* 任务服务表 服务类
*
* @author BladeX
*/
public interface IJobServerService extends BaseService<JobServer> {
/**
* 自定义分页
*
* @param page
* @param jobServer
* @return
*/
IPage<JobServerVO> selectJobServerPage(IPage<JobServerVO> page, JobServerVO jobServer);
/**
* 保存并同步
*
* @param jobServer
* @return
*/
Boolean submitAndSync(JobServer jobServer);
/**
* 同步数据
*
* @param jobServer
* @return
*/
Boolean sync(JobServer jobServer);
}

View File

@@ -0,0 +1,344 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.powerjob.constant.PowerJobConstant;
import org.springblade.core.tool.jackson.JsonUtil;
import org.springblade.core.tool.utils.ConvertUtil;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.job.pojo.dto.JobDTO;
import org.springblade.job.pojo.entity.JobInfo;
import org.springblade.job.pojo.entity.JobServer;
import org.springblade.job.mapper.JobInfoMapper;
import org.springblade.job.service.IJobInfoService;
import org.springblade.job.service.IJobServerService;
import org.springblade.job.pojo.vo.JobInfoVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tech.powerjob.client.PowerJobClient;
import tech.powerjob.common.enums.DispatchStrategy;
import tech.powerjob.common.enums.ExecuteType;
import tech.powerjob.common.enums.ProcessorType;
import tech.powerjob.common.enums.TimeExpressionType;
import tech.powerjob.common.model.AlarmConfig;
import tech.powerjob.common.model.LifeCycle;
import tech.powerjob.common.model.LogConfig;
import tech.powerjob.common.request.http.SaveJobInfoRequest;
import tech.powerjob.common.response.JobInfoDTO;
import tech.powerjob.common.response.ResultDTO;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
/**
* 任务信息表 服务实现类
*
* @author BladeX
*/
@Service
@AllArgsConstructor
public class JobInfoServiceImpl extends BaseServiceImpl<JobInfoMapper, JobInfo> implements IJobInfoService {
private final IJobServerService jobServerService;
@Override
public IPage<JobInfoVO> selectJobInfoPage(IPage<JobInfoVO> page, JobInfoVO jobInfo) {
return page.setRecords(baseMapper.selectJobInfoPage(page, jobInfo));
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean submitAndSync(JobInfo jobInfo) {
//获取应用分组服务端信息
JobServer jobServer = jobServerService.getById(jobInfo.getJobServerId());
//构建Job客户端
PowerJobClient client = new PowerJobClient(jobServer.getJobServerUrl(), jobServer.getJobAppName(), jobServer.getJobAppPassword());
SaveJobInfoRequest request = convertToServer(jobInfo);
//获取上传结果
ResultDTO<Long> result = client.saveJob(request);
if (result.isSuccess()) {
jobInfo.setJobId(result.getData());
return this.saveOrUpdate(jobInfo);
} else {
throw new ServiceException(result.getMessage());
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean removeAndSync(List<Long> ids) {
ids.forEach(id -> {
JobDTO jobDTO = JobData(id);
if (Func.isNotEmpty(jobDTO)) {
JobInfo jobInfo = jobDTO.getJobInfo();
PowerJobClient powerJobClient = jobDTO.getPowerJobClient();
//删除服务数据
ResultDTO<Void> result = powerJobClient.deleteJob(jobInfo.getJobId());
if (result.isSuccess()) {
this.removeById(id);
} else {
throw new ServiceException(result.getMessage());
}
}
});
return true;
}
@Override
public Boolean changeServerJob(Long id, Integer enable) {
JobDTO jobDTO = JobData(id);
if (Func.isNotEmpty(jobDTO)) {
JobInfo jobInfo = jobDTO.getJobInfo();
PowerJobClient powerJobClient = jobDTO.getPowerJobClient();
//更换服务端状态
ResultDTO<Void> result = (enable == PowerJobConstant.JOB_ENABLED) ?
powerJobClient.enableJob(jobInfo.getJobId()) :
powerJobClient.disableJob(jobInfo.getJobId());
//删除客户端数据
if (result.isSuccess()) {
return this.update(Wrappers.<JobInfo>update().lambda().set(JobInfo::getEnable, enable).eq(JobInfo::getId, id));
} else {
throw new ServiceException(result.getMessage());
}
}
return false;
}
@Override
public Boolean runServerJob(Long id) {
JobDTO jobDTO = JobData(id);
if (Func.isNotEmpty(jobDTO)) {
JobInfo jobInfo = jobDTO.getJobInfo();
PowerJobClient powerJobClient = jobDTO.getPowerJobClient();
ResultDTO<Long> result = powerJobClient.runJob(jobInfo.getJobId());
return result.isSuccess();
}
return false;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean sync() {
//任务信息列表
List<JobInfo> jobInfos = this.list();
//任务服务列表
List<JobServer> jobServers = jobServerService.list();
//按应用分组
Map<Long, List<JobInfo>> jobGroups = jobInfos.stream().collect(Collectors.groupingBy(JobInfo::getJobServerId));
//处理服务端数据下载
jobServers.forEach(jobServer -> {
//构建Job客户端
PowerJobClient client = new PowerJobClient(jobServer.getJobServerUrl(), jobServer.getJobAppName(), jobServer.getJobAppPassword());
//从服务端获取数据
List<JobInfoDTO> serverInfoList = Optional.ofNullable(client.fetchAllJob())
.filter(ResultDTO::isSuccess)
.map(ResultDTO::getData)
.orElseGet(ArrayList::new);
//获取客户端数据
List<JobInfo> localInfoList = jobGroups.get(jobServer.getId());
//处理需要从服务端下载的数据
List<JobInfoDTO> jobInfoDTOList = serverInfoList.stream()
.filter(serverData -> serverData.getStatus() != PowerJobConstant.JOB_DELETED)
.filter(serverData -> Func.isEmpty(localInfoList) || localInfoList.stream().noneMatch(localData -> Func.equalsSafe(localData.getJobId(), serverData.getId())))
.collect(Collectors.toList());
List<JobInfo> dataToDownload = convertToLocalList(jobInfoDTOList, jobServer.getId());
//调用本地Service保存数据
this.saveBatch(dataToDownload);
});
//处理客户端数据上传
jobGroups.forEach((jobServerId, localInfoList) -> {
//获取应用分组服务端信息
JobServer jobServer = jobServers.stream().filter(js -> Func.equalsSafe(js.getId(), jobServerId))
.findFirst().orElseThrow(() -> new ServiceException(PowerJobConstant.JOB_SYNC_ALERT));
//构建Job客户端
PowerJobClient client = new PowerJobClient(jobServer.getJobServerUrl(), jobServer.getJobAppName(), jobServer.getJobAppPassword());
//处理需要上传到服务端的数据
localInfoList.forEach(localData -> {
//转换数据格式
SaveJobInfoRequest data = convertToServer(localData);
//调用OpenAPI接口上传数据
ResultDTO<Long> saveResult = client.saveJob(data);
if (saveResult.isSuccess()) {
//更新服务端JobId至客户端
this.update(Wrappers.<JobInfo>update().lambda().set(JobInfo::getJobId, saveResult.getData()).eq(JobInfo::getId, localData.getId()));
} else {
throw new ServiceException(saveResult.getMessage());
}
});
});
return true;
}
/**
* 获取Job数据集合
*
* @param jobInfoId 服务信息ID
* @return PowerJobClient
*/
public JobDTO JobData(Long jobInfoId) {
//构建DTO类
JobDTO jobDTO = new JobDTO();
//获取任务信息
JobInfo jobInfo = this.getById(jobInfoId);
jobDTO.setJobInfo(jobInfo);
if (Func.isEmpty(jobInfo.getJobId())) {
throw new ServiceException(PowerJobConstant.JOB_SYNC_ALERT);
}
if (Func.isNotEmpty(jobInfo.getJobServerId())) {
//获取应用分组服务端信息
JobServer jobServer = jobServerService.getById(jobInfo.getJobServerId());
jobDTO.setJobServer(jobServer);
//构建Job客户端
PowerJobClient powerJobClient = new PowerJobClient(jobServer.getJobServerUrl(), jobServer.getJobAppName(), jobServer.getJobAppPassword());
jobDTO.setPowerJobClient(powerJobClient);
return jobDTO;
}
return null;
}
/**
* 服务端Job列表转换
*
* @param jobInfoList 本地任务信息列表
* @return List<SaveJobInfoRequest>
*/
public List<SaveJobInfoRequest> convertToServerList(List<JobInfo> jobInfoList) {
return jobInfoList.stream().map(this::convertToServer).collect(Collectors.toList());
}
/**
* 本地Job列表转换
*
* @param jobInfoDTOList 服务端任务信息列表
* @return List<JobInfo>
*/
public List<JobInfo> convertToLocalList(List<JobInfoDTO> jobInfoDTOList, Long jobServerId) {
return jobInfoDTOList.stream().map(jobInfoDTO -> convertToLocal(jobInfoDTO, jobServerId)).collect(Collectors.toList());
}
/**
* 服务端Job单个转换
*
* @param jobInfo 本地任务信息
* @return SaveJobInfoRequest
*/
public SaveJobInfoRequest convertToServer(JobInfo jobInfo) {
SaveJobInfoRequest saveJobInfoRequest = new SaveJobInfoRequest();
if (Func.toLong(jobInfo.getJobId()) > 0L) {
saveJobInfoRequest.setId(jobInfo.getJobId());
}
saveJobInfoRequest.setJobName(jobInfo.getJobName());
saveJobInfoRequest.setJobDescription(jobInfo.getJobDescription());
saveJobInfoRequest.setJobParams(jobInfo.getJobParams());
saveJobInfoRequest.setTimeExpressionType(TimeExpressionType.of(jobInfo.getTimeExpressionType()));
saveJobInfoRequest.setTimeExpression(jobInfo.getTimeExpression());
saveJobInfoRequest.setExecuteType(ExecuteType.of(jobInfo.getExecuteType()));
saveJobInfoRequest.setProcessorType(ProcessorType.of(jobInfo.getProcessorType()));
saveJobInfoRequest.setProcessorInfo(jobInfo.getProcessorInfo());
saveJobInfoRequest.setMaxInstanceNum(jobInfo.getMaxInstanceNum());
saveJobInfoRequest.setConcurrency(jobInfo.getConcurrency());
saveJobInfoRequest.setInstanceTimeLimit(jobInfo.getInstanceTimeLimit());
saveJobInfoRequest.setInstanceRetryNum(jobInfo.getInstanceRetryNum());
saveJobInfoRequest.setTaskRetryNum(jobInfo.getTaskRetryNum());
saveJobInfoRequest.setMinCpuCores(jobInfo.getMinCpuCores().doubleValue());
saveJobInfoRequest.setMinMemorySpace(jobInfo.getMinMemorySpace().doubleValue());
saveJobInfoRequest.setMinDiskSpace(jobInfo.getMinDiskSpace().doubleValue());
saveJobInfoRequest.setDesignatedWorkers(jobInfo.getDesignatedWorkers());
saveJobInfoRequest.setMaxWorkerCount(jobInfo.getMaxWorkerCount());
saveJobInfoRequest.setNotifyUserIds(Func.toLongList(jobInfo.getNotifyUserIds()));
saveJobInfoRequest.setEnable(jobInfo.getEnable() == 1);
saveJobInfoRequest.setDispatchStrategy(DispatchStrategy.of(jobInfo.getDispatchStrategy()));
saveJobInfoRequest.setAlarmConfig(new AlarmConfig(jobInfo.getAlertThreshold(), jobInfo.getStatisticWindowLen(), jobInfo.getSilenceWindowLen()));
saveJobInfoRequest.setLogConfig(new LogConfig().setLevel(jobInfo.getLogLevel()).setType(jobInfo.getLogType()));
if (Func.isNotEmpty(jobInfo.getLifecycle())) {
LifeCycle lifeCycle = new LifeCycle();
String[] lifeCycleArr = Func.toStrArray(jobInfo.getLifecycle());
lifeCycle.setStart(DateUtil.parse(lifeCycleArr[0], DateUtil.PATTERN_DATETIME).getTime());
lifeCycle.setEnd(DateUtil.parse(lifeCycleArr[1], DateUtil.PATTERN_DATETIME).getTime());
saveJobInfoRequest.setLifeCycle(lifeCycle);
}
saveJobInfoRequest.setExtra(jobInfo.getExtra());
return saveJobInfoRequest;
}
/**
* 本地Job单个转换
*
* @param jobInfoDTO 服务端任务信息
* @return SaveJobInfoRequest
*/
public JobInfo convertToLocal(JobInfoDTO jobInfoDTO, Long jobServerId) {
JobInfo jobInfo = new JobInfo();
jobInfo.setJobServerId(jobServerId);
jobInfo.setJobId(jobInfoDTO.getId());
jobInfo.setJobName(jobInfoDTO.getJobName());
jobInfo.setJobDescription(jobInfoDTO.getJobDescription());
jobInfo.setJobParams(jobInfoDTO.getJobParams());
jobInfo.setTimeExpressionType(jobInfoDTO.getTimeExpressionType());
jobInfo.setTimeExpression(jobInfoDTO.getTimeExpression());
jobInfo.setExecuteType(jobInfoDTO.getExecuteType());
jobInfo.setProcessorType(jobInfoDTO.getProcessorType());
jobInfo.setProcessorInfo(jobInfoDTO.getProcessorInfo());
jobInfo.setMaxInstanceNum(jobInfoDTO.getMaxInstanceNum());
jobInfo.setConcurrency(jobInfoDTO.getConcurrency());
jobInfo.setInstanceTimeLimit(jobInfoDTO.getInstanceTimeLimit());
jobInfo.setInstanceRetryNum(jobInfoDTO.getInstanceRetryNum());
jobInfo.setTaskRetryNum(jobInfoDTO.getTaskRetryNum());
jobInfo.setMinCpuCores(ConvertUtil.convert(jobInfoDTO.getMinCpuCores(), BigDecimal.class));
jobInfo.setMinMemorySpace(ConvertUtil.convert(jobInfoDTO.getMinMemorySpace(), BigDecimal.class));
jobInfo.setMinDiskSpace(ConvertUtil.convert(jobInfoDTO.getMinDiskSpace(), BigDecimal.class));
jobInfo.setDesignatedWorkers(jobInfoDTO.getDesignatedWorkers());
jobInfo.setMaxWorkerCount(jobInfoDTO.getMaxWorkerCount());
jobInfo.setNotifyUserIds(jobInfoDTO.getNotifyUserIds());
jobInfo.setEnable(jobInfoDTO.getStatus());
jobInfo.setDispatchStrategy(jobInfoDTO.getDispatchStrategy());
if (Func.isNotEmpty(jobInfoDTO.getLifecycle()) && !Func.equalsSafe(jobInfoDTO.getLifecycle(), StringPool.EMPTY_JSON)) {
LifeCycle lifeCycle = JsonUtil.parse(jobInfoDTO.getLifecycle(), LifeCycle.class);
String start = DateUtil.format(new Date(lifeCycle.getStart()), DateUtil.PATTERN_DATETIME);
String end = DateUtil.format(new Date(lifeCycle.getEnd()), DateUtil.PATTERN_DATETIME);
jobInfo.setLifecycle(start + StringPool.COMMA + end);
}
if (Func.isNotEmpty(jobInfoDTO.getAlarmConfig())) {
jobInfo.setAlertThreshold(jobInfoDTO.getAlarmConfig().getAlertThreshold());
jobInfo.setStatisticWindowLen(jobInfoDTO.getAlarmConfig().getStatisticWindowLen());
jobInfo.setSilenceWindowLen(jobInfoDTO.getAlarmConfig().getSilenceWindowLen());
}
if (Func.isNotEmpty(jobInfoDTO.getLogConfig())) {
jobInfo.setLogType(jobInfoDTO.getLogConfig().getType());
jobInfo.setLogLevel(jobInfoDTO.getLogConfig().getLevel());
}
jobInfo.setExtra(jobInfoDTO.getExtra());
return jobInfo;
}
}

View File

@@ -0,0 +1,71 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.core.type.TypeReference;
import org.springblade.core.http.util.HttpUtil;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.tool.jackson.JsonUtil;
import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.Func;
import org.springblade.job.pojo.entity.JobServer;
import org.springblade.job.mapper.JobServerMapper;
import org.springblade.job.service.IJobServerService;
import org.springblade.job.pojo.vo.JobServerVO;
import org.springframework.stereotype.Service;
import tech.powerjob.common.response.ResultDTO;
/**
* 任务服务表 服务实现类
*
* @author BladeX
*/
@Service
public class JobServerServiceImpl extends BaseServiceImpl<JobServerMapper, JobServer> implements IJobServerService {
@Override
public IPage<JobServerVO> selectJobServerPage(IPage<JobServerVO> page, JobServerVO jobServer) {
return page.setRecords(baseMapper.selectJobServerPage(page, jobServer));
}
@Override
public Boolean submitAndSync(JobServer jobServer) {
if (Func.isEmpty(jobServer.getId())) {
this.sync(jobServer);
}
return this.saveOrUpdate(jobServer);
}
@Override
public Boolean sync(JobServer jobServer) {
Kv appInfo = Kv.create().set("appName", jobServer.getJobAppName()).set("password", jobServer.getJobAppPassword());
String data = HttpUtil.postJson(jobServer.getJobServerUrl() + "/appInfo/save", JsonUtil.toJson(appInfo));
ResultDTO<Void> result = JsonUtil.parse(data, new TypeReference<ResultDTO<Void>>() {});
return result.isSuccess();
}
}

View File

@@ -0,0 +1,17 @@
#服务器端口
server:
port: 7770
#job服务配置
powerjob:
worker:
app-name: ${spring.application.name}
port: 27777
server-address: 127.0.0.1:7700
#数据源配置
spring:
datasource:
url: ${blade.datasource.dev.url}
username: ${blade.datasource.dev.username}
password: ${blade.datasource.dev.password}

View File

@@ -0,0 +1,18 @@
#服务器端口
server:
port: 7770
#job服务配置
powerjob:
worker:
app-name: ${spring.application.name}
port: 27777
server-address: 127.0.0.1:7700
#数据源配置
spring:
datasource:
url: ${blade.datasource.prod.url}
username: ${blade.datasource.prod.username}
password: ${blade.datasource.prod.password}

View File

@@ -0,0 +1,17 @@
#服务器端口
server:
port: 7770
#job服务配置
powerjob:
worker:
app-name: ${spring.application.name}
port: 27777
server-address: 127.0.0.1:7700
#数据源配置
spring:
datasource:
url: ${blade.datasource.test.url}
username: ${blade.datasource.test.username}
password: ${blade.datasource.test.password}