refactor: tag支持列表和单项两种选择,另外同时支持不选择tag和选择tag两种解析方式。

This commit is contained in:
dong.dazhen 2022-07-20 19:30:49 +08:00
parent c3260dc752
commit 9c2a8ca89f
8 changed files with 93 additions and 39 deletions

View File

@ -1,4 +1,4 @@
ALTER TABLE `workflow_instance`
add UNIQUE INDEX trigger_id(`trigger_id`);
ALTER TABLE `workflow`
add tag varchar(45) comment '标签';
add tag varchar(255) not null comment '标签';

View File

@ -9,16 +9,17 @@ import org.springframework.test.context.ActiveProfiles;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* @author Ethan Liu
* @class WorkflowTest
* @description TODO
* @author Ethan Liu
* @create 2021-04-08 21:01
*/
*/
@SpringBootTest(classes = SpringbootApp.class)
@ActiveProfiles("test")
public class WorkflowTest {
@ -121,4 +122,56 @@ public class WorkflowTest {
.build();
this.workflowRepository.add(workflow);
}
@Test
@Transactional
@Rollback(value = false)
void test3() {
Start start = Start.Builder.aStart()
.name("Start1")
.ref("start_1")
.description("开始节点1")
.build();
AsyncTask gitTask = AsyncTask.Builder.anAsyncTask()
.name("Git Clone")
.ref("git_clone0.3")
.description("Git库下载任务")
.build();
AsyncTask mavenTask = AsyncTask.Builder.anAsyncTask()
.name("Maven")
.ref("maven11")
.description("Maven命令执行环境")
.build();
End end = End.Builder.anEnd()
.name("End1")
.ref("end_1")
.description("结束节点1")
.build();
start.setTargets(Set.of(gitTask.getRef()));
gitTask.setSources(Set.of(start.getRef()));
gitTask.setTargets(Set.of(mavenTask.getRef()));
mavenTask.setSources(Set.of(gitTask.getRef()));
mavenTask.setTargets(Set.of(end.getRef()));
end.setSources(Set.of(mavenTask.getRef()));
Set<Node> nodes = Set.of(start, gitTask, mavenTask, end);
var workflow = Workflow.Builder.aWorkflow()
.name("Java CI")
.ref("java_ci")
.type(Workflow.Type.PIPELINE)
.tag("java_ci,dozen,test")
.description("CI流程 for Java 11")
.nodes(nodes)
.globalParameters(Set.of())
.dslText("")
.build();
List<String> tags = workflow.getTags();
assertEquals(tags.get(0), "java_ci");
assertEquals(tags.get(1), "dozen");
assertEquals(tags.get(2), "test");
}
}

View File

@ -288,8 +288,11 @@ public class DslParser {
this.concurrent = (Boolean) concurrent;
}
var tag = this.global.get("tag");
if (tag instanceof String){
if (tag instanceof String) {
this.tag = (String) tag;
} else if (tag instanceof List) {
List<Object> tags = (List<Object>) tag;
this.tag = tags.stream().map(Object::toString).collect(Collectors.joining(","));
}
}

View File

@ -160,17 +160,14 @@ public class WorkerInternalApplication {
this.workflowInstanceRepository.findByTriggerId(event.getTriggerId())
.ifPresent(workflowInstance -> {
// 分发worker
String workerTag = this.getWorkerTag(workflowInstance);
if (!StringUtils.hasText(workerTag)) {
throw new RuntimeException("未找到该流程的tag");
}
var workers = this.checkOldVersionOfWorkflowTag(workflowInstance) ?
List<String> workerTags = this.getWorkerTag(workflowInstance);
var workers = workerTags.isEmpty() ?
this.workerRepository.findByTypeInAndCreatedTimeLessThan(
List.of(Worker.Type.DOCKER, Worker.Type.KUBERNETES),
workflowInstance.getStartTime()) :
workflowInstance.getStartTime()) :
this.workerRepository.findByTypeInAndTagAndCreatedTimeLessThan(
List.of(Worker.Type.DOCKER, Worker.Type.KUBERNETES),
workerTag, workflowInstance.getStartTime());
List.of(Worker.Type.DOCKER, Worker.Type.KUBERNETES),
workerTags, workflowInstance.getStartTime());
if (workers.isEmpty()) {
throw new RuntimeException("worker数量为0节点任务类型" + Worker.Type.DOCKER);
}
@ -187,18 +184,12 @@ public class WorkerInternalApplication {
}
}
private Boolean checkOldVersionOfWorkflowTag(WorkflowInstance workflowInstance) {
var workflow = this.workflowRepository.findByRefAndVersion(workflowInstance.getWorkflowRef(), workflowInstance.getWorkflowVersion())
.orElseThrow(() -> new RuntimeException(String.format("无法找到对应的流程定义: %s, %s", workflowInstance.getWorkflowRef(), workflowInstance.getWorkflowVersion())));
return workflow.getTag() == null;
}
private String getWorkerTag(WorkflowInstance workflowInstance) {
private List<String> getWorkerTag(WorkflowInstance workflowInstance) {
// 因为trigger参数与workflow的全局参数并不一致该方法无法在workflow实体中进行处理
var context = new ElContext();
var workflow = this.workflowRepository.findByRefAndVersion(workflowInstance.getWorkflowRef(), workflowInstance.getWorkflowVersion())
.orElseThrow(() -> new RuntimeException(String.format("无法找到对应的流程定义: %s, %s", workflowInstance.getWorkflowRef(), workflowInstance.getWorkflowVersion())));
Expression el = this.expressionLanguage.parseExpression("`" + workflow.getTag() + "`");
List<String> tags = workflow.getTags();
workflow.getGlobalParameters()
.forEach(globalParameter -> context.add(
"global",
@ -215,13 +206,16 @@ public class WorkerInternalApplication {
Parameter
.Type.getTypeByName(triggerEventParameter.getType())
.newParameter(triggerEventParameter.getValue()))));
EvaluationResult result = this.expressionLanguage.evaluateExpression(el, context);
if (result.isFailure()) {
throw new RuntimeException("解析执行器标签的el表达式解析失败: " + result.getFailureMessage());
} else if (!Parameter.Type.STRING.equals(result.getValue().getType())) {
throw new RuntimeException("解析执行器标签的el表达式解析失败: 解析结果类型不正确");
}
return result.getValue().getStringValue();
return workflow.getTags().stream().filter(StringUtils::hasText).map(tag -> {
Expression el = this.expressionLanguage.parseExpression("`" + tag + "`");
EvaluationResult result = this.expressionLanguage.evaluateExpression(el, context);
if (result.isFailure()) {
throw new RuntimeException("解析执行器标签的el表达式解析失败: " + result.getFailureMessage());
} else if (!Parameter.Type.STRING.equals(result.getValue().getType())) {
throw new RuntimeException("解析执行器标签的el表达式解析失败: 解析结果类型不正确");
}
return result.getValue().getStringValue();
}).collect(Collectors.toList());
}
@Transactional

View File

@ -47,10 +47,13 @@ public interface WorkerMapper {
" type IN " +
" <foreach collection='types' item='item' open='(' close=')' separator=','> #{item} " +
" </foreach>" +
" and tags = #{tag}" +
" and " +
" tags IN " +
" <foreach collection='tags' item='tag' open='(' close=')' separator=','> #{tag} " +
" </foreach>" +
"</where>" +
"</script>")
@Result(column = "created_time", property = "createdTime")
List<Worker> findByTypeInAndTagAndCreatedTimeLessThan(@Param("types") List<Worker.Type> types, @Param("tag") String tag, @Param("createdTime") LocalDateTime createdTime);
List<Worker> findByTypeInAndTagAndCreatedTimeLessThan(@Param("types") List<Worker.Type> types, @Param("tags") List<String> tags, @Param("createdTime") LocalDateTime createdTime);
}

View File

@ -64,7 +64,7 @@ public class WorkerRepositoryImpl implements WorkerRepository {
}
@Override
public List<Worker> findByTypeInAndTagAndCreatedTimeLessThan(List<Worker.Type> types, String tag, LocalDateTime createdTime) {
return this.workerMapper.findByTypeInAndTagAndCreatedTimeLessThan(types, tag, createdTime);
public List<Worker> findByTypeInAndTagAndCreatedTimeLessThan(List<Worker.Type> types, List<String> tags, LocalDateTime createdTime) {
return this.workerMapper.findByTypeInAndTagAndCreatedTimeLessThan(types, tags, createdTime);
}
}

View File

@ -27,5 +27,5 @@ public interface WorkerRepository {
List<Worker> findByTypeInAndCreatedTimeLessThan(List<Worker.Type> types, LocalDateTime createdTime);
List<Worker> findByTypeInAndTagAndCreatedTimeLessThan(List<Worker.Type> types, String tag, LocalDateTime createdTime);
List<Worker> findByTypeInAndTagAndCreatedTimeLessThan(List<Worker.Type> types, List<String> tags, LocalDateTime createdTime);
}

View File

@ -9,10 +9,7 @@ import dev.jianmu.workflow.el.ExpressionLanguage;
import dev.jianmu.workflow.event.definition.*;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@ -378,7 +375,11 @@ public class Workflow extends AggregateRoot {
}
public String getTag() {
return tag;
return this.tag;
}
public List<String> getTags() {
return Arrays.asList(this.tag.split(","));
}
public String getDescription() {