feat: support InstanceQuery #158

This commit is contained in:
tjq 2021-01-16 11:40:54 +08:00
parent 64c36d402a
commit 0912964ec3
9 changed files with 125 additions and 21 deletions

View File

@ -289,6 +289,14 @@ public class OhMyClient {
return JSONObject.parseObject(post, INSTANCE_RESULT_TYPE);
}
public ResultDTO<List<InstanceInfoDTO>> queryInstanceInfo(PowerQuery powerQuery) {
powerQuery.setAppIdEq(appId);
MediaType jsonType = MediaType.parse("application/json; charset=utf-8");
String json = JsonUtils.toJSONStringUnsafe(powerQuery);
String post = postHA(OpenAPIConstant.QUERY_INSTANCE, RequestBody.create(jsonType, json));
return JSONObject.parseObject(post, LIST_INSTANCE_RESULT_TYPE);
}
/* ************* Workflow API list ************* */
/**
* Save one workflow

View File

@ -25,6 +25,8 @@ public class TypeStore {
public static final TypeReference<ResultDTO<InstanceInfoDTO>> INSTANCE_RESULT_TYPE = new TypeReference<ResultDTO<InstanceInfoDTO>>() {};
public static final TypeReference<ResultDTO<List<InstanceInfoDTO>>> LIST_INSTANCE_RESULT_TYPE = new TypeReference<ResultDTO<List<InstanceInfoDTO>>>(){};
public static final TypeReference<ResultDTO<WorkflowInfoDTO>> WF_RESULT_TYPE = new TypeReference<ResultDTO<WorkflowInfoDTO>>() {};
public static final TypeReference<ResultDTO<WorkflowInstanceInfoDTO>> WF_INSTANCE_RESULT_TYPE = new TypeReference<ResultDTO<WorkflowInstanceInfoDTO>>() {};

View File

@ -28,6 +28,7 @@ public class OpenAPIConstant {
public static final String RETRY_INSTANCE = "/retryInstance";
public static final String FETCH_INSTANCE_STATUS = "/fetchInstanceStatus";
public static final String FETCH_INSTANCE_INFO = "/fetchInstanceInfo";
public static final String QUERY_INSTANCE = "/queryInstance";
/* ************* Workflow 区 ************* */
public static final String SAVE_WORKFLOW = "/saveWorkflow";

View File

@ -1,6 +1,6 @@
package com.github.kfcfans.powerjob.server.common.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.github.kfcfans.powerjob.common.PowerJobException;
import com.github.kfcfans.powerjob.common.PowerQuery;
import com.google.common.collect.Lists;
@ -26,9 +26,10 @@ public class QueryConvertUtils {
return (Specification<T>) (root, query, cb) -> {
List<Predicate> predicates = Lists.newLinkedList();
Field[ ] fields = query.getClass().getDeclaredFields();
Field[] fields = powerQuery.getClass().getDeclaredFields();
try {
for (Field field : fields) {
field.setAccessible(true);
String fieldName = field.getName();
Object fieldValue = field.get(powerQuery);
if (fieldValue == null) {
@ -42,10 +43,10 @@ public class QueryConvertUtils {
predicates.add(cb.notEqual(root.get(colName), fieldValue));
} else if (fieldName.endsWith(PowerQuery.LIKE)) {
String colName = StringUtils.substringBeforeLast(fieldName, PowerQuery.LIKE);
predicates.add(cb.like(root.get(colName), (String) fieldValue));
predicates.add(cb.like(root.get(colName), convertLikeParams(fieldValue)));
} else if (fieldName.endsWith(PowerQuery.NOT_LIKE)) {
String colName = StringUtils.substringBeforeLast(fieldName, PowerQuery.NOT_LIKE);
predicates.add(cb.notLike(root.get(colName), (String) fieldValue));
predicates.add(cb.notLike(root.get(colName), convertLikeParams(fieldValue)));
} else if (fieldName.endsWith(PowerQuery.LESS_THAN)) {
String colName = StringUtils.substringBeforeLast(fieldName, PowerQuery.LESS_THAN);
predicates.add(cb.lessThan(root.get(colName), (Comparable)fieldValue));
@ -60,10 +61,10 @@ public class QueryConvertUtils {
predicates.add(cb.greaterThanOrEqualTo(root.get(colName), (Comparable)fieldValue));
} else if (fieldName.endsWith(PowerQuery.IN)) {
String colName = StringUtils.substringBeforeLast(fieldName, PowerQuery.IN);
predicates.add(root.get(colName).in(fieldValue));
predicates.add(root.get(colName).in(convertInParams(fieldValue)));
} else if (fieldName.endsWith(PowerQuery.NOT_IN)) {
String colName = StringUtils.substringBeforeLast(fieldName, PowerQuery.NOT_IN);
predicates.add(cb.not(root.get(colName).in(fieldValue)));
predicates.add(cb.not(root.get(colName).in(convertInParams(fieldValue))));
} else if (fieldName.endsWith(PowerQuery.IS_NULL)) {
String colName = StringUtils.substringBeforeLast(fieldName, PowerQuery.IS_NULL);
predicates.add(cb.isNull(root.get(colName)));
@ -73,16 +74,31 @@ public class QueryConvertUtils {
}
}
} catch (Exception e) {
log.warn("[QueryConvertUtils] convert failed for query: {}", JSON.toJSON(query));
log.warn("[QueryConvertUtils] convert failed for query: {}", query, e);
throw new PowerJobException("convert query object failed, maybe you should redesign your query object!");
}
if (powerQuery.getAppIdEq() != null) {
predicates.add(cb.equal(root.get("appId"), powerQuery.getAppIdEq()));
}
return query.where(predicates.toArray(new Predicate[0])).getRestriction();
};
}
public static void main(String[] args) {
String s = "appIdEq";
System.out.println(StringUtils.substringBeforeLast(s, "Eq"));
private static String convertLikeParams(Object o) {
String s = (String) o;
if (!s.startsWith("%")) {
s = "%" + s;
}
if (!s.endsWith("%")) {
s = s + "%";
}
return s;
}
private static Object[] convertInParams(Object o) {
// FastJSON, 永远滴神
return JSONArray.parseArray(JSONArray.toJSONString(o)).toArray();
}
}

View File

@ -3,6 +3,7 @@ package com.github.kfcfans.powerjob.server.persistence.core.repository;
import com.github.kfcfans.powerjob.server.persistence.core.model.InstanceInfoDO;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
@ -16,7 +17,7 @@ import java.util.List;
* @author tjq
* @since 2020/4/1
*/
public interface InstanceInfoRepository extends JpaRepository<InstanceInfoDO, Long> {
public interface InstanceInfoRepository extends JpaRepository<InstanceInfoDO, Long>, JpaSpecificationExecutor<InstanceInfoDO> {
/**
* 统计当前JOB有多少实例正在运行

View File

@ -2,10 +2,7 @@ package com.github.kfcfans.powerjob.server.service.instance;
import akka.actor.ActorSelection;
import akka.pattern.Patterns;
import com.github.kfcfans.powerjob.common.InstanceStatus;
import com.github.kfcfans.powerjob.common.PowerJobException;
import com.github.kfcfans.powerjob.common.RemoteConstant;
import com.github.kfcfans.powerjob.common.SystemInstanceResult;
import com.github.kfcfans.powerjob.common.*;
import com.github.kfcfans.powerjob.common.model.InstanceDetail;
import com.github.kfcfans.powerjob.common.request.ServerQueryInstanceStatusReq;
import com.github.kfcfans.powerjob.common.request.ServerStopInstanceReq;
@ -14,6 +11,7 @@ import com.github.kfcfans.powerjob.common.response.InstanceInfoDTO;
import com.github.kfcfans.powerjob.server.akka.OhMyServer;
import com.github.kfcfans.powerjob.server.common.constans.InstanceType;
import com.github.kfcfans.powerjob.server.common.redirect.DesignateServer;
import com.github.kfcfans.powerjob.server.common.utils.QueryConvertUtils;
import com.github.kfcfans.powerjob.server.common.utils.timewheel.TimerFuture;
import com.github.kfcfans.powerjob.server.persistence.core.model.InstanceInfoDO;
import com.github.kfcfans.powerjob.server.persistence.core.model.JobInfoDO;
@ -28,8 +26,10 @@ import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.Duration;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static com.github.kfcfans.powerjob.common.InstanceStatus.RUNNING;
import static com.github.kfcfans.powerjob.common.InstanceStatus.STOPPED;
@ -201,16 +201,21 @@ public class InstanceService {
}
}
public List<InstanceInfoDTO> queryInstanceInfo(PowerQuery powerQuery) {
return instanceInfoRepository
.findAll(QueryConvertUtils.autoConvert(powerQuery))
.stream()
.map(InstanceService::directConvert)
.collect(Collectors.toList());
}
/**
* 获取任务实例的信息
* @param instanceId 任务实例ID
* @return 任务实例的信息
*/
public InstanceInfoDTO getInstanceInfo(Long instanceId) {
InstanceInfoDO instanceInfoDO = fetchInstanceInfo(instanceId);
InstanceInfoDTO instanceInfoDTO = new InstanceInfoDTO();
BeanUtils.copyProperties(instanceInfoDO, instanceInfoDTO);
return instanceInfoDTO;
return directConvert(fetchInstanceInfo(instanceId));
}
/**
@ -276,4 +281,10 @@ public class InstanceService {
}
return instanceInfoDO;
}
private static InstanceInfoDTO directConvert(InstanceInfoDO instanceInfoDO) {
InstanceInfoDTO instanceInfoDTO = new InstanceInfoDTO();
BeanUtils.copyProperties(instanceInfoDO, instanceInfoDTO);
return instanceInfoDTO;
}
}

View File

@ -131,6 +131,11 @@ public class OpenAPIController {
return ResultDTO.success(instanceService.getInstanceInfo(instanceId));
}
@PostMapping(OpenAPIConstant.QUERY_INSTANCE)
public ResultDTO<List<InstanceInfoDTO>> queryInstance(@RequestBody PowerQuery powerQuery) {
return ResultDTO.success(instanceService.queryInstanceInfo(powerQuery));
}
/* ************* Workflow 区 ************* */
@PostMapping(OpenAPIConstant.SAVE_WORKFLOW)
public ResultDTO<Long> saveWorkflow(@RequestBody SaveWorkflowRequest request) throws Exception {

View File

@ -0,0 +1,59 @@
package com.github.kfcfans.powerjob.server.common.utils;
import com.alibaba.fastjson.JSONObject;
import com.github.kfcfans.powerjob.common.PowerQuery;
import com.github.kfcfans.powerjob.common.response.JobInfoDTO;
import com.github.kfcfans.powerjob.server.persistence.core.model.JobInfoDO;
import com.github.kfcfans.powerjob.server.service.JobService;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.time.DateUtils;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
/**
* test QueryConvertUtils
*
* @author tjq
* @since 2021/1/16
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class QueryConvertUtilsTest {
@Resource
private JobService jobService;
@Test
void autoConvert() {
JobInfoQuery jobInfoQuery = new JobInfoQuery();
jobInfoQuery.setAppIdEq(1L);
jobInfoQuery.setJobNameLike("DAG");
jobInfoQuery.setStatusIn(Lists.newArrayList(1));
jobInfoQuery.setGmtCreateGt(DateUtils.addDays(new Date(), -300));
List<JobInfoDTO> list = jobService.queryJob(jobInfoQuery);
System.out.println("size: " + list.size());
System.out.println(JSONObject.toJSONString(list));
}
@Getter
@Setter
public static class JobInfoQuery extends PowerQuery {
private String jobNameLike;
private Date gmtCreateGt;
private List<Integer> statusIn;
}
}

View File

@ -14,14 +14,15 @@ spring.servlet.multipart.max-request-size=209715200
####### 数据库配置 #######
spring.datasource.core.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.core.jdbc-url=jdbc:mysql://remotehost:3391/oms-daily?useUnicode=true&characterEncoding=UTF-8
spring.datasource.core.jdbc-url=jdbc:mysql://localhost:3306/powerjob-daily?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
spring.datasource.core.username=root
spring.datasource.core.password=No1Bug2Please3!
spring.datasource.core.hikari.maximum-pool-size=20
spring.datasource.core.hikari.minimum-idle=5
####### mongoDB配置非核心依赖可移除 #######
spring.data.mongodb.uri=mongodb://remotehost:27017/oms-daily
oms.mongodb.enable=true
spring.data.mongodb.uri=mongodb+srv://zqq:No1Bug2Please3!@cluster0.wie54.gcp.mongodb.net/powerjob_daily?retryWrites=true&w=majority
###### OhMyScheduler 自身配置(该配置只允许存在于 application.properties 文件中) ######
# akka ActorSystem 服务端口