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); 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 ************* */ /* ************* Workflow API list ************* */
/** /**
* Save one workflow * 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<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<WorkflowInfoDTO>> WF_RESULT_TYPE = new TypeReference<ResultDTO<WorkflowInfoDTO>>() {};
public static final TypeReference<ResultDTO<WorkflowInstanceInfoDTO>> WF_INSTANCE_RESULT_TYPE = new TypeReference<ResultDTO<WorkflowInstanceInfoDTO>>() {}; 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 RETRY_INSTANCE = "/retryInstance";
public static final String FETCH_INSTANCE_STATUS = "/fetchInstanceStatus"; public static final String FETCH_INSTANCE_STATUS = "/fetchInstanceStatus";
public static final String FETCH_INSTANCE_INFO = "/fetchInstanceInfo"; public static final String FETCH_INSTANCE_INFO = "/fetchInstanceInfo";
public static final String QUERY_INSTANCE = "/queryInstance";
/* ************* Workflow 区 ************* */ /* ************* Workflow 区 ************* */
public static final String SAVE_WORKFLOW = "/saveWorkflow"; public static final String SAVE_WORKFLOW = "/saveWorkflow";

View File

@ -1,6 +1,6 @@
package com.github.kfcfans.powerjob.server.common.utils; 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.PowerJobException;
import com.github.kfcfans.powerjob.common.PowerQuery; import com.github.kfcfans.powerjob.common.PowerQuery;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
@ -26,9 +26,10 @@ public class QueryConvertUtils {
return (Specification<T>) (root, query, cb) -> { return (Specification<T>) (root, query, cb) -> {
List<Predicate> predicates = Lists.newLinkedList(); List<Predicate> predicates = Lists.newLinkedList();
Field[ ] fields = query.getClass().getDeclaredFields(); Field[] fields = powerQuery.getClass().getDeclaredFields();
try { try {
for (Field field : fields) { for (Field field : fields) {
field.setAccessible(true);
String fieldName = field.getName(); String fieldName = field.getName();
Object fieldValue = field.get(powerQuery); Object fieldValue = field.get(powerQuery);
if (fieldValue == null) { if (fieldValue == null) {
@ -42,10 +43,10 @@ public class QueryConvertUtils {
predicates.add(cb.notEqual(root.get(colName), fieldValue)); predicates.add(cb.notEqual(root.get(colName), fieldValue));
} else if (fieldName.endsWith(PowerQuery.LIKE)) { } else if (fieldName.endsWith(PowerQuery.LIKE)) {
String colName = StringUtils.substringBeforeLast(fieldName, 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)) { } else if (fieldName.endsWith(PowerQuery.NOT_LIKE)) {
String colName = StringUtils.substringBeforeLast(fieldName, 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)) { } else if (fieldName.endsWith(PowerQuery.LESS_THAN)) {
String colName = StringUtils.substringBeforeLast(fieldName, PowerQuery.LESS_THAN); String colName = StringUtils.substringBeforeLast(fieldName, PowerQuery.LESS_THAN);
predicates.add(cb.lessThan(root.get(colName), (Comparable)fieldValue)); 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)); predicates.add(cb.greaterThanOrEqualTo(root.get(colName), (Comparable)fieldValue));
} else if (fieldName.endsWith(PowerQuery.IN)) { } else if (fieldName.endsWith(PowerQuery.IN)) {
String colName = StringUtils.substringBeforeLast(fieldName, 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)) { } else if (fieldName.endsWith(PowerQuery.NOT_IN)) {
String colName = StringUtils.substringBeforeLast(fieldName, 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)) { } else if (fieldName.endsWith(PowerQuery.IS_NULL)) {
String colName = StringUtils.substringBeforeLast(fieldName, PowerQuery.IS_NULL); String colName = StringUtils.substringBeforeLast(fieldName, PowerQuery.IS_NULL);
predicates.add(cb.isNull(root.get(colName))); predicates.add(cb.isNull(root.get(colName)));
@ -73,16 +74,31 @@ public class QueryConvertUtils {
} }
} }
} catch (Exception e) { } 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!"); 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(); return query.where(predicates.toArray(new Predicate[0])).getRestriction();
}; };
} }
public static void main(String[] args) { private static String convertLikeParams(Object o) {
String s = "appIdEq"; String s = (String) o;
System.out.println(StringUtils.substringBeforeLast(s, "Eq")); 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.github.kfcfans.powerjob.server.persistence.core.model.InstanceInfoDO;
import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.CanIgnoreReturnValue;
import org.springframework.data.jpa.repository.JpaRepository; 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.Modifying;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
@ -16,7 +17,7 @@ import java.util.List;
* @author tjq * @author tjq
* @since 2020/4/1 * @since 2020/4/1
*/ */
public interface InstanceInfoRepository extends JpaRepository<InstanceInfoDO, Long> { public interface InstanceInfoRepository extends JpaRepository<InstanceInfoDO, Long>, JpaSpecificationExecutor<InstanceInfoDO> {
/** /**
* 统计当前JOB有多少实例正在运行 * 统计当前JOB有多少实例正在运行

View File

@ -2,10 +2,7 @@ package com.github.kfcfans.powerjob.server.service.instance;
import akka.actor.ActorSelection; import akka.actor.ActorSelection;
import akka.pattern.Patterns; import akka.pattern.Patterns;
import com.github.kfcfans.powerjob.common.InstanceStatus; import com.github.kfcfans.powerjob.common.*;
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.model.InstanceDetail; import com.github.kfcfans.powerjob.common.model.InstanceDetail;
import com.github.kfcfans.powerjob.common.request.ServerQueryInstanceStatusReq; import com.github.kfcfans.powerjob.common.request.ServerQueryInstanceStatusReq;
import com.github.kfcfans.powerjob.common.request.ServerStopInstanceReq; 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.akka.OhMyServer;
import com.github.kfcfans.powerjob.server.common.constans.InstanceType; 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.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.common.utils.timewheel.TimerFuture;
import com.github.kfcfans.powerjob.server.persistence.core.model.InstanceInfoDO; import com.github.kfcfans.powerjob.server.persistence.core.model.InstanceInfoDO;
import com.github.kfcfans.powerjob.server.persistence.core.model.JobInfoDO; import com.github.kfcfans.powerjob.server.persistence.core.model.JobInfoDO;
@ -28,8 +26,10 @@ import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.time.Duration; import java.time.Duration;
import java.util.Date; import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletionStage; import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit; 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.RUNNING;
import static com.github.kfcfans.powerjob.common.InstanceStatus.STOPPED; 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 * @param instanceId 任务实例ID
* @return 任务实例的信息 * @return 任务实例的信息
*/ */
public InstanceInfoDTO getInstanceInfo(Long instanceId) { public InstanceInfoDTO getInstanceInfo(Long instanceId) {
InstanceInfoDO instanceInfoDO = fetchInstanceInfo(instanceId); return directConvert(fetchInstanceInfo(instanceId));
InstanceInfoDTO instanceInfoDTO = new InstanceInfoDTO();
BeanUtils.copyProperties(instanceInfoDO, instanceInfoDTO);
return instanceInfoDTO;
} }
/** /**
@ -276,4 +281,10 @@ public class InstanceService {
} }
return instanceInfoDO; 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)); 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 区 ************* */ /* ************* Workflow 区 ************* */
@PostMapping(OpenAPIConstant.SAVE_WORKFLOW) @PostMapping(OpenAPIConstant.SAVE_WORKFLOW)
public ResultDTO<Long> saveWorkflow(@RequestBody SaveWorkflowRequest request) throws Exception { 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.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.username=root
spring.datasource.core.password=No1Bug2Please3! spring.datasource.core.password=No1Bug2Please3!
spring.datasource.core.hikari.maximum-pool-size=20 spring.datasource.core.hikari.maximum-pool-size=20
spring.datasource.core.hikari.minimum-idle=5 spring.datasource.core.hikari.minimum-idle=5
####### mongoDB配置非核心依赖可移除 ####### ####### 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 文件中) ###### ###### OhMyScheduler 自身配置(该配置只允许存在于 application.properties 文件中) ######
# akka ActorSystem 服务端口 # akka ActorSystem 服务端口