feat: 接口定义定时任务改造
This commit is contained in:
parent
3c9df86106
commit
5eaae502d4
|
@ -8,7 +8,6 @@ import io.metersphere.api.dto.automation.ApiScenarioRequest;
|
|||
import io.metersphere.api.dto.automation.ReferenceDTO;
|
||||
import io.metersphere.api.dto.definition.*;
|
||||
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
|
||||
import io.metersphere.api.dto.definition.request.ScheduleInfoSwaggerUrlRequest;
|
||||
import io.metersphere.api.dto.swaggerurl.SwaggerTaskResult;
|
||||
import io.metersphere.api.dto.swaggerurl.SwaggerUrlRequest;
|
||||
import io.metersphere.api.service.ApiDefinitionService;
|
||||
|
@ -22,10 +21,8 @@ import io.metersphere.base.domain.Schedule;
|
|||
import io.metersphere.commons.constants.OperLogConstants;
|
||||
import io.metersphere.commons.constants.PermissionConstants;
|
||||
import io.metersphere.commons.json.JSONSchemaGenerator;
|
||||
import io.metersphere.commons.utils.CronUtils;
|
||||
import io.metersphere.commons.utils.PageUtils;
|
||||
import io.metersphere.commons.utils.Pager;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
import io.metersphere.controller.request.ScheduleRequest;
|
||||
import io.metersphere.log.annotation.MsAuditLog;
|
||||
import io.metersphere.service.CheckPermissionService;
|
||||
|
@ -39,8 +36,6 @@ import org.springframework.web.multipart.MultipartFile;
|
|||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
|
@ -211,12 +206,12 @@ public class ApiDefinitionController {
|
|||
//定时任务创建
|
||||
@PostMapping(value = "/schedule/create")
|
||||
@MsAuditLog(module = "api_definition", type = OperLogConstants.CREATE, title = "#request.scheduleFrom", project = "#request.projectId")
|
||||
public void createSchedule(@RequestBody ScheduleRequest request) throws MalformedURLException {
|
||||
public void createSchedule(@RequestBody ScheduleRequest request) {
|
||||
apiDefinitionService.createSchedule(request);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/schedule/update")
|
||||
public void updateSchedule(@RequestBody Schedule request) {
|
||||
public void updateSchedule(@RequestBody ScheduleRequest request) {
|
||||
apiDefinitionService.updateSchedule(request);
|
||||
}
|
||||
|
||||
|
@ -229,30 +224,18 @@ public class ApiDefinitionController {
|
|||
//查找定时任务列表
|
||||
@GetMapping("/scheduleTask/{projectId}")
|
||||
public List<SwaggerTaskResult> getSwaggerScheduleList(@PathVariable String projectId) {
|
||||
List<SwaggerTaskResult> resultList = apiDefinitionService.getSwaggerScheduleList(projectId);
|
||||
int dataIndex = 1;
|
||||
for (SwaggerTaskResult swaggerTaskResult :
|
||||
resultList) {
|
||||
swaggerTaskResult.setIndex(dataIndex++);
|
||||
Date nextExecutionTime = CronUtils.getNextTriggerTime(swaggerTaskResult.getRule());
|
||||
if (nextExecutionTime != null) {
|
||||
swaggerTaskResult.setNextExecutionTime(nextExecutionTime.getTime());
|
||||
}
|
||||
}
|
||||
return resultList;
|
||||
return apiDefinitionService.getSwaggerScheduleList(projectId);
|
||||
}
|
||||
|
||||
//更新定时任务
|
||||
@PostMapping(value = "/schedule/updateByPrimyKey")
|
||||
public void updateScheduleEnableByPrimyKey(@RequestBody ScheduleInfoSwaggerUrlRequest request) {
|
||||
Schedule schedule = scheduleService.getSchedule(request.getTaskId());
|
||||
schedule.setEnable(request.getTaskStatus());
|
||||
apiDefinitionService.updateSchedule(schedule);
|
||||
//更新定时任务更新定时任务
|
||||
@PostMapping(value = "/schedule/switch")
|
||||
public void updateScheduleEnable(@RequestBody Schedule request) {
|
||||
apiDefinitionService.switchSchedule(request);
|
||||
}
|
||||
|
||||
//删除定时任务和swaggereUrl
|
||||
@PostMapping("/schedule/deleteByPrimyKey")
|
||||
public void deleteSchedule(@RequestBody ScheduleInfoSwaggerUrlRequest request) {
|
||||
@PostMapping("/schedule/delete")
|
||||
public void deleteSchedule(@RequestBody ScheduleRequest request) {
|
||||
apiDefinitionService.deleteSchedule(request);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,12 +14,20 @@ import java.util.List;
|
|||
public class ApiDefinitionImportUtil {
|
||||
|
||||
public static ApiModule getSelectModule(String moduleId) {
|
||||
return getSelectModule(moduleId, null);
|
||||
}
|
||||
|
||||
public static ApiModule getSelectModule(String moduleId, String userId) {
|
||||
ApiModuleService apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class);
|
||||
if (StringUtils.isNotBlank(moduleId) && !StringUtils.equals("root", moduleId)) {
|
||||
ApiModule module = new ApiModule();
|
||||
ApiModuleDTO moduleDTO = apiModuleService.getNode(moduleId);
|
||||
if (moduleDTO != null) {
|
||||
BeanUtils.copyBean(module, moduleDTO);
|
||||
} else {
|
||||
if (StringUtils.isNotBlank(userId)) {
|
||||
module.setCreateUser(userId);
|
||||
}
|
||||
}
|
||||
return module;
|
||||
}
|
||||
|
@ -57,7 +65,24 @@ public class ApiDefinitionImportUtil {
|
|||
return module;
|
||||
}
|
||||
|
||||
public static ApiModule buildModule(ApiModule parentModule, String name, String projectId, String userId) {
|
||||
ApiModuleService apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class);
|
||||
ApiModule module;
|
||||
if (parentModule != null) {
|
||||
module = apiModuleService.getNewModule(name, projectId, parentModule.getLevel() + 1);
|
||||
module.setParentId(parentModule.getId());
|
||||
} else {
|
||||
module = apiModuleService.getNewModule(name, projectId, 1);
|
||||
}
|
||||
createModule(module, userId);
|
||||
return module;
|
||||
}
|
||||
|
||||
public static void createModule(ApiModule module) {
|
||||
createModule(module, null);
|
||||
}
|
||||
|
||||
public static void createModule(ApiModule module, String userId) {
|
||||
ApiModuleService apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class);
|
||||
module.setProtocol(RequestType.HTTP);
|
||||
if (module.getName().length() > 64) {
|
||||
|
@ -65,6 +90,9 @@ public class ApiDefinitionImportUtil {
|
|||
}
|
||||
List<ApiModule> apiModules = apiModuleService.selectSameModule(module);
|
||||
if (CollectionUtils.isEmpty(apiModules)) {
|
||||
if (StringUtils.isNotBlank(userId)) {
|
||||
module.setCreateUser(userId);
|
||||
}
|
||||
apiModuleService.addNode(module);
|
||||
} else {
|
||||
module.setId(apiModules.get(0).getId());
|
||||
|
|
|
@ -128,7 +128,7 @@ public class MsDefinitionParser extends MsAbstractParser<ApiDefinitionImport> {
|
|||
Iterator<String> iterator = modules.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
String item = iterator.next();
|
||||
parent = ApiDefinitionImportUtil.buildModule(parent, item, this.projectId);
|
||||
parent = ApiDefinitionImportUtil.buildModule(parent, item, this.projectId, importRequest.getUserId());
|
||||
if (!iterator.hasNext()) {
|
||||
apiDefinition.setModuleId(parent.getId());
|
||||
String path = apiDefinition.getModulePath() == null ? "" : apiDefinition.getModulePath();
|
||||
|
|
|
@ -1,27 +1,22 @@
|
|||
package io.metersphere.api.dto.swaggerurl;
|
||||
|
||||
import io.metersphere.base.domain.SwaggerUrlProject;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class SwaggerTaskResult {
|
||||
public class SwaggerTaskResult extends SwaggerUrlProject {
|
||||
//序号
|
||||
private int index;
|
||||
//定时任务号
|
||||
private String taskId;
|
||||
//SwaggerUrlId
|
||||
private String SwaggerUrlId;
|
||||
//SwaggerUrl
|
||||
private String swaggerUrl;
|
||||
//导入模块
|
||||
private String modulePath;
|
||||
//同步规则
|
||||
private String rule;
|
||||
//下次同步时间
|
||||
private Long nextExecutionTime;
|
||||
//同步开关
|
||||
private boolean taskStatus;
|
||||
private boolean enable;
|
||||
//定时任务类型 swaggerUrlType
|
||||
private String taskType;
|
||||
}
|
||||
|
|
|
@ -203,7 +203,7 @@ public class APITestService {
|
|||
}
|
||||
deleteFileByTestId(testId);
|
||||
apiReportService.deleteByTestId(testId);
|
||||
scheduleService.deleteByResourceId(testId);
|
||||
scheduleService.deleteByResourceId(testId, ScheduleGroup.API_TEST.name());
|
||||
apiTestMapper.deleteByPrimaryKey(testId);
|
||||
deleteBodyFiles(testId);
|
||||
}
|
||||
|
|
|
@ -411,7 +411,7 @@ public class ApiAutomationService {
|
|||
ids.add(scenarioId);
|
||||
deleteApiScenarioReport(ids);
|
||||
|
||||
scheduleService.deleteScheduleAndJobByResourceId(scenarioId, ScheduleGroup.API_SCENARIO_TEST.name());
|
||||
scheduleService.deleteByResourceId(scenarioId, ScheduleGroup.API_SCENARIO_TEST.name());
|
||||
TestPlanApiScenarioExample example = new TestPlanApiScenarioExample();
|
||||
example.createCriteria().andApiScenarioIdEqualTo(scenarioId);
|
||||
List<TestPlanApiScenario> testPlanApiScenarioList = testPlanApiScenarioMapper.selectByExample(example);
|
||||
|
@ -485,7 +485,7 @@ public class ApiAutomationService {
|
|||
}
|
||||
}
|
||||
|
||||
scheduleService.deleteByResourceId(id);
|
||||
scheduleService.deleteByResourceId(id, ScheduleGroup.API_SCENARIO_TEST.name());
|
||||
}
|
||||
if (!testPlanApiScenarioIdList.isEmpty()) {
|
||||
TestPlanApiScenarioExample example = new TestPlanApiScenarioExample();
|
||||
|
@ -507,7 +507,7 @@ public class ApiAutomationService {
|
|||
extApiScenarioMapper.removeToGc(apiIds);
|
||||
//将这些场景的定时任务删除掉
|
||||
for (String id : apiIds) {
|
||||
scheduleService.deleteScheduleAndJobByResourceId(id, ScheduleGroup.API_SCENARIO_TEST.name());
|
||||
scheduleService.deleteByResourceId(id, ScheduleGroup.API_SCENARIO_TEST.name());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
|
|||
import io.metersphere.api.dto.definition.parse.ApiDefinitionImportParserFactory;
|
||||
import io.metersphere.api.dto.definition.parse.Swagger3Parser;
|
||||
import io.metersphere.api.dto.definition.request.ParameterConfig;
|
||||
import io.metersphere.api.dto.definition.request.ScheduleInfoSwaggerUrlRequest;
|
||||
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
|
||||
import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler;
|
||||
import io.metersphere.api.dto.scenario.Body;
|
||||
|
@ -917,21 +916,22 @@ public class ApiDefinitionService {
|
|||
}
|
||||
|
||||
/*swagger定时导入*/
|
||||
public void createSchedule(ScheduleRequest request) throws MalformedURLException {
|
||||
public void createSchedule(ScheduleRequest request) {
|
||||
/*保存swaggerUrl*/
|
||||
SwaggerUrlProject swaggerUrlProject = new SwaggerUrlProject();
|
||||
BeanUtils.copyBean(swaggerUrlProject, request);
|
||||
swaggerUrlProject.setId(UUID.randomUUID().toString());
|
||||
swaggerUrlProject.setProjectId(request.getProjectId());
|
||||
swaggerUrlProject.setSwaggerUrl(request.getResourceId());
|
||||
swaggerUrlProject.setModuleId(request.getModuleId());
|
||||
swaggerUrlProject.setModulePath(request.getModulePath());
|
||||
swaggerUrlProject.setModeId(request.getModeId());
|
||||
scheduleService.addSwaggerUrlSchedule(swaggerUrlProject);
|
||||
|
||||
request.setResourceId(swaggerUrlProject.getId());
|
||||
Schedule schedule = scheduleService.buildApiTestSchedule(request);
|
||||
schedule.setProjectId(swaggerUrlProject.getProjectId());
|
||||
java.net.URL swaggerUrl = new java.net.URL(swaggerUrlProject.getSwaggerUrl());
|
||||
schedule.setName(swaggerUrl.getHost()); // swagger 定时任务的 name 设置为 swaggerURL 的域名
|
||||
try {
|
||||
schedule.setName(new java.net.URL(swaggerUrlProject.getSwaggerUrl()).getHost());
|
||||
} catch (MalformedURLException e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
MSException.throwException("URL 格式不正确!");
|
||||
}
|
||||
schedule.setJob(SwaggerUrlImportJob.class.getName());
|
||||
schedule.setGroup(ScheduleGroup.SWAGGER_IMPORT.name());
|
||||
schedule.setType(ScheduleType.CRON.name());
|
||||
|
@ -940,17 +940,39 @@ public class ApiDefinitionService {
|
|||
|
||||
}
|
||||
|
||||
//关闭
|
||||
public void updateSchedule(Schedule request) {
|
||||
public void updateSchedule(ScheduleRequest request) {
|
||||
SwaggerUrlProject swaggerUrlProject = new SwaggerUrlProject();
|
||||
BeanUtils.copyBean(swaggerUrlProject, request);
|
||||
scheduleService.updateSwaggerUrlSchedule(swaggerUrlProject);
|
||||
// 只修改表达式和名称
|
||||
Schedule schedule = new Schedule();
|
||||
schedule.setId(request.getTaskId());
|
||||
schedule.setValue(request.getValue().trim());
|
||||
schedule.setEnable(request.getEnable());
|
||||
try {
|
||||
schedule.setName(new java.net.URL(swaggerUrlProject.getSwaggerUrl()).getHost());
|
||||
} catch (MalformedURLException e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
MSException.throwException("URL 格式不正确!");
|
||||
}
|
||||
scheduleService.editSchedule(schedule);
|
||||
request.setResourceId(swaggerUrlProject.getId());
|
||||
this.addOrUpdateSwaggerImportCronJob(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表开关切换
|
||||
* @param request
|
||||
*/
|
||||
public void switchSchedule(Schedule request) {
|
||||
scheduleService.editSchedule(request);
|
||||
this.addOrUpdateSwaggerImportCronJob(request);
|
||||
}
|
||||
|
||||
//删除
|
||||
public void deleteSchedule(ScheduleInfoSwaggerUrlRequest request) {
|
||||
public void deleteSchedule(ScheduleRequest request) {
|
||||
swaggerUrlProjectMapper.deleteByPrimaryKey(request.getId());
|
||||
scheduleMapper.deleteByPrimaryKey(request.getTaskId());
|
||||
|
||||
scheduleService.deleteByResourceId(request.getTaskId(), ScheduleGroup.SWAGGER_IMPORT.name());
|
||||
}
|
||||
|
||||
//查询swaggerUrl详情
|
||||
|
@ -974,7 +996,17 @@ public class ApiDefinitionService {
|
|||
}
|
||||
|
||||
public List<SwaggerTaskResult> getSwaggerScheduleList(String projectId) {
|
||||
return extSwaggerUrlScheduleMapper.getSwaggerTaskList(projectId);
|
||||
List<SwaggerTaskResult> resultList = extSwaggerUrlScheduleMapper.getSwaggerTaskList(projectId);
|
||||
int dataIndex = 1;
|
||||
for (SwaggerTaskResult swaggerTaskResult :
|
||||
resultList) {
|
||||
swaggerTaskResult.setIndex(dataIndex++);
|
||||
Date nextExecutionTime = CronUtils.getNextTriggerTime(swaggerTaskResult.getRule());
|
||||
if (nextExecutionTime != null) {
|
||||
swaggerTaskResult.setNextExecutionTime(nextExecutionTime.getTime());
|
||||
}
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
private void addOrUpdateSwaggerImportCronJob(Schedule request) {
|
||||
|
|
|
@ -184,7 +184,9 @@ public class ApiModuleService extends NodeTreeService<ApiModuleDTO> {
|
|||
node.setCreateTime(System.currentTimeMillis());
|
||||
node.setUpdateTime(System.currentTimeMillis());
|
||||
node.setId(UUID.randomUUID().toString());
|
||||
if (StringUtils.isBlank(node.getCreateUser())) {
|
||||
node.setCreateUser(SessionUtils.getUserId());
|
||||
}
|
||||
double pos = getNextLevelPos(node.getProjectId(), node.getLevel(), node.getParentId());
|
||||
node.setPos(pos);
|
||||
apiModuleMapper.insertSelective(node);
|
||||
|
|
|
@ -3,11 +3,14 @@
|
|||
<mapper namespace="io.metersphere.base.mapper.ext.ExtSwaggerUrlScheduleMapper">
|
||||
<select id="getSwaggerTaskList" resultType="io.metersphere.api.dto.swaggerurl.SwaggerTaskResult"
|
||||
parameterType="java.lang.String">
|
||||
SELECT sup.id as SwaggerUrlId,
|
||||
sup.swagger_url as swaggerUrl,
|
||||
sup.module_path as modulePath,
|
||||
SELECT sup.id,
|
||||
sup.swagger_url,
|
||||
sup.module_path,
|
||||
sup.mode_id,
|
||||
sup.module_id,
|
||||
sup.project_id,
|
||||
sch.value as rule,
|
||||
sch.enable as taskStatus,
|
||||
sch.enable,
|
||||
sch.id as taskId
|
||||
FROM swagger_url_project sup
|
||||
INNER JOIN schedule sch ON sup.id = sch.resource_id
|
||||
|
|
|
@ -9,14 +9,14 @@ import org.apache.shiro.subject.Subject;
|
|||
import org.apache.shiro.subject.support.DefaultSubjectContext;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
|
||||
import static io.metersphere.commons.constants.SessionConstants.ATTR_USER;
|
||||
|
||||
public class SessionUtils {
|
||||
|
||||
public static String getUserId() {
|
||||
return Objects.requireNonNull(getUser()).getId();
|
||||
SessionUser user = getUser();
|
||||
return user == null ? null : user.getId();
|
||||
}
|
||||
|
||||
public static SessionUser getUser() {
|
||||
|
|
|
@ -24,4 +24,8 @@ public class ScheduleRequest extends Schedule {
|
|||
|
||||
private String modeId;
|
||||
|
||||
private String swaggerUrl;
|
||||
|
||||
private String taskId;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
package io.metersphere.job.sechedule;
|
||||
|
||||
import io.metersphere.api.dto.ApiTestImportRequest;
|
||||
import io.metersphere.api.dto.definition.ApiSwaggerUrlDTO;
|
||||
import io.metersphere.api.service.ApiDefinitionService;
|
||||
import io.metersphere.base.domain.SwaggerUrlProject;
|
||||
import io.metersphere.commons.constants.ScheduleGroup;
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import io.metersphere.service.ScheduleService;
|
||||
import org.quartz.JobDataMap;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobKey;
|
||||
|
@ -16,7 +14,7 @@ public class SwaggerUrlImportJob extends MsScheduleJob {
|
|||
private ApiDefinitionService apiDefinitionService;
|
||||
|
||||
public SwaggerUrlImportJob() {
|
||||
apiDefinitionService = (ApiDefinitionService) CommonBeanFactory.getBean(ApiDefinitionService.class);
|
||||
apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -31,6 +29,7 @@ public class SwaggerUrlImportJob extends MsScheduleJob {
|
|||
request.setPlatform("Swagger2");
|
||||
request.setUserId(jobDataMap.getString("userId"));
|
||||
request.setType("schedule");
|
||||
request.setUserId(jobDataMap.getString("userId"));
|
||||
apiDefinitionService.apiTestImport(null, request);
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ public class AppStartListener implements ApplicationListener<ApplicationReadyEve
|
|||
initPythonEnv();
|
||||
|
||||
try {
|
||||
Thread.sleep(3 * 60 * 1000);
|
||||
Thread.sleep(1 * 60 * 1000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ public class PerformanceTestService {
|
|||
extLoadTestReportMapper.updateJmxContentIfAbsent(record);
|
||||
});
|
||||
//delete schedule
|
||||
scheduleService.deleteByResourceId(testId);
|
||||
scheduleService.deleteByResourceId(testId, ScheduleGroup.PERFORMANCE_TEST.name());
|
||||
|
||||
// delete load_test
|
||||
loadTestMapper.deleteByPrimaryKey(request.getId());
|
||||
|
|
|
@ -58,9 +58,15 @@ public class ScheduleService {
|
|||
schedule.setUpdateTime(System.currentTimeMillis());
|
||||
scheduleMapper.insert(schedule);
|
||||
}
|
||||
|
||||
public void addSwaggerUrlSchedule(SwaggerUrlProject swaggerUrlProject) {
|
||||
swaggerUrlProjectMapper.insert(swaggerUrlProject);
|
||||
}
|
||||
|
||||
public void updateSwaggerUrlSchedule(SwaggerUrlProject swaggerUrlProject) {
|
||||
swaggerUrlProjectMapper.updateByPrimaryKeySelective(swaggerUrlProject);
|
||||
}
|
||||
|
||||
public ApiSwaggerUrlDTO selectApiSwaggerUrlDTO(String id){
|
||||
return extScheduleMapper.select(id);
|
||||
}
|
||||
|
@ -85,34 +91,23 @@ public class ScheduleService {
|
|||
return null;
|
||||
}
|
||||
|
||||
public int deleteSchedule(String scheduleId) {
|
||||
Schedule schedule = scheduleMapper.selectByPrimaryKey(scheduleId);
|
||||
removeJob(schedule.getResourceId());
|
||||
return scheduleMapper.deleteByPrimaryKey(scheduleId);
|
||||
}
|
||||
|
||||
public int deleteByResourceId(String resourceId) {
|
||||
public int deleteByResourceId(String resourceId, String group) {
|
||||
ScheduleExample scheduleExample = new ScheduleExample();
|
||||
scheduleExample.createCriteria().andResourceIdEqualTo(resourceId);
|
||||
removeJob(resourceId);
|
||||
removeJob(resourceId, group);
|
||||
return scheduleMapper.deleteByExample(scheduleExample);
|
||||
}
|
||||
|
||||
public int deleteScheduleAndJobByResourceId(String resourceId,String group) {
|
||||
ScheduleExample scheduleExample = new ScheduleExample();
|
||||
scheduleExample.createCriteria().andResourceIdEqualTo(resourceId);
|
||||
removeJob(resourceId,group);
|
||||
return scheduleMapper.deleteByExample(scheduleExample);
|
||||
}
|
||||
|
||||
public void removeJob(String resourceId,String group) {
|
||||
if(StringUtils.equals(ScheduleGroup.API_SCENARIO_TEST.name(),group)){
|
||||
private void removeJob(String resourceId, String group) {
|
||||
if(StringUtils.equals(ScheduleGroup.API_SCENARIO_TEST.name(), group)){
|
||||
scheduleManager.removeJob(ApiScenarioTestJob.getJobKey(resourceId), ApiScenarioTestJob.getTriggerKey(resourceId));
|
||||
}else if(StringUtils.equals(ScheduleGroup.TEST_PLAN_TEST.name(),group)){
|
||||
} else if(StringUtils.equals(ScheduleGroup.TEST_PLAN_TEST.name(), group)){
|
||||
scheduleManager.removeJob(TestPlanTestJob.getJobKey(resourceId), TestPlanTestJob.getTriggerKey(resourceId));
|
||||
}else if(StringUtils.equals(ScheduleGroup.SWAGGER_IMPORT.name(),group)){
|
||||
} else if(StringUtils.equals(ScheduleGroup.SWAGGER_IMPORT.name(), group)){
|
||||
scheduleManager.removeJob(SwaggerUrlImportJob.getJobKey(resourceId), SwaggerUrlImportJob.getTriggerKey(resourceId));
|
||||
}else{
|
||||
} else if(StringUtils.equals(ScheduleGroup.PERFORMANCE_TEST.name(), group)){
|
||||
scheduleManager.removeJob(PerformanceTestJob.getJobKey(resourceId), PerformanceTestJob.getTriggerKey(resourceId));
|
||||
} else {
|
||||
scheduleManager.removeJob(ApiTestJob.getJobKey(resourceId), ApiTestJob.getTriggerKey(resourceId));
|
||||
}
|
||||
}
|
||||
|
@ -156,10 +151,6 @@ public class ScheduleService {
|
|||
return schedule;
|
||||
}
|
||||
|
||||
public void removeJob(String resourceId) {
|
||||
scheduleManager.removeJob(ApiTestJob.getJobKey(resourceId), ApiTestJob.getTriggerKey(resourceId));
|
||||
}
|
||||
|
||||
public void addOrUpdateCronJob(Schedule request, JobKey jobKey, TriggerKey triggerKey, Class clazz) {
|
||||
Boolean enable = request.getEnable();
|
||||
String cronExpression = request.getValue();
|
||||
|
|
|
@ -298,7 +298,7 @@ public class TestPlanService {
|
|||
testPlanScenarioCaseService.deleteByPlanId(planId);
|
||||
|
||||
//删除定时任务
|
||||
scheduleService.deleteScheduleAndJobByResourceId(planId, ScheduleGroup.TEST_PLAN_TEST.name());
|
||||
scheduleService.deleteByResourceId(planId, ScheduleGroup.TEST_PLAN_TEST.name());
|
||||
|
||||
int num = testPlanMapper.deleteByPrimaryKey(planId);
|
||||
List<String> relatedUsers = new ArrayList<>();
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
@setModuleOptions="setModuleOptions"
|
||||
@setNodeTree="setNodeTree"
|
||||
@enableTrash="enableTrash"
|
||||
@schedule="handleTabsEdit($t('api_test.definition.request.fast_debug'), 'SCHEDULE')"
|
||||
:type="'edit'"
|
||||
page-source="definition"
|
||||
ref="nodeTree"/>
|
||||
|
@ -118,6 +119,12 @@
|
|||
:project-id="projectId"
|
||||
@saveAsApi="editApi" @refresh="refresh" v-if="currentProtocol==='DUBBO'"/>
|
||||
</div>
|
||||
|
||||
<!-- 定时任务 -->
|
||||
<div v-if="item.type=== 'SCHEDULE'" class="ms-api-div">
|
||||
<api-schedule :module-options="nodeTree"/>
|
||||
</div>
|
||||
|
||||
<div v-else-if="item.type=== 'MOCK'" class="ms-api-div">
|
||||
<mock-config :base-mock-config-data="item.mock"></mock-config>
|
||||
</div>
|
||||
|
@ -173,6 +180,7 @@ import MsTabButton from "@/business/components/common/components/MsTabButton";
|
|||
import {getLabel} from "@/common/js/tableUtils";
|
||||
|
||||
import MockConfig from "@/business/components/api/definition/components/mock/MockConfig";
|
||||
import ApiSchedule from "@/business/components/api/definition/components/import/ApiSchedule";
|
||||
|
||||
export default {
|
||||
name: "ApiDefinition",
|
||||
|
@ -191,6 +199,7 @@ export default {
|
|||
},
|
||||
},
|
||||
components: {
|
||||
ApiSchedule,
|
||||
MsTabButton,
|
||||
MsTableButton,
|
||||
ApiCaseSimpleList,
|
||||
|
|
|
@ -127,14 +127,16 @@
|
|||
id: 'id',
|
||||
label: 'name',
|
||||
},
|
||||
modeOptions: [{
|
||||
modeOptions: [
|
||||
{
|
||||
id: 'fullCoverage',
|
||||
name: this.$t('commons.cover')
|
||||
},
|
||||
{
|
||||
id: 'incrementalMerge',
|
||||
name: this.$t('commons.not_cover')
|
||||
}],
|
||||
}
|
||||
],
|
||||
protocol: "",
|
||||
platforms: [
|
||||
{
|
||||
|
|
|
@ -0,0 +1,256 @@
|
|||
<template>
|
||||
<el-main>
|
||||
<div class="api-schedule-form">
|
||||
<el-form :model="formData" :rules="rules" v-loading="result.loading" label-width="140px" ref="form">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="'Swagger URL'" prop="swaggerUrl" class="swagger-url">
|
||||
<el-input size="small" v-model="formData.swaggerUrl" clearable/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="'Cron表达式'" prop="rule">
|
||||
<el-input :disabled="isReadOnly"
|
||||
v-model="formData.rule"
|
||||
size="small"
|
||||
:placeholder="$t('schedule.please_input_cron_expression')"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="$t('commons.import_module')" prop="moduleId">
|
||||
<select-tree class="select-tree" size="small"
|
||||
:data="moduleOptions"
|
||||
:defaultKey="formData.moduleId"
|
||||
@getValue="setModule"
|
||||
:obj="moduleObj" clearable checkStrictly ref="selectTree"/>
|
||||
<!-- <ms-select-tree :disabled="readOnly" :data="treeNodes" :defaultKey="form.module" :obj="moduleObj"-->
|
||||
<!-- @getValue="setModule" clearable checkStrictly size="small"/>-->
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.import_mode')" prop="modeId">
|
||||
<el-select size="small" v-model="formData.modeId" clearable >
|
||||
<el-option v-for="item in modeOptions" :key="item.id" :label="item.name" :value="item.id"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item class="expression-link">
|
||||
<el-link :disabled="isReadOnly" type="primary" @click="showCronDialog">
|
||||
{{ $t('schedule.generate_expression') }}
|
||||
</el-link>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<crontab-result :ex="formData.rule" ref="crontabResult"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div style="margin-top: 20px;" class="clearfix">
|
||||
<el-button v-if="!formData.id" type="primary" style="float: right" size="mini" @click="saveCron">{{$t('commons.add')}}</el-button>
|
||||
<div v-else>
|
||||
<el-button type="primary" style="float: right;margin-left: 10px" size="mini" @click="clear">{{$t('commons.clear')}}</el-button>
|
||||
<el-button type="primary" style="float: right" size="mini" @click="saveCron">{{$t('commons.update')}}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="task-list">
|
||||
<swagger-task-list
|
||||
@rowClick="handleRowClick"
|
||||
ref="taskList"/>
|
||||
</div>
|
||||
|
||||
<el-dialog width="60%" :title="$t('schedule.generate_expression')" :visible.sync="showCron" :modal="false">
|
||||
<crontab @hide="showCron=false" @fill="crontabFill" :expression="formData.value" ref="crontab"/>
|
||||
</el-dialog>
|
||||
|
||||
</el-main>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsFormDivider from "@/business/components/common/components/MsFormDivider";
|
||||
import SwaggerTaskList from "@/business/components/api/definition/components/import/SwaggerTaskList";
|
||||
import CrontabResult from "@/business/components/common/cron/CrontabResult";
|
||||
import Crontab from "@/business/components/common/cron/Crontab";
|
||||
import {cronValidate} from "@/common/js/cron";
|
||||
import {getCurrentProjectID, getCurrentUser} from "@/common/js/utils";
|
||||
import SelectTree from "@/business/components/common/select-tree/SelectTree";
|
||||
export default {
|
||||
name: "ApiSchedule",
|
||||
components: {SelectTree, MsFormDivider,SwaggerTaskList, CrontabResult, Crontab},
|
||||
props: {
|
||||
customValidate: {
|
||||
type: Function,
|
||||
default: () => {return {pass: true};}
|
||||
},
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
moduleOptions: Array,
|
||||
},
|
||||
|
||||
watch: {
|
||||
'schedule.value'() {
|
||||
this.formData.rule = this.formData.value;
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const validateCron = (rule, ruleVal, callback) => {
|
||||
let customValidate = this.customValidate(this.getIntervalTime());
|
||||
if (!ruleVal) {
|
||||
callback(new Error(this.$t('commons.input_content')));
|
||||
} else if (!cronValidate(ruleVal)) {
|
||||
callback(new Error(this.$t('schedule.cron_expression_format_error')));
|
||||
} else if (!customValidate.pass) {
|
||||
callback(new Error(customValidate.info));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
return {
|
||||
operation: true,
|
||||
schedule: {
|
||||
value: "",
|
||||
},
|
||||
showCron: false,
|
||||
activeName: 'first',
|
||||
swaggerUrl: String,
|
||||
projectId: String,
|
||||
moduleId: String,
|
||||
paramSwaggerUrlId: String,
|
||||
modulePath: String,
|
||||
modeId: String,
|
||||
rules: {
|
||||
rule: [{required: true, validator: validateCron, trigger: 'blur'}],
|
||||
swaggerUrl: [{required: true, trigger: 'blur', message: this.$t('commons.please_fill_content')}],
|
||||
},
|
||||
formData: {
|
||||
swaggerUrl: '',
|
||||
modeId: this.$t('commons.not_cover'),
|
||||
moduleId: '',
|
||||
rule: ''
|
||||
},
|
||||
modeOptions: [
|
||||
{
|
||||
id: 'fullCoverage',
|
||||
name: this.$t('commons.cover')
|
||||
},
|
||||
{
|
||||
id: 'incrementalMerge',
|
||||
name: this.$t('commons.not_cover')
|
||||
}
|
||||
],
|
||||
result: {},
|
||||
moduleObj: {
|
||||
id: 'id',
|
||||
label: 'name',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
currentUser: () => {
|
||||
return getCurrentUser();
|
||||
},
|
||||
clear() {
|
||||
this.formData.id = null;
|
||||
this.formData.moduleId = null;
|
||||
this.$refs['form'].resetFields();
|
||||
if (!this.formData.rule) {
|
||||
this.$refs.crontabResult.resultList = [];
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.$refs.selectTree.init();
|
||||
});
|
||||
},
|
||||
crontabFill(value, resultList) {
|
||||
//确定后回传的值
|
||||
this.formData.rule = value;
|
||||
this.$refs.crontabResult.resultList = resultList;
|
||||
this.$refs['form'].validate();
|
||||
},
|
||||
showCronDialog() {
|
||||
this.showCron = true;
|
||||
},
|
||||
saveCron() {
|
||||
this.$refs['form'].validate((valid) => {
|
||||
if (valid) {
|
||||
this.intervalShortValidate();
|
||||
this.saveSchedule();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
saveSchedule() {
|
||||
this.formData.projectId = getCurrentProjectID();
|
||||
this.formData.value = this.formData.rule;
|
||||
let url = '';
|
||||
if (this.formData.id) {
|
||||
url = '/api/definition/schedule/update';
|
||||
} else {
|
||||
this.formData.enable = true;
|
||||
url = '/api/definition/schedule/create';
|
||||
}
|
||||
this.$post(url, this.formData, () => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.$refs.taskList.search();
|
||||
this.clear();
|
||||
});
|
||||
},
|
||||
|
||||
intervalShortValidate() {
|
||||
if (this.getIntervalTime() < 3 * 60 * 1000) {
|
||||
this.$info(this.$t('schedule.cron_expression_interval_short_error'));
|
||||
}
|
||||
return true;
|
||||
},
|
||||
resultListChange() {
|
||||
this.$refs['form'].validate();
|
||||
},
|
||||
getIntervalTime() {
|
||||
let resultList = this.$refs.crontabResult.resultList;
|
||||
let time1 = new Date(resultList[0]);
|
||||
let time2 = new Date(resultList[1]);
|
||||
return time2 - time1;
|
||||
},
|
||||
setModule(id, data) {
|
||||
this.formData.moduleId = id;
|
||||
this.formData.modulePath = data.path;
|
||||
},
|
||||
handleRowClick(row) {
|
||||
Object.assign(this.formData, row);
|
||||
this.$nextTick(() => {
|
||||
this.$refs.selectTree.init();
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
computed: {
|
||||
isTesterPermission() {
|
||||
return true;
|
||||
},
|
||||
isSwagger2() {
|
||||
return this.selectedPlatformValue === 'Swagger2';
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.select-tree {
|
||||
width: 205px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.api-schedule-form,.task-list {
|
||||
border: #DCDFE6 solid 1px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.task-list {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.expression-link {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
|
@ -1,21 +1,33 @@
|
|||
<template>
|
||||
<el-table border :data="tableData" class="adjust-table table-content" height="300px">
|
||||
<el-table-column prop="index" :label="$t('api_test.home_page.running_task_list.table_coloum.index')"
|
||||
width="50"
|
||||
<el-table border
|
||||
v-loading="result.loading"
|
||||
highlight-current-row
|
||||
@row-click="handleRowClick"
|
||||
:data="tableData"
|
||||
class="adjust-table table-content"
|
||||
height="300px">
|
||||
<el-table-column prop="index"
|
||||
width="60"
|
||||
:label="$t('api_test.home_page.running_task_list.table_coloum.index')"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="SwaggerUrlId">
|
||||
</el-table-column>
|
||||
<el-table-column prop="swaggerUrl" :label="$t('swaggerUrl')" width="100" show-overflow-tooltip>
|
||||
<!-- <el-table-column prop="SwaggerUrlId">-->
|
||||
<!-- </el-table-column>-->
|
||||
<el-table-column
|
||||
prop="swaggerUrl"
|
||||
:label="$t('swaggerUrl')"
|
||||
min-width="170" show-overflow-tooltip>
|
||||
</el-table-column>
|
||||
<el-table-column prop="modulePath" :label="$t('导入模块')"
|
||||
width="100" show-overflow-tooltip/>
|
||||
<el-table-column prop="rule" label="同步规则" width="120"
|
||||
min-width="100"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="rule" label="同步规则"
|
||||
min-width="140"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column width="100" :label="$t('api_test.home_page.running_task_list.table_coloum.task_status')">
|
||||
<template v-slot:default="scope">
|
||||
<div>
|
||||
<el-switch
|
||||
v-model="scope.row.taskStatus"
|
||||
v-model="scope.row.enable"
|
||||
class="captcha-img"
|
||||
@click.native="closeTaskConfirm(scope.row)"
|
||||
></el-switch>
|
||||
|
@ -48,6 +60,7 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
tableData: [],
|
||||
result: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -57,32 +70,41 @@ export default {
|
|||
this.tableData = response.data;
|
||||
})
|
||||
},
|
||||
handleRowClick(row) {
|
||||
this.$emit('rowClick', row);
|
||||
},
|
||||
closeTaskConfirm(row) {
|
||||
let flag = row.taskStatus;
|
||||
row.taskStatus = !flag;
|
||||
if (row.taskStatus) {
|
||||
let flag = row.enable;
|
||||
row.enable = !flag;
|
||||
if (row.enable) {
|
||||
this.$confirm(this.$t('api_test.home_page.running_task_list.confirm.close_title'), this.$t('commons.prompt'), {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
cancelButtonText: this.$t('commons.cancel'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
row.taskStatus = !row.taskStatus
|
||||
row.enable = !row.enable
|
||||
this.updateTask(row);
|
||||
}).catch(() => {
|
||||
});
|
||||
} else {
|
||||
row.taskStatus = !row.taskStatus
|
||||
row.enable = !row.enable
|
||||
this.updateTask(row);
|
||||
}
|
||||
|
||||
},
|
||||
updateTask(taskRow) {
|
||||
this.result = this.$post('/api/definition/schedule/updateByPrimyKey', taskRow, response => {
|
||||
let schedule = {
|
||||
resourceId: taskRow.id,
|
||||
id: taskRow.taskId,
|
||||
enable: taskRow.enable,
|
||||
value: taskRow.rule
|
||||
}
|
||||
this.result = this.$post('/api/definition/schedule/switch', schedule, response => {
|
||||
this.search();
|
||||
});
|
||||
},
|
||||
deleteRowTask(row) {
|
||||
this.result = this.$post('/api/definition/schedule/deleteByPrimyKey', row, response => {
|
||||
this.result = this.$post('/api/definition/schedule/delete', row, response => {
|
||||
this.search();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
@exportAPI="exportAPI"
|
||||
@saveAsEdit="saveAsEdit"
|
||||
@refreshTable="$emit('refreshTable')"
|
||||
@schedule="$emit('schedule')"
|
||||
@refresh="refresh"
|
||||
@debug="debug"/>
|
||||
</template>
|
||||
|
@ -47,7 +48,7 @@
|
|||
import ApiImport from "../import/ApiImport";
|
||||
import MsNodeTree from "../../../../track/common/NodeTree";
|
||||
import ApiModuleHeader from "./ApiModuleHeader";
|
||||
import {buildNodePath, buildTree} from "../../model/NodeTree";
|
||||
import {buildTree} from "../../model/NodeTree";
|
||||
import {getCurrentProjectID} from "@/common/js/utils";
|
||||
|
||||
export default {
|
||||
|
|
|
@ -65,6 +65,13 @@ export default {
|
|||
callback: this.handleImport,
|
||||
permissions: ['PROJECT_API_DEFINITION:READ+IMPORT_API']
|
||||
},
|
||||
{
|
||||
label: this.$t('定时同步'),
|
||||
callback: () => {
|
||||
this.$emit('schedule');
|
||||
},
|
||||
permissions: ['PROJECT_API_DEFINITION:READ+IMPORT_API']
|
||||
},
|
||||
{
|
||||
label: this.$t('report.export'),
|
||||
permissions: ['PROJECT_API_DEFINITION:READ+EXPORT_API'],
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
import OutsideClick from "@/common/js/outside-click";
|
||||
|
||||
export default {
|
||||
name: 'test-code',
|
||||
name: 'SelectTree',
|
||||
directives: {OutsideClick},
|
||||
props: {
|
||||
// 树结构数据
|
||||
|
|
Loading…
Reference in New Issue