From 7e2e0c337c0bfceb22690ca2644713e9e63ed2f5 Mon Sep 17 00:00:00 2001 From: zhanghua <964552300@qq.com> Date: Mon, 5 Dec 2022 01:18:05 +0800 Subject: [PATCH] =?UTF-8?q?1.=20chain=E3=80=81script=E5=88=86=E7=A6=BB?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=E6=94=AF=E6=8C=81Apollo=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../liteflow-rule-apollo/pom.xml | 4 - .../parser/apollo/ApolloXmlELParser.java | 23 +- .../parser/apollo/util/ApolloParseHelper.java | 212 +++++++++++++++--- .../apollo/vo/ApolloParserConfigVO.java | 28 ++- pom.xml | 2 - 5 files changed, 215 insertions(+), 54 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-apollo/pom.xml b/liteflow-rule-plugin/liteflow-rule-apollo/pom.xml index f69b5075..23c2643b 100644 --- a/liteflow-rule-plugin/liteflow-rule-apollo/pom.xml +++ b/liteflow-rule-plugin/liteflow-rule-apollo/pom.xml @@ -26,10 +26,6 @@ provided - - com.alibaba.nacos - nacos-client - org.apache.httpcomponents httpclient diff --git a/liteflow-rule-plugin/liteflow-rule-apollo/src/main/java/com/yomahub/liteflow/parser/apollo/ApolloXmlELParser.java b/liteflow-rule-plugin/liteflow-rule-apollo/src/main/java/com/yomahub/liteflow/parser/apollo/ApolloXmlELParser.java index 9401af7c..f47ec484 100644 --- a/liteflow-rule-plugin/liteflow-rule-apollo/src/main/java/com/yomahub/liteflow/parser/apollo/ApolloXmlELParser.java +++ b/liteflow-rule-plugin/liteflow-rule-apollo/src/main/java/com/yomahub/liteflow/parser/apollo/ApolloXmlELParser.java @@ -4,6 +4,7 @@ import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.StrUtil; +import com.yomahub.liteflow.core.FlowInitHook; import com.yomahub.liteflow.parser.apollo.exception.ApolloException; import com.yomahub.liteflow.parser.apollo.util.ApolloParseHelper; import com.yomahub.liteflow.parser.apollo.vo.ApolloParserConfigVO; @@ -13,7 +14,6 @@ import com.yomahub.liteflow.property.LiteflowConfigGetter; import com.yomahub.liteflow.util.JsonUtil; import java.util.Objects; -import java.util.function.Consumer; /** * @Description: @@ -33,29 +33,32 @@ public class ApolloXmlELParser extends ClassXmlFlowELParser { } else if (StrUtil.isNotBlank(liteflowConfig.getRuleSourceExtData())) { apolloParserConfigVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), ApolloParserConfigVO.class); } + + // check config if (Objects.isNull(apolloParserConfigVO)) { throw new ApolloException("ruleSourceExtData or map is empty"); } + if (StrUtil.isBlank(apolloParserConfigVO.getChainNamespace())) { + throw new ApolloException("chainNamespace is empty, you must configure the chainNamespace property"); + } + apolloParseHelper = new ApolloParseHelper(apolloParserConfigVO); } catch (Exception e) { throw new ApolloException(e.getMessage()); } } + @Override public String parseCustom() { - Consumer parseConsumer = t -> { - try { - parse(t); - } catch (Exception e) { - throw new ApolloException(e.getMessage()); - } - }; + try { String content = apolloParseHelper.getContent(); - apolloParseHelper.checkContent(content); - apolloParseHelper.listen(parseConsumer); + FlowInitHook.addHook(() -> { + apolloParseHelper.listenApollo(); + return true; + }); return content; } catch (Exception e) { diff --git a/liteflow-rule-plugin/liteflow-rule-apollo/src/main/java/com/yomahub/liteflow/parser/apollo/util/ApolloParseHelper.java b/liteflow-rule-plugin/liteflow-rule-apollo/src/main/java/com/yomahub/liteflow/parser/apollo/util/ApolloParseHelper.java index 699a3214..11e2557c 100644 --- a/liteflow-rule-plugin/liteflow-rule-apollo/src/main/java/com/yomahub/liteflow/parser/apollo/util/ApolloParseHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-apollo/src/main/java/com/yomahub/liteflow/parser/apollo/util/ApolloParseHelper.java @@ -1,17 +1,26 @@ package com.yomahub.liteflow.parser.apollo.util; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; -import com.ctrip.framework.apollo.ConfigFile; +import com.ctrip.framework.apollo.Config; import com.ctrip.framework.apollo.ConfigService; -import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; -import com.yomahub.liteflow.exception.ParseException; +import com.ctrip.framework.apollo.enums.PropertyChangeType; +import com.ctrip.framework.apollo.model.ConfigChange; +import com.yomahub.liteflow.builder.LiteFlowNodeBuilder; +import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; +import com.yomahub.liteflow.enums.NodeTypeEnum; +import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.parser.apollo.exception.ApolloException; import com.yomahub.liteflow.parser.apollo.vo.ApolloParserConfigVO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.List; import java.util.Objects; -import java.util.function.Consumer; +import java.util.Set; +import java.util.stream.Collectors; /** * @Description: @@ -23,54 +32,197 @@ public class ApolloParseHelper { private static final Logger LOG = LoggerFactory.getLogger(ApolloParseHelper.class); + private final String CHAIN_XML_PATTERN = "{}"; + + private final String NODE_XML_PATTERN = "{}"; + + private final String NODE_ITEM_XML_PATTERN = ""; + + private final String XML_PATTERN = "{}{}"; + private final ApolloParserConfigVO apolloParserConfigVO; - private ConfigFile liteflowConfigFile; + private Config chainConfig; + + private Config scriptConfig; + public ApolloParseHelper(ApolloParserConfigVO apolloParserConfigVO) { this.apolloParserConfigVO = apolloParserConfigVO; try { - liteflowConfigFile = ConfigService.getConfigFile(apolloParserConfigVO.getNamespace(), ConfigFileFormat.XML); + chainConfig = ConfigService.getConfig(apolloParserConfigVO.getChainNamespace()); + String scriptNamespace; + // scriptConfig is optional + if (StrUtil.isNotBlank(scriptNamespace = apolloParserConfigVO.getScriptNamespace())) { + scriptConfig = ConfigService.getConfig(scriptNamespace); + } } catch (Exception e) { - LOG.error("[ApolloParseHelper] liteflowConfigFile get init error, apolloParserConfigVO:{}", apolloParserConfigVO); throw new ApolloException(e.getMessage()); } } public String getContent() { + try { - ConfigFile configFile = ConfigService.getConfigFile(apolloParserConfigVO.getNamespace(), ConfigFileFormat.XML); - String content; - if (Objects.isNull(configFile) || StrUtil.isBlank(content = configFile.getContent())) { - throw new ApolloException(String.format("not find config file, namespace:%s", apolloParserConfigVO.getNamespace())); + // 1. handle chain + Set propertyNames = chainConfig.getPropertyNames(); + if (CollectionUtil.isEmpty(propertyNames)) { + throw new ApolloException(StrUtil.format("There are no chains in namespace : {}", apolloParserConfigVO.getChainNamespace())); } - return content; + List chainItemContentList = propertyNames.stream() + .map(item -> StrUtil.format(CHAIN_XML_PATTERN, item, chainConfig.getProperty(item, StrUtil.EMPTY))) + .collect(Collectors.toList()); + // merge all chain content + String chainAllContent = CollUtil.join(chainItemContentList, StrUtil.EMPTY); + + // 2. handle script if needed + String scriptAllContent = StrUtil.EMPTY; + Set scriptNamespaces; + if (Objects.nonNull(scriptConfig) && CollectionUtil.isNotEmpty(scriptNamespaces = scriptConfig.getPropertyNames())) { + + List scriptItemContentList = scriptNamespaces.stream() + .map(item -> convert(item, scriptConfig.getProperty(item, StrUtil.EMPTY))) + .filter(Objects::nonNull) + .map(item -> StrUtil.format(NODE_ITEM_XML_PATTERN, item.getNodeId(), item.getName(), item.getType(), item.getScript())) + .collect(Collectors.toList()); + + scriptAllContent = StrUtil.format(NODE_XML_PATTERN, CollUtil.join(scriptItemContentList, StrUtil.EMPTY)); + } + + return StrUtil.format(XML_PATTERN, scriptAllContent, chainAllContent); } catch (Exception e) { throw new ApolloException(e.getMessage()); } } - /** - * 检查 content 是否合法 - */ - public void checkContent(String content) { - if (StrUtil.isBlank(content)) { - String error = StrUtil.format("the node[{}] value is empty", apolloParserConfigVO.toString()); - throw new ParseException(error); - } - } /** - * 监听 apollo 数据变化 + * listen apollo config change */ - public void listen(Consumer parseConsumer) { - try { - liteflowConfigFile.addChangeListener(configFileChangeEvent -> { - String newContext = configFileChangeEvent.getNewValue(); - parseConsumer.accept(newContext); - }); - } catch (Exception e) { - throw new ApolloException(e.getMessage()); + public void listenApollo() { + + // chain + chainConfig.addChangeListener(changeEvent -> + changeEvent.changedKeys().forEach(changeKey -> { + ConfigChange configChange = changeEvent.getChange(changeKey); + String newValue = configChange.getNewValue(); + PropertyChangeType changeType = configChange.getChangeType(); + switch (changeType) { + case ADDED: + case MODIFIED: + LOG.info("starting reload flow config... {} key={} value={},", changeType.name(), changeKey, newValue); + LiteFlowChainELBuilder.createChain() + .setChainId(changeKey) + .setEL(newValue) + .build(); + break; + case DELETED: + LOG.info("starting reload flow config... delete key={}", changeKey); + FlowBus.removeChain(changeKey); + + } + })); + + // script + if (Objects.isNull(scriptConfig)) { + // no script config + return; + } + scriptConfig.addChangeListener(changeEvent -> + changeEvent.changedKeys().forEach(changeKey -> { + ConfigChange configChange = changeEvent.getChange(changeKey); + String newValue = configChange.getNewValue(); + + PropertyChangeType changeType = configChange.getChangeType(); + + NodeSimpleVO nodeSimpleVO; + switch (changeType) { + case ADDED: + case MODIFIED: + LOG.info("starting reload flow config... {} key={} value={},", changeType.name(), changeKey, newValue); + nodeSimpleVO = convert(changeKey, newValue); + LiteFlowNodeBuilder.createScriptNode() + .setId(nodeSimpleVO.getNodeId()) + .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType())) + .setName(nodeSimpleVO.getName()) + .setScript(nodeSimpleVO.getScript()) + .build(); + break; + case DELETED: + LOG.info("starting reload flow config... delete key={}", changeKey); + nodeSimpleVO = convert(changeKey, null); + FlowBus.getNodeMap().remove(nodeSimpleVO.getNodeId()); + } + })); + + } + + + private NodeSimpleVO convert(String key, String value) { + //不需要去理解这串正则,就是一个匹配冒号的 + //一定得是a:b,或是a:b:c...这种完整类型的字符串的 + List matchItemList = ReUtil.findAllGroup0("(?<=[^:]:)[^:]+|[^:]+(?=:[^:])", key); + if (CollUtil.isEmpty(matchItemList)) { + return null; + } + + NodeSimpleVO nodeSimpleVO = new NodeSimpleVO(); + if (matchItemList.size() > 1) { + nodeSimpleVO.setNodeId(matchItemList.get(0)); + nodeSimpleVO.setType(matchItemList.get(1)); + } + + if (matchItemList.size() > 2) { + nodeSimpleVO.setName(matchItemList.get(2)); + } + + // set script + nodeSimpleVO.setScript(value); + + return nodeSimpleVO; + } + + + private static class NodeSimpleVO { + + private String nodeId; + + private String type; + + private String name = StrUtil.EMPTY; + + private String script; + + public String getNodeId() { + return nodeId; + } + + public void setNodeId(String nodeId) { + this.nodeId = nodeId; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getScript() { + return script; + } + + public void setScript(String script) { + this.script = script; } } diff --git a/liteflow-rule-plugin/liteflow-rule-apollo/src/main/java/com/yomahub/liteflow/parser/apollo/vo/ApolloParserConfigVO.java b/liteflow-rule-plugin/liteflow-rule-apollo/src/main/java/com/yomahub/liteflow/parser/apollo/vo/ApolloParserConfigVO.java index ed79f75e..311fd3bd 100644 --- a/liteflow-rule-plugin/liteflow-rule-apollo/src/main/java/com/yomahub/liteflow/parser/apollo/vo/ApolloParserConfigVO.java +++ b/liteflow-rule-plugin/liteflow-rule-apollo/src/main/java/com/yomahub/liteflow/parser/apollo/vo/ApolloParserConfigVO.java @@ -7,28 +7,40 @@ package com.yomahub.liteflow.parser.apollo.vo; */ public class ApolloParserConfigVO { - private String namespace; + private String chainNamespace; + + private String scriptNamespace; public ApolloParserConfigVO() { } - public ApolloParserConfigVO(String namespace) { - this.namespace = namespace; + public ApolloParserConfigVO(String chainNamespace, String scriptNamespace) { + this.chainNamespace = chainNamespace; + this.scriptNamespace = scriptNamespace; } - public String getNamespace() { - return namespace; + public String getChainNamespace() { + return chainNamespace; } - public void setNamespace(String namespace) { - this.namespace = namespace; + public void setChainNamespace(String chainNamespace) { + this.chainNamespace = chainNamespace; + } + + public String getScriptNamespace() { + return scriptNamespace; + } + + public void setScriptNamespace(String scriptNamespace) { + this.scriptNamespace = scriptNamespace; } @Override public String toString() { return "ApolloParserConfigVO{" + - "namespace='" + namespace + '\'' + + "chainNamespace='" + chainNamespace + '\'' + + ", scriptNamespace='" + scriptNamespace + '\'' + '}'; } } diff --git a/pom.xml b/pom.xml index 36d2115c..3d91f351 100644 --- a/pom.xml +++ b/pom.xml @@ -377,8 +377,6 @@ liteflow-spring-boot-starter liteflow-spring liteflow-testcase-el - liteflow-rule-apollo - liteflow-testcase-el-apollo-springboot