feat(规则引擎): 增加场景分支executeAnyway配置.优化场景条件分支逻辑. (#511)

This commit is contained in:
tancong 2024-05-23 17:12:50 +08:00 committed by GitHub
parent 86b073b389
commit 2b8f571e9a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 95 additions and 7 deletions

View File

@ -104,7 +104,7 @@ public class DefaultAlarmRuleHandler implements AlarmRuleHandler, CommandLineRun
//节点所在的条件分支索引
int branchIndex = context
.getJob()
.getConfiguration(SceneRule.ACTION_KEY_BRANCH_INDEX)
.getConfiguration(SceneRule.ACTION_KEY_BRANCH_ID)
.map(idx -> CastUtils.castNumber(idx).intValue())
.orElse(AlarmRuleBindEntity.ANY_BRANCH_INDEX);

View File

@ -30,6 +30,12 @@ public class SceneConditionAction implements Serializable {
@Schema(description = "满足条件时执行的动作")
private List<SceneActions> then;
@Schema(description = "无论如何都尝试执行此分支")
private boolean executeAnyway = false;
@Schema(description = "分支ID")
private Integer branchId;
//仅用于设置到reactQl sql的column中
public List<Term> createContextTerm() {

View File

@ -50,6 +50,7 @@ import java.util.function.Function;
@Setter
public class SceneRule implements Serializable {
public static final String ACTION_KEY_BRANCH_ID = "_branchId";
public static final String ACTION_KEY_BRANCH_INDEX = "_branchIndex";
public static final String ACTION_KEY_GROUP_INDEX = "_groupIndex";
public static final String ACTION_KEY_ACTION_INDEX = "_actionIndex";
@ -331,11 +332,16 @@ public class SceneRule implements Serializable {
if (last == null) {
last = handler;
} else {
boolean executeAnyway = branch.isExecuteAnyway();
Function<Map<String, Object>, Mono<Boolean>> _last = last;
last = data -> _last
.apply(data)
.flatMap(match -> {
//无论如何都尝试执行当前分支
if(executeAnyway){
return handler.apply(data);
}
//上一个分支满足了则返回,不执行此分支逻辑
if (match) {
return Reactors.ALWAYS_FALSE;

View File

@ -1,26 +1,45 @@
package org.jetlinks.community.rule.engine.service.terms;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.collections4.CollectionUtils;
import org.hswebframework.ezorm.core.param.Term;
import org.hswebframework.ezorm.rdb.metadata.RDBColumnMetadata;
import org.hswebframework.ezorm.rdb.operator.builder.fragments.PrepareSqlFragments;
import org.hswebframework.ezorm.rdb.operator.builder.fragments.SqlFragments;
import org.hswebframework.ezorm.rdb.operator.builder.fragments.term.AbstractTermFragmentBuilder;
import org.hswebframework.web.bean.FastBeanCopier;
import org.jetlinks.community.utils.ConverterUtils;
import org.jetlinks.community.utils.ObjectMappers;
import org.jetlinks.reactor.ql.utils.CastUtils;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 根据规则查询告警配置.
*
* <p>
* 例如查询场景联动ID为rule-id绑定的告警
* <pre>
* <pre>{@code
* {
* "column":"id",
* "termType":"rule-bind-alarm",
* "value":"rule-id"
* }
* </pre>
*
* {
* "column":"id",
* "termType":"rule-bind-alarm",
* "value": {
* "ruleId":["rule-id"],
* "branchId":[-1,2]
* }
* }
* }</pre>
*
* @author zhangji 2022/11/23
*/
@ -36,6 +55,10 @@ public class RuleBindAlarmTerm extends AbstractTermFragmentBuilder {
RDBColumnMetadata column,
Term term) {
AlarmRuleBindTerm bindTerm = AlarmRuleBindTerm.of(term.getValue());
if (CollectionUtils.isEmpty(bindTerm.ruleId)) {
throw new IllegalArgumentException("illegal term [rule-bind-alarm] value :" + term);
}
PrepareSqlFragments sqlFragments = PrepareSqlFragments.of();
if (term.getOptions().contains("not")) {
sqlFragments.addSql("not");
@ -43,16 +66,69 @@ public class RuleBindAlarmTerm extends AbstractTermFragmentBuilder {
sqlFragments
.addSql("exists(select 1 from ", getTableName("s_alarm_rule_bind", column), " _bind where _bind.alarm_id =", columnFullName);
List<Object> ruleId = convertList(column, term);
sqlFragments
.addSql(
"and _bind.rule_id in (",
ruleId.stream().map(r -> "?").collect(Collectors.joining(",")),
String.join("?", bindTerm.ruleId),
")")
.addParameter(ruleId);
.addParameter(bindTerm.ruleId);
if (CollectionUtils.isNotEmpty(bindTerm.branchId)) {
sqlFragments
.addSql(
"and _bind.branch_index in (",
bindTerm.branchId.stream().map(r -> "?").collect(Collectors.joining(",")),
")")
.addParameter(bindTerm.branchId);
}
sqlFragments.addSql(")");
return sqlFragments;
}
@Getter
@Setter
public static class AlarmRuleBindTerm {
private List<String> ruleId;
private List<Integer> branchId;
public static AlarmRuleBindTerm of(Object term) {
if(term instanceof AlarmRuleBindTerm){
return ((AlarmRuleBindTerm) term);
}
AlarmRuleBindTerm bindTerm = new AlarmRuleBindTerm();
if (term instanceof String) {
String str = ((String) term);
if (str.startsWith("{")) {
term = ObjectMappers.parseJson(str, Map.class);
} else if (str.startsWith("[")) {
term = ObjectMappers.parseJsonArray(str, Object.class);
} else if (str.contains(":")) {
// ruleId:-1,1,2,3
String[] split = str.split(":");
bindTerm.setRuleId(Collections.singletonList(split[0]));
bindTerm.setBranchId(ConverterUtils.convertToList(split[1], val -> CastUtils
.castNumber(val)
.intValue()));
} else {
bindTerm.setRuleId(Collections.singletonList(str));
}
}
if (term instanceof Collection) {
bindTerm.setRuleId(ConverterUtils.convertToList(term, String::valueOf));
}
if (term instanceof Map) {
FastBeanCopier.copy(term, bindTerm);
}
return bindTerm;
}
}
}