From 4fbc388845219deffa156c6ee9a0beeaae88ce45 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Tue, 27 Jun 2023 23:49:04 +0800 Subject: [PATCH 01/41] feat:redis file --- .../liteflow-rule-redis/pom.xml | 25 +++++++++++++++++++ .../parser/redis/RedisXmlELParser.java | 4 +++ .../redis/exception/RedisException.java | 4 +++ .../parser/redis/util/RedisParserHelper.java | 4 +++ .../parser/redis/vo/RedisParserVO.java | 4 +++ .../spi/redis/RedisParserClassNameSpi.java | 15 +++++++++++ liteflow-rule-plugin/pom.xml | 1 + 7 files changed, 57 insertions(+) create mode 100644 liteflow-rule-plugin/liteflow-rule-redis/pom.xml create mode 100644 liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java create mode 100644 liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/exception/RedisException.java create mode 100644 liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java create mode 100644 liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java create mode 100644 liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/spi/redis/RedisParserClassNameSpi.java diff --git a/liteflow-rule-plugin/liteflow-rule-redis/pom.xml b/liteflow-rule-plugin/liteflow-rule-redis/pom.xml new file mode 100644 index 00000000..9233cdbc --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-redis/pom.xml @@ -0,0 +1,25 @@ + + + + liteflow-rule-plugin + com.yomahub + ${revision} + ../pom.xml + + 4.0.0 + + liteflow-rule-redis + + + + com.yomahub + liteflow-core + ${revision} + true + provided + + + + \ No newline at end of file diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java new file mode 100644 index 00000000..17d33811 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java @@ -0,0 +1,4 @@ +package com.yomahub.liteflow.parser.redis; + +public class RedisXmlELParser { +} diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/exception/RedisException.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/exception/RedisException.java new file mode 100644 index 00000000..6778b54c --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/exception/RedisException.java @@ -0,0 +1,4 @@ +package com.yomahub.liteflow.parser.redis.exception; + +public class RedisException { +} diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java new file mode 100644 index 00000000..62d229a2 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java @@ -0,0 +1,4 @@ +package com.yomahub.liteflow.parser.redis.util; + +public class RedisParserHelper { +} diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java new file mode 100644 index 00000000..b3138460 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java @@ -0,0 +1,4 @@ +package com.yomahub.liteflow.parser.redis.vo; + +public class RedisParserVO { +} diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/spi/redis/RedisParserClassNameSpi.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/spi/redis/RedisParserClassNameSpi.java new file mode 100644 index 00000000..7fe750c1 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/spi/redis/RedisParserClassNameSpi.java @@ -0,0 +1,15 @@ +package com.yomahub.liteflow.parser.spi.redis; + +import com.yomahub.liteflow.parser.redis.RedisXmlELParser; +import com.yomahub.liteflow.parser.spi.ParserClassNameSpi; + +/** + * Redis 解析器 SPI 实现 + */ +public class RedisParserClassNameSpi implements ParserClassNameSpi { + + @Override + public String getSpiClassName() { + return RedisXmlELParser.class.getName(); + } +} diff --git a/liteflow-rule-plugin/pom.xml b/liteflow-rule-plugin/pom.xml index 02de13a6..f915ebb7 100644 --- a/liteflow-rule-plugin/pom.xml +++ b/liteflow-rule-plugin/pom.xml @@ -16,6 +16,7 @@ liteflow-rule-nacos liteflow-rule-etcd liteflow-rule-apollo + liteflow-rule-redis liteflow-rule-plugin From 0e22e66536414eead631145b58b606447915a9fa Mon Sep 17 00:00:00 2001 From: houxinyu Date: Wed, 28 Jun 2023 00:14:50 +0800 Subject: [PATCH 02/41] add ParserVO --- .../parser/redis/vo/RedisParserVO.java | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java index b3138460..23b092ff 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java @@ -1,4 +1,114 @@ package com.yomahub.liteflow.parser.redis.vo; public class RedisParserVO { + + /*连接地址*/ + private String url; + + /*端口号*/ + private String port; + + /*账号名*/ + private String username; + + /*密码*/ + private String password; + + /*是否采用轮询机制 默认为轮询 否则选择pub/sub机制*/ + private boolean isPolling = true; + + /*轮询时间间隔(ms) 默认1分组 若选择pub/sub机制可不配置*/ + private String pollingInterval = "60000"; + + /*chain表配置的数据库号*/ + private String chainDataBase; + + /*chain配置的键名*/ + private String chainKey; + + /*脚本表配置的数据库号*/ + private String scriptDataBase; + + /*脚本配置的键名*/ + private String scriptKey; + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getPort() { + return port; + } + + public void setPort(String port) { + this.port = port; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public boolean isPolling() { + return isPolling; + } + + public void setPolling(boolean polling) { + isPolling = polling; + } + + public String getPollingInterval() { + return pollingInterval; + } + + public void setPollingInterval(String pollingInterval) { + this.pollingInterval = pollingInterval; + } + + public String getChainDataBase() { + return chainDataBase; + } + + public void setChainDataBase(String chainDataBase) { + this.chainDataBase = chainDataBase; + } + + public String getChainKey() { + return chainKey; + } + + public void setChainKey(String chainKey) { + this.chainKey = chainKey; + } + + public String getScriptDataBase() { + return scriptDataBase; + } + + public void setScriptDataBase(String scriptDataBase) { + this.scriptDataBase = scriptDataBase; + } + + public String getScriptKey() { + return scriptKey; + } + + public void setScriptKey(String scriptKey) { + this.scriptKey = scriptKey; + } } From e684db9ee825a66002b8317140cf4587fc2588dd Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sat, 1 Jul 2023 11:19:23 +0800 Subject: [PATCH 03/41] =?UTF-8?q?=E6=B7=BB=E5=8A=A0XML=20Parser?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../parser/redis/RedisXmlELParser.java | 62 ++++++++++++++++++- .../redis/exception/RedisException.java | 14 ++++- .../parser/redis/util/RedisParserHelper.java | 5 ++ .../parser/redis/vo/RedisParserVO.java | 18 +++--- 4 files changed, 88 insertions(+), 11 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java index 17d33811..8deb542c 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java @@ -1,4 +1,64 @@ package com.yomahub.liteflow.parser.redis; -public class RedisXmlELParser { +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.bean.copier.CopyOptions; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.text.StrFormatter; +import cn.hutool.core.util.StrUtil; +import com.yomahub.liteflow.parser.el.ClassXmlFlowELParser; +import com.yomahub.liteflow.parser.redis.exception.RedisException; +import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.property.LiteflowConfigGetter; +import com.yomahub.liteflow.util.JsonUtil; + +import java.util.Objects; + +public class RedisXmlELParser extends ClassXmlFlowELParser { + + private static final String ERROR_COMMON_MSG = "ruleSourceExtData or map is empty"; + + private static final String ERROR_MSG_PATTERN = "uleSourceExtData {} is blank"; + + public RedisXmlELParser() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + + try{ + RedisParserVO redisParserVO = null; + if (MapUtil.isNotEmpty((liteflowConfig.getRuleSourceExtDataMap()))) { + redisParserVO = BeanUtil.toBean(liteflowConfig.getRuleSourceExtDataMap(), + RedisParserVO.class, CopyOptions.create()); + } + else if (StrUtil.isNotBlank(liteflowConfig.getRuleSourceExtData())) { + redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + } + if (Objects.isNull(redisParserVO)) { + throw new RedisException(ERROR_COMMON_MSG); + } + + //检查配置文件 + checkParserVO(redisParserVO); + } + catch (RedisException redisException){ + throw redisException; + } + catch (Exception e){ + throw new RedisException(e.getMessage()); + } + } + + @Override + public String parseCustom() { + //todo + return null; + } + + private void checkParserVO(RedisParserVO redisParserVO) { + if (StrUtil.isEmpty(redisParserVO.getHost())){ + throw new RedisException(StrFormatter.format(ERROR_MSG_PATTERN, "host")); + } + if (StrUtil.isEmpty(redisParserVO.getPort())){ + throw new RedisException(StrFormatter.format(ERROR_MSG_PATTERN, "port")); + } + } } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/exception/RedisException.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/exception/RedisException.java index 6778b54c..021dce8e 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/exception/RedisException.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/exception/RedisException.java @@ -1,4 +1,16 @@ package com.yomahub.liteflow.parser.redis.exception; -public class RedisException { +public class RedisException extends RuntimeException{ + + private String message; + + public RedisException(String message) { + super(); + this.message = message; + } + + @Override + public String getMessage() { + return message; + } } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java index 62d229a2..d361cb74 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java @@ -1,4 +1,9 @@ package com.yomahub.liteflow.parser.redis.util; +import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; + public class RedisParserHelper { + + private RedisParserVO redisParserVO; + } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java index 23b092ff..a96e8bf8 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java @@ -3,7 +3,7 @@ package com.yomahub.liteflow.parser.redis.vo; public class RedisParserVO { /*连接地址*/ - private String url; + private String host; /*端口号*/ private String port; @@ -15,9 +15,9 @@ public class RedisParserVO { private String password; /*是否采用轮询机制 默认为轮询 否则选择pub/sub机制*/ - private boolean isPolling = true; + private String isPolling = "true"; - /*轮询时间间隔(ms) 默认1分组 若选择pub/sub机制可不配置*/ + /*轮询时间间隔(ms) 默认1分钟 若选择pub/sub机制可不配置*/ private String pollingInterval = "60000"; /*chain表配置的数据库号*/ @@ -32,12 +32,12 @@ public class RedisParserVO { /*脚本配置的键名*/ private String scriptKey; - public String getUrl() { - return url; + public String getHost() { + return host; } - public void setUrl(String url) { - this.url = url; + public void setHost(String url) { + this.host = host; } public String getPort() { @@ -64,11 +64,11 @@ public class RedisParserVO { this.password = password; } - public boolean isPolling() { + public String isPolling() { return isPolling; } - public void setPolling(boolean polling) { + public void setPolling(String polling) { isPolling = polling; } From 1c32e2b5c57fb58b2396929727647485f4e97046 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sun, 2 Jul 2023 00:46:37 +0800 Subject: [PATCH 04/41] add redisson --- .../liteflow-rule-redis/pom.xml | 6 +++ .../parser/redis/util/RedisParserHelper.java | 38 +++++++++++++++++++ pom.xml | 1 + 3 files changed, 45 insertions(+) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/pom.xml b/liteflow-rule-plugin/liteflow-rule-redis/pom.xml index 9233cdbc..183bacb0 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/pom.xml +++ b/liteflow-rule-plugin/liteflow-rule-redis/pom.xml @@ -20,6 +20,12 @@ true provided + + + org.redisson + redisson + ${redisson.version} + \ No newline at end of file diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java index d361cb74..964c4de2 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java @@ -1,9 +1,47 @@ package com.yomahub.liteflow.parser.redis.util; +import cn.hutool.core.util.ObjectUtil; +import com.yomahub.liteflow.parser.redis.exception.RedisException; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; +import com.yomahub.liteflow.spi.holder.ContextAwareHolder; +import org.redisson.api.RedissonClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class RedisParserHelper { + private static final Logger LOG = LoggerFactory.getLogger(RedisParserHelper.class); + private RedisParserVO redisParserVO; + private final String CHAIN_XML_PATTERN = "{}"; + + private final String NODE_XML_PATTERN = "{}"; + + private static final String NODE_ITEM_XML_PATTERN = ""; + + private static final String NODE_ITEM_WITH_LANGUAGE_XML_PATTERN = ""; + + private static final String XML_PATTERN = "{}{}"; + + private RedissonClient redissonClient; + + public RedisParserHelper(RedisParserVO redisParserVO) { + this.redisParserVO = redisParserVO; + + try{ + try{ + this.redissonClient = ContextAwareHolder.loadContextAware().getBean(RedissonClient.class); + } + catch (Exception ignored){ + } + if(ObjectUtil.isNull(redissonClient)){ + //todo get client + } + } + catch (Exception e){ + throw new RedisException(e.getMessage()); + } + + } } diff --git a/pom.xml b/pom.xml index 0cfbdd3f..c61e7dfe 100644 --- a/pom.xml +++ b/pom.xml @@ -74,6 +74,7 @@ 3.0.1 5.3.3 2.11.0 + 3.20.0 From 9e2b8d5dbfe7349608bd7235c3ab4cdebf60b5be Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sun, 2 Jul 2023 13:44:35 +0800 Subject: [PATCH 05/41] add init --- .../parser/redis/RedisXmlELParser.java | 5 +++ .../parser/redis/util/RedisParserHelper.java | 39 +++++++++++++++++-- .../parser/redis/vo/RedisParserVO.java | 15 +------ 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java index 8deb542c..884276d3 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java @@ -7,6 +7,7 @@ import cn.hutool.core.text.StrFormatter; import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.parser.el.ClassXmlFlowELParser; import com.yomahub.liteflow.parser.redis.exception.RedisException; +import com.yomahub.liteflow.parser.redis.util.RedisParserHelper; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import com.yomahub.liteflow.property.LiteflowConfig; import com.yomahub.liteflow.property.LiteflowConfigGetter; @@ -16,6 +17,8 @@ import java.util.Objects; public class RedisXmlELParser extends ClassXmlFlowELParser { + private final RedisParserHelper redisParserHelper; + private static final String ERROR_COMMON_MSG = "ruleSourceExtData or map is empty"; private static final String ERROR_MSG_PATTERN = "uleSourceExtData {} is blank"; @@ -38,6 +41,8 @@ public class RedisXmlELParser extends ClassXmlFlowELParser { //检查配置文件 checkParserVO(redisParserVO); + + redisParserHelper = new RedisParserHelper(redisParserVO); } catch (RedisException redisException){ throw redisException; diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java index 964c4de2..403f3577 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java @@ -1,10 +1,14 @@ package com.yomahub.liteflow.parser.redis.util; +import cn.hutool.core.text.StrFormatter; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.parser.redis.exception.RedisException; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import com.yomahub.liteflow.spi.holder.ContextAwareHolder; +import org.redisson.Redisson; import org.redisson.api.RedissonClient; +import org.redisson.config.Config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,6 +18,8 @@ public class RedisParserHelper { private RedisParserVO redisParserVO; + private final String REDIS_URL_PATTERN = "redis://{}:{}"; + private final String CHAIN_XML_PATTERN = "{}"; private final String NODE_XML_PATTERN = "{}"; @@ -24,19 +30,31 @@ public class RedisParserHelper { private static final String XML_PATTERN = "{}{}"; - private RedissonClient redissonClient; + private RedissonClient chainClient; + + private RedissonClient scriptClient; public RedisParserHelper(RedisParserVO redisParserVO) { this.redisParserVO = redisParserVO; try{ try{ - this.redissonClient = ContextAwareHolder.loadContextAware().getBean(RedissonClient.class); + this.chainClient = ContextAwareHolder.loadContextAware().getBean("chainClient"); + this.scriptClient = ContextAwareHolder.loadContextAware().getBean("scriptClient"); } catch (Exception ignored){ } - if(ObjectUtil.isNull(redissonClient)){ - //todo get client + if(ObjectUtil.isNull(chainClient)){ + Config config = new Config(); + config = getRedissonConfig(redisParserVO, config, + Integer.parseInt(redisParserVO.getChainDataBase())); + this.chainClient = Redisson.create(config); + //如果有脚本数据 + if (StrUtil.isNotBlank(redisParserVO.getScriptDataBase())){ + config = getRedissonConfig(redisParserVO, config, + Integer.parseInt(redisParserVO.getScriptDataBase())); + this.scriptClient = Redisson.create(config); + } } } catch (Exception e){ @@ -44,4 +62,17 @@ public class RedisParserHelper { } } + + private Config getRedissonConfig(RedisParserVO redisParserVO, Config config, Integer dataBase){ + String redisAddress = StrFormatter.format(REDIS_URL_PATTERN, redisParserVO.getHost(), redisParserVO.getPort()); + if (StrUtil.isNotBlank(redisParserVO.getPassword())){ + config.useSingleServer().setAddress(redisAddress) + .setPassword(redisParserVO.getPassword()) + .setDatabase(dataBase); + } else{ + config.useSingleServer().setAddress(redisAddress) + .setDatabase(dataBase); + } + return config; + } } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java index a96e8bf8..d2a2d9d2 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java @@ -8,9 +8,6 @@ public class RedisParserVO { /*端口号*/ private String port; - /*账号名*/ - private String username; - /*密码*/ private String password; @@ -26,10 +23,10 @@ public class RedisParserVO { /*chain配置的键名*/ private String chainKey; - /*脚本表配置的数据库号*/ + /*脚本表配置的数据库号 若没有脚本数据可不配置*/ private String scriptDataBase; - /*脚本配置的键名*/ + /*脚本配置的键名 若没有脚本数据可不配置*/ private String scriptKey; public String getHost() { @@ -48,14 +45,6 @@ public class RedisParserVO { this.port = port; } - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - public String getPassword() { return password; } From a55f30c6297234c3b2357eff6d8780beb1e3e49c Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sun, 2 Jul 2023 18:50:30 +0800 Subject: [PATCH 06/41] add getContent() --- .../parser/redis/RedisXmlELParser.java | 15 +- .../parser/redis/util/RedisParserHelper.java | 154 ++++++++++++++++++ 2 files changed, 167 insertions(+), 2 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java index 884276d3..b48958a0 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java @@ -5,6 +5,7 @@ import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.map.MapUtil; import cn.hutool.core.text.StrFormatter; import cn.hutool.core.util.StrUtil; +import com.yomahub.liteflow.core.FlowInitHook; import com.yomahub.liteflow.parser.el.ClassXmlFlowELParser; import com.yomahub.liteflow.parser.redis.exception.RedisException; import com.yomahub.liteflow.parser.redis.util.RedisParserHelper; @@ -54,8 +55,18 @@ public class RedisXmlELParser extends ClassXmlFlowELParser { @Override public String parseCustom() { - //todo - return null; + try { + String content = redisParserHelper.getContent(); + FlowInitHook.addHook(() -> { + // redisParserHelper.listenApollo(); + return true; + }); + return content; + + } + catch (Exception e) { + throw new RedisException(e.getMessage()); + } } private void checkParserVO(RedisParserVO redisParserVO) { diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java index 403f3577..7f70fda5 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java @@ -1,17 +1,27 @@ package com.yomahub.liteflow.parser.redis.util; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.text.StrFormatter; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.parser.redis.exception.RedisException; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import com.yomahub.liteflow.spi.holder.ContextAwareHolder; import org.redisson.Redisson; +import org.redisson.api.RMapCache; import org.redisson.api.RedissonClient; import org.redisson.config.Config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + public class RedisParserHelper { private static final Logger LOG = LoggerFactory.getLogger(RedisParserHelper.class); @@ -75,4 +85,148 @@ public class RedisParserHelper { } return config; } + + public String getContent(){ + try{ + // 检查chainKey下有没有子节点 + RMapCache chainKey = chainClient.getMapCache(redisParserVO.getChainKey()); + Set chainNameSet = chainKey.keySet(); + if (CollectionUtil.isEmpty(chainNameSet)) { + throw new RedisException(StrUtil.format("There are no chains in key [{}]", + redisParserVO.getChainKey()); + } + // 获取chainKey下的所有子节点内容List + List chainItemContentList = new ArrayList<>(); + for (String chainName : chainNameSet) { + String chainData = chainKey.get(chainName); + if (StrUtil.isNotBlank(chainData)) { + chainItemContentList.add(StrUtil.format(CHAIN_XML_PATTERN, chainName, chainData)); + } + } + // 合并成所有chain的xml内容 + String chainAllContent = CollUtil.join(chainItemContentList, StrUtil.EMPTY); + + // 检查是否有脚本内容,如果有,进行脚本内容的获取 + String scriptAllContent = StrUtil.EMPTY; + if (hasScript()){ + RMapCache scriptKey = scriptClient.getMapCache(redisParserVO.getScriptKey()); + Set scriptKeySet = scriptKey.keySet(); + + List scriptItemContentList = new ArrayList<>(); + for (String scriptKeyValue : scriptKeySet){ + NodeSimpleVO nodeSimpleVO = convert(scriptKeyValue); + if (Objects.isNull(nodeSimpleVO)) { + throw new RedisException( + StrUtil.format("The name of the redis key is invalid:{}", scriptKeyValue)); + } + String scriptData = scriptKey.get(scriptKeyValue); + + // 有语言类型 + if (StrUtil.isNotBlank(nodeSimpleVO.getLanguage())) { + scriptItemContentList.add(StrUtil.format(NODE_ITEM_WITH_LANGUAGE_XML_PATTERN, + nodeSimpleVO.getNodeId(), nodeSimpleVO.getName(), nodeSimpleVO.getType(), + nodeSimpleVO.getLanguage(), scriptData)); + } + // 没有语言类型 + else { + scriptItemContentList.add(StrUtil.format(NODE_ITEM_XML_PATTERN, nodeSimpleVO.getNodeId(), + nodeSimpleVO.getName(), nodeSimpleVO.getType(), scriptData)); + } + + scriptAllContent = StrUtil.format(NODE_XML_PATTERN, + CollUtil.join(scriptItemContentList, StrUtil.EMPTY)); + } + } + + return StrUtil.format(XML_PATTERN, scriptAllContent, chainAllContent); + } + catch (Exception e){ + throw new RedisException(e.getMessage()); + } + } + + public boolean hasScript(){ + // 没有scriptClient或没有配置scriptDataBase + if (Objects.isNull(scriptClient) || StrUtil.isNotBlank(redisParserVO.getScriptDataBase())) { + return false; + } + try { + // 存在这个节点,但是子节点不存在 + RMapCache scriptKey = scriptClient.getMapCache(redisParserVO.getScriptKey()); + Set scriptKeySet = scriptKey.keySet(); + return !CollUtil.isEmpty(scriptKeySet); + } + catch (Exception e) { + return false; + } + } + + public NodeSimpleVO convert(String str) { + // 不需要去理解这串正则,就是一个匹配冒号的 + // 一定得是a:b,或是a:b:c...这种完整类型的字符串的 + List matchItemList = ReUtil.findAllGroup0("(?<=[^:]:)[^:]+|[^:]+(?=:[^:])", str); + 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)); + } + + if (matchItemList.size() > 3) { + nodeSimpleVO.setLanguage(matchItemList.get(3)); + } + + return nodeSimpleVO; + } + + private static class NodeSimpleVO { + + private String nodeId; + + private String type; + + private String name = StrUtil.EMPTY; + + private String language; + + 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 getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + } } From ac446950c3a40cbcbd1f5b61dfe27c6d5bdb02c8 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sun, 2 Jul 2023 19:45:54 +0800 Subject: [PATCH 07/41] add listener --- .../parser/redis/RedisXmlELParser.java | 2 +- .../parser/redis/util/RedisParserHelper.java | 123 ++++++++++++++---- 2 files changed, 98 insertions(+), 27 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java index b48958a0..8cf02e38 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java @@ -58,7 +58,7 @@ public class RedisXmlELParser extends ClassXmlFlowELParser { try { String content = redisParserHelper.getContent(); FlowInitHook.addHook(() -> { - // redisParserHelper.listenApollo(); + redisParserHelper.listenRedis(); return true; }); return content; diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java index 7f70fda5..ee9fa67a 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java @@ -6,12 +6,20 @@ import cn.hutool.core.text.StrFormatter; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; +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.redis.exception.RedisException; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import com.yomahub.liteflow.spi.holder.ContextAwareHolder; import org.redisson.Redisson; import org.redisson.api.RMapCache; import org.redisson.api.RedissonClient; +import org.redisson.api.map.event.EntryCreatedListener; +import org.redisson.api.map.event.EntryEvent; +import org.redisson.api.map.event.EntryRemovedListener; +import org.redisson.api.map.event.EntryUpdatedListener; import org.redisson.config.Config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -20,13 +28,12 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Set; -import java.util.stream.Collectors; public class RedisParserHelper { private static final Logger LOG = LoggerFactory.getLogger(RedisParserHelper.class); - private RedisParserVO redisParserVO; + private final RedisParserVO redisParserVO; private final String REDIS_URL_PATTERN = "redis://{}:{}"; @@ -47,53 +54,51 @@ public class RedisParserHelper { public RedisParserHelper(RedisParserVO redisParserVO) { this.redisParserVO = redisParserVO; - try{ - try{ + try { + try { this.chainClient = ContextAwareHolder.loadContextAware().getBean("chainClient"); this.scriptClient = ContextAwareHolder.loadContextAware().getBean("scriptClient"); + } catch (Exception ignored) { } - catch (Exception ignored){ - } - if(ObjectUtil.isNull(chainClient)){ - Config config = new Config(); - config = getRedissonConfig(redisParserVO, config, + if (ObjectUtil.isNull(chainClient)) { + Config config = getRedissonConfig(redisParserVO, Integer.parseInt(redisParserVO.getChainDataBase())); this.chainClient = Redisson.create(config); //如果有脚本数据 - if (StrUtil.isNotBlank(redisParserVO.getScriptDataBase())){ - config = getRedissonConfig(redisParserVO, config, + if (StrUtil.isNotBlank(redisParserVO.getScriptDataBase())) { + config = getRedissonConfig(redisParserVO, Integer.parseInt(redisParserVO.getScriptDataBase())); this.scriptClient = Redisson.create(config); } } - } - catch (Exception e){ + } catch (Exception e) { throw new RedisException(e.getMessage()); } } - private Config getRedissonConfig(RedisParserVO redisParserVO, Config config, Integer dataBase){ + private Config getRedissonConfig(RedisParserVO redisParserVO, Integer dataBase) { + Config config = new Config(); String redisAddress = StrFormatter.format(REDIS_URL_PATTERN, redisParserVO.getHost(), redisParserVO.getPort()); - if (StrUtil.isNotBlank(redisParserVO.getPassword())){ + if (StrUtil.isNotBlank(redisParserVO.getPassword())) { config.useSingleServer().setAddress(redisAddress) .setPassword(redisParserVO.getPassword()) .setDatabase(dataBase); - } else{ + } else { config.useSingleServer().setAddress(redisAddress) .setDatabase(dataBase); } return config; } - public String getContent(){ - try{ + public String getContent() { + try { // 检查chainKey下有没有子节点 RMapCache chainKey = chainClient.getMapCache(redisParserVO.getChainKey()); Set chainNameSet = chainKey.keySet(); if (CollectionUtil.isEmpty(chainNameSet)) { throw new RedisException(StrUtil.format("There are no chains in key [{}]", - redisParserVO.getChainKey()); + redisParserVO.getChainKey())); } // 获取chainKey下的所有子节点内容List List chainItemContentList = new ArrayList<>(); @@ -108,12 +113,12 @@ public class RedisParserHelper { // 检查是否有脚本内容,如果有,进行脚本内容的获取 String scriptAllContent = StrUtil.EMPTY; - if (hasScript()){ + if (hasScript()) { RMapCache scriptKey = scriptClient.getMapCache(redisParserVO.getScriptKey()); Set scriptKeySet = scriptKey.keySet(); List scriptItemContentList = new ArrayList<>(); - for (String scriptKeyValue : scriptKeySet){ + for (String scriptKeyValue : scriptKeySet) { NodeSimpleVO nodeSimpleVO = convert(scriptKeyValue); if (Objects.isNull(nodeSimpleVO)) { throw new RedisException( @@ -139,13 +144,12 @@ public class RedisParserHelper { } return StrUtil.format(XML_PATTERN, scriptAllContent, chainAllContent); - } - catch (Exception e){ + } catch (Exception e) { throw new RedisException(e.getMessage()); } } - public boolean hasScript(){ + public boolean hasScript() { // 没有scriptClient或没有配置scriptDataBase if (Objects.isNull(scriptClient) || StrUtil.isNotBlank(redisParserVO.getScriptDataBase())) { return false; @@ -155,12 +159,79 @@ public class RedisParserHelper { RMapCache scriptKey = scriptClient.getMapCache(redisParserVO.getScriptKey()); Set scriptKeySet = scriptKey.keySet(); return !CollUtil.isEmpty(scriptKeySet); - } - catch (Exception e) { + } catch (Exception e) { return false; } } + /** + * 监听 redis key + */ + public void listenRedis() { + //监听 chain + RMapCache chainKey = chainClient.getMapCache(redisParserVO.getChainKey()); + //添加新 chain + chainKey.addListener((EntryCreatedListener) event -> { + LOG.info("starting reload flow config... create key={} value={},", event.getKey(), event.getValue()); + LiteFlowChainELBuilder.createChain().setChainId(event.getKey()).setEL(event.getValue()).build(); + }); + //修改 chain + chainKey.addListener((EntryUpdatedListener) event -> { + LOG.info("starting reload flow config... update path={} new value={},", event.getKey(), event.getValue()); + LiteFlowChainELBuilder.createChain().setChainId(event.getKey()).setEL(event.getValue()).build(); + }); + //删除 chain + chainKey.addListener((EntryRemovedListener) event -> { + LOG.info("starting reload flow config... delete key={}", event.getKey()); + FlowBus.removeChain(event.getKey()); + }); + + //监听 script + if (Objects.nonNull(scriptClient) && StrUtil.isNotBlank(redisParserVO.getScriptDataBase())) { + RMapCache scriptKey = scriptClient.getMapCache(redisParserVO.getScriptKey()); + //添加 script + scriptKey.addListener((EntryCreatedListener) event -> { + LOG.info("starting reload flow config... create key={} value={},", event.getKey(), event.getValue()); + NodeSimpleVO nodeSimpleVO = convert(event.getKey()); + changeScriptNode(nodeSimpleVO, event.getValue()); + }); + //修改 script + scriptKey.addListener((EntryUpdatedListener) event -> { + LOG.info("starting reload flow config... update path={} new value={},", event.getKey(), event.getValue()); + NodeSimpleVO nodeSimpleVO = convert(event.getKey()); + changeScriptNode(nodeSimpleVO, event.getValue()); + }); + //删除 script + scriptKey.addListener((EntryRemovedListener) event -> { + LOG.info("starting reload flow config... delete key={}", event.getKey()); + NodeSimpleVO nodeSimpleVO = convert(event.getKey()); + FlowBus.getNodeMap().remove(nodeSimpleVO.getNodeId()); + }); + } + } + + private void changeScriptNode(NodeSimpleVO nodeSimpleVO, String newValue) { + // 有语言类型 + if (StrUtil.isNotBlank(nodeSimpleVO.getLanguage())) { + LiteFlowNodeBuilder.createScriptNode() + .setId(nodeSimpleVO.getNodeId()) + .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.type)) + .setName(nodeSimpleVO.getName()) + .setScript(newValue) + .setLanguage(nodeSimpleVO.getLanguage()) + .build(); + } + // 没有语言类型 + else { + LiteFlowNodeBuilder.createScriptNode() + .setId(nodeSimpleVO.getNodeId()) + .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.type)) + .setName(nodeSimpleVO.getName()) + .setScript(newValue) + .build(); + } + } + public NodeSimpleVO convert(String str) { // 不需要去理解这串正则,就是一个匹配冒号的 // 一定得是a:b,或是a:b:c...这种完整类型的字符串的 From 942212f10b1d6cde60cf28fba6c62d9ef0e6a9f5 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sun, 2 Jul 2023 20:34:14 +0800 Subject: [PATCH 08/41] add interface --- .../parser/redis/RedisXmlELParser.java | 21 +- .../redis/util/RedisParserByPolling.java | 22 ++ .../redis/util/RedisParserByPubSub.java | 224 +++++++++++++++++ .../parser/redis/util/RedisParserHelper.java | 229 +----------------- 4 files changed, 273 insertions(+), 223 deletions(-) create mode 100644 liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java create mode 100644 liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPubSub.java diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java index 8cf02e38..cd5cd5cc 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java @@ -8,6 +8,8 @@ import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.core.FlowInitHook; import com.yomahub.liteflow.parser.el.ClassXmlFlowELParser; import com.yomahub.liteflow.parser.redis.exception.RedisException; +import com.yomahub.liteflow.parser.redis.util.RedisParserByPolling; +import com.yomahub.liteflow.parser.redis.util.RedisParserByPubSub; import com.yomahub.liteflow.parser.redis.util.RedisParserHelper; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import com.yomahub.liteflow.property.LiteflowConfig; @@ -27,7 +29,7 @@ public class RedisXmlELParser extends ClassXmlFlowELParser { public RedisXmlELParser() { LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - try{ + try { RedisParserVO redisParserVO = null; if (MapUtil.isNotEmpty((liteflowConfig.getRuleSourceExtDataMap()))) { redisParserVO = BeanUtil.toBean(liteflowConfig.getRuleSourceExtDataMap(), @@ -43,12 +45,19 @@ public class RedisXmlELParser extends ClassXmlFlowELParser { //检查配置文件 checkParserVO(redisParserVO); - redisParserHelper = new RedisParserHelper(redisParserVO); + //选择Pub/Sub机制 or 轮询机制 + if (StrUtil.equalsIgnoreCase("false", redisParserVO.isPolling())) { + redisParserHelper = new RedisParserByPubSub(redisParserVO); + } else { + //todo 实例化轮询机制 + redisParserHelper = new RedisParserByPolling(redisParserVO); + } + } - catch (RedisException redisException){ + catch (RedisException redisException) { throw redisException; } - catch (Exception e){ + catch (Exception e) { throw new RedisException(e.getMessage()); } } @@ -70,10 +79,10 @@ public class RedisXmlELParser extends ClassXmlFlowELParser { } private void checkParserVO(RedisParserVO redisParserVO) { - if (StrUtil.isEmpty(redisParserVO.getHost())){ + if (StrUtil.isEmpty(redisParserVO.getHost())) { throw new RedisException(StrFormatter.format(ERROR_MSG_PATTERN, "host")); } - if (StrUtil.isEmpty(redisParserVO.getPort())){ + if (StrUtil.isEmpty(redisParserVO.getPort())) { throw new RedisException(StrFormatter.format(ERROR_MSG_PATTERN, "port")); } } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java new file mode 100644 index 00000000..ef6637d6 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java @@ -0,0 +1,22 @@ +package com.yomahub.liteflow.parser.redis.util; + +import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; + +public class RedisParserByPolling implements RedisParserHelper{ + + private final RedisParserVO redisParserVO; + + public RedisParserByPolling(RedisParserVO redisParserVO) { + this.redisParserVO = redisParserVO; + } + + @Override + public String getContent() { + return null; + } + + @Override + public void listenRedis() { + + } +} diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPubSub.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPubSub.java new file mode 100644 index 00000000..cad9880e --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPubSub.java @@ -0,0 +1,224 @@ +package com.yomahub.liteflow.parser.redis.util; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.text.StrFormatter; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.ReUtil; +import cn.hutool.core.util.StrUtil; +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.redis.exception.RedisException; +import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; +import com.yomahub.liteflow.spi.holder.ContextAwareHolder; +import org.redisson.Redisson; +import org.redisson.api.RMapCache; +import org.redisson.api.RedissonClient; +import org.redisson.api.map.event.EntryCreatedListener; +import org.redisson.api.map.event.EntryRemovedListener; +import org.redisson.api.map.event.EntryUpdatedListener; +import org.redisson.config.Config; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +public class RedisParserByPubSub implements RedisParserHelper { + + private final RedisParserVO redisParserVO; + + private RedissonClient chainClient; + + private RedissonClient scriptClient; + + public RedisParserByPubSub(RedisParserVO redisParserVO) { + this.redisParserVO = redisParserVO; + + try { + try { + this.chainClient = ContextAwareHolder.loadContextAware().getBean("chainClient"); + this.scriptClient = ContextAwareHolder.loadContextAware().getBean("scriptClient"); + } + catch (Exception ignored) { + } + if (ObjectUtil.isNull(chainClient)) { + Config config = getRedissonConfig(redisParserVO, + Integer.parseInt(redisParserVO.getChainDataBase())); + this.chainClient = Redisson.create(config); + //如果有脚本数据 + if (StrUtil.isNotBlank(redisParserVO.getScriptDataBase())) { + config = getRedissonConfig(redisParserVO, + Integer.parseInt(redisParserVO.getScriptDataBase())); + this.scriptClient = Redisson.create(config); + } + } + } + catch (Exception e) { + throw new RedisException(e.getMessage()); + } + + } + + private Config getRedissonConfig(RedisParserVO redisParserVO, Integer dataBase) { + Config config = new Config(); + String redisAddress = StrFormatter.format(REDIS_URL_PATTERN, redisParserVO.getHost(), redisParserVO.getPort()); + if (StrUtil.isNotBlank(redisParserVO.getPassword())) { + config.useSingleServer().setAddress(redisAddress) + .setPassword(redisParserVO.getPassword()) + .setDatabase(dataBase); + } + else { + config.useSingleServer().setAddress(redisAddress) + .setDatabase(dataBase); + } + return config; + } + + @Override + public String getContent() { + try { + // 检查chainKey下有没有子节点 + RMapCache chainKey = chainClient.getMapCache(redisParserVO.getChainKey()); + Set chainNameSet = chainKey.keySet(); + if (CollectionUtil.isEmpty(chainNameSet)) { + throw new RedisException(StrUtil.format("There are no chains in key [{}]", + redisParserVO.getChainKey())); + } + // 获取chainKey下的所有子节点内容List + List chainItemContentList = new ArrayList<>(); + for (String chainName : chainNameSet) { + String chainData = chainKey.get(chainName); + if (StrUtil.isNotBlank(chainData)) { + chainItemContentList.add(StrUtil.format(CHAIN_XML_PATTERN, chainName, chainData)); + } + } + // 合并成所有chain的xml内容 + String chainAllContent = CollUtil.join(chainItemContentList, StrUtil.EMPTY); + + // 检查是否有脚本内容,如果有,进行脚本内容的获取 + String scriptAllContent = StrUtil.EMPTY; + if (hasScript()) { + RMapCache scriptKey = scriptClient.getMapCache(redisParserVO.getScriptKey()); + Set scriptKeySet = scriptKey.keySet(); + + List scriptItemContentList = new ArrayList<>(); + for (String scriptKeyValue : scriptKeySet) { + NodeSimpleVO nodeSimpleVO = convert(scriptKeyValue); + if (Objects.isNull(nodeSimpleVO)) { + throw new RedisException( + StrUtil.format("The name of the redis key is invalid:{}", scriptKeyValue)); + } + String scriptData = scriptKey.get(scriptKeyValue); + + // 有语言类型 + if (StrUtil.isNotBlank(nodeSimpleVO.getLanguage())) { + scriptItemContentList.add(StrUtil.format(NODE_ITEM_WITH_LANGUAGE_XML_PATTERN, + nodeSimpleVO.getNodeId(), nodeSimpleVO.getName(), nodeSimpleVO.getType(), + nodeSimpleVO.getLanguage(), scriptData)); + } + // 没有语言类型 + else { + scriptItemContentList.add(StrUtil.format(NODE_ITEM_XML_PATTERN, nodeSimpleVO.getNodeId(), + nodeSimpleVO.getName(), nodeSimpleVO.getType(), scriptData)); + } + + scriptAllContent = StrUtil.format(NODE_XML_PATTERN, + CollUtil.join(scriptItemContentList, StrUtil.EMPTY)); + } + } + + return StrUtil.format(XML_PATTERN, scriptAllContent, chainAllContent); + } + catch (Exception e) { + throw new RedisException(e.getMessage()); + } + } + + public boolean hasScript() { + // 没有scriptClient或没有配置scriptDataBase + if (Objects.isNull(scriptClient) || StrUtil.isNotBlank(redisParserVO.getScriptDataBase())) { + return false; + } + try { + // 存在这个节点,但是子节点不存在 + RMapCache scriptKey = scriptClient.getMapCache(redisParserVO.getScriptKey()); + Set scriptKeySet = scriptKey.keySet(); + return !CollUtil.isEmpty(scriptKeySet); + } + catch (Exception e) { + return false; + } + } + + /** + * 监听 redis key + */ + @Override + public void listenRedis() { + //监听 chain + RMapCache chainKey = chainClient.getMapCache(redisParserVO.getChainKey()); + //添加新 chain + chainKey.addListener((EntryCreatedListener) event -> { + LOG.info("starting reload flow config... create key={} value={},", event.getKey(), event.getValue()); + LiteFlowChainELBuilder.createChain().setChainId(event.getKey()).setEL(event.getValue()).build(); + }); + //修改 chain + chainKey.addListener((EntryUpdatedListener) event -> { + LOG.info("starting reload flow config... update path={} new value={},", event.getKey(), event.getValue()); + LiteFlowChainELBuilder.createChain().setChainId(event.getKey()).setEL(event.getValue()).build(); + }); + //删除 chain + chainKey.addListener((EntryRemovedListener) event -> { + LOG.info("starting reload flow config... delete key={}", event.getKey()); + FlowBus.removeChain(event.getKey()); + }); + + //监听 script + if (Objects.nonNull(scriptClient) && StrUtil.isNotBlank(redisParserVO.getScriptDataBase())) { + RMapCache scriptKey = scriptClient.getMapCache(redisParserVO.getScriptKey()); + //添加 script + scriptKey.addListener((EntryCreatedListener) event -> { + LOG.info("starting reload flow config... create key={} value={},", event.getKey(), event.getValue()); + NodeSimpleVO nodeSimpleVO = convert(event.getKey()); + changeScriptNode(nodeSimpleVO, event.getValue()); + }); + //修改 script + scriptKey.addListener((EntryUpdatedListener) event -> { + LOG.info("starting reload flow config... update path={} new value={},", event.getKey(), event.getValue()); + NodeSimpleVO nodeSimpleVO = convert(event.getKey()); + changeScriptNode(nodeSimpleVO, event.getValue()); + }); + //删除 script + scriptKey.addListener((EntryRemovedListener) event -> { + LOG.info("starting reload flow config... delete key={}", event.getKey()); + NodeSimpleVO nodeSimpleVO = convert(event.getKey()); + FlowBus.getNodeMap().remove(nodeSimpleVO.getNodeId()); + }); + } + } + + private void changeScriptNode(NodeSimpleVO nodeSimpleVO, String newValue) { + // 有语言类型 + if (StrUtil.isNotBlank(nodeSimpleVO.getLanguage())) { + LiteFlowNodeBuilder.createScriptNode() + .setId(nodeSimpleVO.getNodeId()) + .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType())) + .setName(nodeSimpleVO.getName()) + .setScript(newValue) + .setLanguage(nodeSimpleVO.getLanguage()) + .build(); + } + // 没有语言类型 + else { + LiteFlowNodeBuilder.createScriptNode() + .setId(nodeSimpleVO.getNodeId()) + .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType())) + .setName(nodeSimpleVO.getName()) + .setScript(newValue) + .build(); + } + } +} diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java index ee9fa67a..b784e0f8 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java @@ -1,238 +1,33 @@ package com.yomahub.liteflow.parser.redis.util; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.collection.CollectionUtil; -import cn.hutool.core.text.StrFormatter; -import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; -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.redis.exception.RedisException; -import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; -import com.yomahub.liteflow.spi.holder.ContextAwareHolder; -import org.redisson.Redisson; -import org.redisson.api.RMapCache; -import org.redisson.api.RedissonClient; -import org.redisson.api.map.event.EntryCreatedListener; -import org.redisson.api.map.event.EntryEvent; -import org.redisson.api.map.event.EntryRemovedListener; -import org.redisson.api.map.event.EntryUpdatedListener; -import org.redisson.config.Config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; import java.util.List; -import java.util.Objects; -import java.util.Set; -public class RedisParserHelper { +public interface RedisParserHelper { - private static final Logger LOG = LoggerFactory.getLogger(RedisParserHelper.class); + Logger LOG = LoggerFactory.getLogger(RedisParserByPubSub.class); + String REDIS_URL_PATTERN = "redis://{}:{}"; - private final RedisParserVO redisParserVO; + String CHAIN_XML_PATTERN = "{}"; - private final String REDIS_URL_PATTERN = "redis://{}:{}"; + String NODE_XML_PATTERN = "{}"; - private final String CHAIN_XML_PATTERN = "{}"; + String NODE_ITEM_XML_PATTERN = ""; - private final String NODE_XML_PATTERN = "{}"; + String NODE_ITEM_WITH_LANGUAGE_XML_PATTERN = ""; - private static final String NODE_ITEM_XML_PATTERN = ""; + String XML_PATTERN = "{}{}"; - private static final String NODE_ITEM_WITH_LANGUAGE_XML_PATTERN = ""; + String getContent(); - private static final String XML_PATTERN = "{}{}"; + void listenRedis(); - private RedissonClient chainClient; - - private RedissonClient scriptClient; - - public RedisParserHelper(RedisParserVO redisParserVO) { - this.redisParserVO = redisParserVO; - - try { - try { - this.chainClient = ContextAwareHolder.loadContextAware().getBean("chainClient"); - this.scriptClient = ContextAwareHolder.loadContextAware().getBean("scriptClient"); - } catch (Exception ignored) { - } - if (ObjectUtil.isNull(chainClient)) { - Config config = getRedissonConfig(redisParserVO, - Integer.parseInt(redisParserVO.getChainDataBase())); - this.chainClient = Redisson.create(config); - //如果有脚本数据 - if (StrUtil.isNotBlank(redisParserVO.getScriptDataBase())) { - config = getRedissonConfig(redisParserVO, - Integer.parseInt(redisParserVO.getScriptDataBase())); - this.scriptClient = Redisson.create(config); - } - } - } catch (Exception e) { - throw new RedisException(e.getMessage()); - } - - } - - private Config getRedissonConfig(RedisParserVO redisParserVO, Integer dataBase) { - Config config = new Config(); - String redisAddress = StrFormatter.format(REDIS_URL_PATTERN, redisParserVO.getHost(), redisParserVO.getPort()); - if (StrUtil.isNotBlank(redisParserVO.getPassword())) { - config.useSingleServer().setAddress(redisAddress) - .setPassword(redisParserVO.getPassword()) - .setDatabase(dataBase); - } else { - config.useSingleServer().setAddress(redisAddress) - .setDatabase(dataBase); - } - return config; - } - - public String getContent() { - try { - // 检查chainKey下有没有子节点 - RMapCache chainKey = chainClient.getMapCache(redisParserVO.getChainKey()); - Set chainNameSet = chainKey.keySet(); - if (CollectionUtil.isEmpty(chainNameSet)) { - throw new RedisException(StrUtil.format("There are no chains in key [{}]", - redisParserVO.getChainKey())); - } - // 获取chainKey下的所有子节点内容List - List chainItemContentList = new ArrayList<>(); - for (String chainName : chainNameSet) { - String chainData = chainKey.get(chainName); - if (StrUtil.isNotBlank(chainData)) { - chainItemContentList.add(StrUtil.format(CHAIN_XML_PATTERN, chainName, chainData)); - } - } - // 合并成所有chain的xml内容 - String chainAllContent = CollUtil.join(chainItemContentList, StrUtil.EMPTY); - - // 检查是否有脚本内容,如果有,进行脚本内容的获取 - String scriptAllContent = StrUtil.EMPTY; - if (hasScript()) { - RMapCache scriptKey = scriptClient.getMapCache(redisParserVO.getScriptKey()); - Set scriptKeySet = scriptKey.keySet(); - - List scriptItemContentList = new ArrayList<>(); - for (String scriptKeyValue : scriptKeySet) { - NodeSimpleVO nodeSimpleVO = convert(scriptKeyValue); - if (Objects.isNull(nodeSimpleVO)) { - throw new RedisException( - StrUtil.format("The name of the redis key is invalid:{}", scriptKeyValue)); - } - String scriptData = scriptKey.get(scriptKeyValue); - - // 有语言类型 - if (StrUtil.isNotBlank(nodeSimpleVO.getLanguage())) { - scriptItemContentList.add(StrUtil.format(NODE_ITEM_WITH_LANGUAGE_XML_PATTERN, - nodeSimpleVO.getNodeId(), nodeSimpleVO.getName(), nodeSimpleVO.getType(), - nodeSimpleVO.getLanguage(), scriptData)); - } - // 没有语言类型 - else { - scriptItemContentList.add(StrUtil.format(NODE_ITEM_XML_PATTERN, nodeSimpleVO.getNodeId(), - nodeSimpleVO.getName(), nodeSimpleVO.getType(), scriptData)); - } - - scriptAllContent = StrUtil.format(NODE_XML_PATTERN, - CollUtil.join(scriptItemContentList, StrUtil.EMPTY)); - } - } - - return StrUtil.format(XML_PATTERN, scriptAllContent, chainAllContent); - } catch (Exception e) { - throw new RedisException(e.getMessage()); - } - } - - public boolean hasScript() { - // 没有scriptClient或没有配置scriptDataBase - if (Objects.isNull(scriptClient) || StrUtil.isNotBlank(redisParserVO.getScriptDataBase())) { - return false; - } - try { - // 存在这个节点,但是子节点不存在 - RMapCache scriptKey = scriptClient.getMapCache(redisParserVO.getScriptKey()); - Set scriptKeySet = scriptKey.keySet(); - return !CollUtil.isEmpty(scriptKeySet); - } catch (Exception e) { - return false; - } - } - - /** - * 监听 redis key - */ - public void listenRedis() { - //监听 chain - RMapCache chainKey = chainClient.getMapCache(redisParserVO.getChainKey()); - //添加新 chain - chainKey.addListener((EntryCreatedListener) event -> { - LOG.info("starting reload flow config... create key={} value={},", event.getKey(), event.getValue()); - LiteFlowChainELBuilder.createChain().setChainId(event.getKey()).setEL(event.getValue()).build(); - }); - //修改 chain - chainKey.addListener((EntryUpdatedListener) event -> { - LOG.info("starting reload flow config... update path={} new value={},", event.getKey(), event.getValue()); - LiteFlowChainELBuilder.createChain().setChainId(event.getKey()).setEL(event.getValue()).build(); - }); - //删除 chain - chainKey.addListener((EntryRemovedListener) event -> { - LOG.info("starting reload flow config... delete key={}", event.getKey()); - FlowBus.removeChain(event.getKey()); - }); - - //监听 script - if (Objects.nonNull(scriptClient) && StrUtil.isNotBlank(redisParserVO.getScriptDataBase())) { - RMapCache scriptKey = scriptClient.getMapCache(redisParserVO.getScriptKey()); - //添加 script - scriptKey.addListener((EntryCreatedListener) event -> { - LOG.info("starting reload flow config... create key={} value={},", event.getKey(), event.getValue()); - NodeSimpleVO nodeSimpleVO = convert(event.getKey()); - changeScriptNode(nodeSimpleVO, event.getValue()); - }); - //修改 script - scriptKey.addListener((EntryUpdatedListener) event -> { - LOG.info("starting reload flow config... update path={} new value={},", event.getKey(), event.getValue()); - NodeSimpleVO nodeSimpleVO = convert(event.getKey()); - changeScriptNode(nodeSimpleVO, event.getValue()); - }); - //删除 script - scriptKey.addListener((EntryRemovedListener) event -> { - LOG.info("starting reload flow config... delete key={}", event.getKey()); - NodeSimpleVO nodeSimpleVO = convert(event.getKey()); - FlowBus.getNodeMap().remove(nodeSimpleVO.getNodeId()); - }); - } - } - - private void changeScriptNode(NodeSimpleVO nodeSimpleVO, String newValue) { - // 有语言类型 - if (StrUtil.isNotBlank(nodeSimpleVO.getLanguage())) { - LiteFlowNodeBuilder.createScriptNode() - .setId(nodeSimpleVO.getNodeId()) - .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.type)) - .setName(nodeSimpleVO.getName()) - .setScript(newValue) - .setLanguage(nodeSimpleVO.getLanguage()) - .build(); - } - // 没有语言类型 - else { - LiteFlowNodeBuilder.createScriptNode() - .setId(nodeSimpleVO.getNodeId()) - .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.type)) - .setName(nodeSimpleVO.getName()) - .setScript(newValue) - .build(); - } - } - - public NodeSimpleVO convert(String str) { + default NodeSimpleVO convert(String str) { // 不需要去理解这串正则,就是一个匹配冒号的 // 一定得是a:b,或是a:b:c...这种完整类型的字符串的 List matchItemList = ReUtil.findAllGroup0("(?<=[^:]:)[^:]+|[^:]+(?=:[^:])", str); @@ -257,7 +52,7 @@ public class RedisParserHelper { return nodeSimpleVO; } - private static class NodeSimpleVO { + class NodeSimpleVO { private String nodeId; From 77f259d98a25311e8ac06bcfa77a1e4d3d06bee9 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Tue, 4 Jul 2023 00:50:05 +0800 Subject: [PATCH 09/41] fix:bug --- .../liteflow/parser/redis/RedisXmlELParser.java | 9 ++++++++- .../parser/redis/exception/RedisException.java | 7 +++++++ .../parser/redis/util/RedisParserByPolling.java | 7 +++++++ .../parser/redis/util/RedisParserByPubSub.java | 10 +++++++++- .../parser/redis/util/RedisParserHelper.java | 13 ++++++++++++- .../liteflow/parser/redis/vo/RedisParserVO.java | 7 +++++++ 6 files changed, 50 insertions(+), 3 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java index cd5cd5cc..334832a0 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java @@ -18,13 +18,20 @@ import com.yomahub.liteflow.util.JsonUtil; import java.util.Objects; +/** + * Redis解析器实现,只支持EL形式的XML,不支持其他的形式 + * + * @author hxinyu + * @since 2.10.6 + */ + public class RedisXmlELParser extends ClassXmlFlowELParser { private final RedisParserHelper redisParserHelper; private static final String ERROR_COMMON_MSG = "ruleSourceExtData or map is empty"; - private static final String ERROR_MSG_PATTERN = "uleSourceExtData {} is blank"; + private static final String ERROR_MSG_PATTERN = "ruleSourceExtData {} is blank"; public RedisXmlELParser() { LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/exception/RedisException.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/exception/RedisException.java index 021dce8e..3882bfb9 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/exception/RedisException.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/exception/RedisException.java @@ -1,5 +1,12 @@ package com.yomahub.liteflow.parser.redis.exception; +/** + * Redis解析异常 + * + * @author hxinyu + * @since 2.10.6 + */ + public class RedisException extends RuntimeException{ private String message; diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java index ef6637d6..eae79424 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java @@ -2,6 +2,13 @@ package com.yomahub.liteflow.parser.redis.util; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; +/** + * Redis 轮询机制实现类 + * + * @author hxinyu + * @since 2.10.6 + */ + public class RedisParserByPolling implements RedisParserHelper{ private final RedisParserVO redisParserVO; diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPubSub.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPubSub.java index cad9880e..fb390d0b 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPubSub.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPubSub.java @@ -26,6 +26,14 @@ import java.util.List; import java.util.Objects; import java.util.Set; +/** + * Redis Pub/Sub机制实现类 + * Redisson客户端 RMapCache存储结构 + * + * @author hxinyu + * @since 2.10.6 + */ + public class RedisParserByPubSub implements RedisParserHelper { private final RedisParserVO redisParserVO; @@ -139,7 +147,7 @@ public class RedisParserByPubSub implements RedisParserHelper { public boolean hasScript() { // 没有scriptClient或没有配置scriptDataBase - if (Objects.isNull(scriptClient) || StrUtil.isNotBlank(redisParserVO.getScriptDataBase())) { + if (Objects.isNull(scriptClient) || StrUtil.isBlank(redisParserVO.getScriptDataBase())) { return false; } try { diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java index b784e0f8..9f6b0f64 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java @@ -3,14 +3,25 @@ package com.yomahub.liteflow.parser.redis.util; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; +import com.yomahub.liteflow.core.FlowExecutor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; +/** + * Redis 解析器通用接口 + * + * @author hxinyu + * @since 2.10.6 + */ + public interface RedisParserHelper { - Logger LOG = LoggerFactory.getLogger(RedisParserByPubSub.class); + Logger LOG = LoggerFactory.getLogger(RedisParserHelper.class); + + // LFLog LOG = LFLoggerManager.getLogger(FlowExecutor.class); + String REDIS_URL_PATTERN = "redis://{}:{}"; String CHAIN_XML_PATTERN = "{}"; diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java index d2a2d9d2..868ae510 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java @@ -1,5 +1,12 @@ package com.yomahub.liteflow.parser.redis.vo; +/** + * 用于解析RuleSourceExtData的vo类,用于Redis模式中 + * + * @author hxinyu + * @since 2.10.6 + */ + public class RedisParserVO { /*连接地址*/ From 4140e14047c1d8b74e2a9999fb0d8e27ecbc6c9d Mon Sep 17 00:00:00 2001 From: houxinyu Date: Thu, 6 Jul 2023 23:14:51 +0800 Subject: [PATCH 10/41] fix:param --- .../parser/redis/RedisXmlELParser.java | 8 +++--- ...ubSub.java => RedisParserBySubscribe.java} | 17 +++++------- .../parser/redis/util/RedisParserHelper.java | 1 - .../parser/redis/vo/RedisParserVO.java | 26 +++++++++---------- 4 files changed, 24 insertions(+), 28 deletions(-) rename liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/{RedisParserByPubSub.java => RedisParserBySubscribe.java} (93%) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java index 334832a0..ab3529fa 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java @@ -9,7 +9,7 @@ import com.yomahub.liteflow.core.FlowInitHook; import com.yomahub.liteflow.parser.el.ClassXmlFlowELParser; import com.yomahub.liteflow.parser.redis.exception.RedisException; import com.yomahub.liteflow.parser.redis.util.RedisParserByPolling; -import com.yomahub.liteflow.parser.redis.util.RedisParserByPubSub; +import com.yomahub.liteflow.parser.redis.util.RedisParserBySubscribe; import com.yomahub.liteflow.parser.redis.util.RedisParserHelper; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import com.yomahub.liteflow.property.LiteflowConfig; @@ -52,9 +52,9 @@ public class RedisXmlELParser extends ClassXmlFlowELParser { //检查配置文件 checkParserVO(redisParserVO); - //选择Pub/Sub机制 or 轮询机制 - if (StrUtil.equalsIgnoreCase("false", redisParserVO.isPolling())) { - redisParserHelper = new RedisParserByPubSub(redisParserVO); + //选择订阅机制 or 轮询机制 + if (StrUtil.equalsIgnoreCase("subscribe", redisParserVO.getMode())) { + redisParserHelper = new RedisParserBySubscribe(redisParserVO); } else { //todo 实例化轮询机制 redisParserHelper = new RedisParserByPolling(redisParserVO); diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPubSub.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java similarity index 93% rename from liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPubSub.java rename to liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java index fb390d0b..7c2fc733 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPubSub.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.text.StrFormatter; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.builder.LiteFlowNodeBuilder; import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; @@ -34,7 +33,7 @@ import java.util.Set; * @since 2.10.6 */ -public class RedisParserByPubSub implements RedisParserHelper { +public class RedisParserBySubscribe implements RedisParserHelper { private final RedisParserVO redisParserVO; @@ -42,7 +41,7 @@ public class RedisParserByPubSub implements RedisParserHelper { private RedissonClient scriptClient; - public RedisParserByPubSub(RedisParserVO redisParserVO) { + public RedisParserBySubscribe(RedisParserVO redisParserVO) { this.redisParserVO = redisParserVO; try { @@ -53,13 +52,11 @@ public class RedisParserByPubSub implements RedisParserHelper { catch (Exception ignored) { } if (ObjectUtil.isNull(chainClient)) { - Config config = getRedissonConfig(redisParserVO, - Integer.parseInt(redisParserVO.getChainDataBase())); + Config config = getRedissonConfig(redisParserVO, redisParserVO.getChainDataBase()); this.chainClient = Redisson.create(config); //如果有脚本数据 - if (StrUtil.isNotBlank(redisParserVO.getScriptDataBase())) { - config = getRedissonConfig(redisParserVO, - Integer.parseInt(redisParserVO.getScriptDataBase())); + if (Objects.isNull(redisParserVO.getScriptDataBase())) { + config = getRedissonConfig(redisParserVO, redisParserVO.getScriptDataBase()); this.scriptClient = Redisson.create(config); } } @@ -147,7 +144,7 @@ public class RedisParserByPubSub implements RedisParserHelper { public boolean hasScript() { // 没有scriptClient或没有配置scriptDataBase - if (Objects.isNull(scriptClient) || StrUtil.isBlank(redisParserVO.getScriptDataBase())) { + if (Objects.isNull(scriptClient) || Objects.isNull(redisParserVO.getScriptDataBase())) { return false; } try { @@ -185,7 +182,7 @@ public class RedisParserByPubSub implements RedisParserHelper { }); //监听 script - if (Objects.nonNull(scriptClient) && StrUtil.isNotBlank(redisParserVO.getScriptDataBase())) { + if (Objects.nonNull(scriptClient) && Objects.isNull(redisParserVO.getScriptDataBase())) { RMapCache scriptKey = scriptClient.getMapCache(redisParserVO.getScriptKey()); //添加 script scriptKey.addListener((EntryCreatedListener) event -> { diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java index 9f6b0f64..045e2644 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java @@ -3,7 +3,6 @@ package com.yomahub.liteflow.parser.redis.util; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; -import com.yomahub.liteflow.core.FlowExecutor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java index 868ae510..51e8024d 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java @@ -18,20 +18,20 @@ public class RedisParserVO { /*密码*/ private String password; - /*是否采用轮询机制 默认为轮询 否则选择pub/sub机制*/ - private String isPolling = "true"; + /*监听机制 轮询为poll 订阅为subscribe 默认为poll*/ + private String mode = "poll"; - /*轮询时间间隔(ms) 默认1分钟 若选择pub/sub机制可不配置*/ + /*轮询时间间隔(ms) 默认1分钟 若选择订阅机制可不配置*/ private String pollingInterval = "60000"; /*chain表配置的数据库号*/ - private String chainDataBase; + private Integer chainDataBase; /*chain配置的键名*/ private String chainKey; /*脚本表配置的数据库号 若没有脚本数据可不配置*/ - private String scriptDataBase; + private Integer scriptDataBase; /*脚本配置的键名 若没有脚本数据可不配置*/ private String scriptKey; @@ -60,12 +60,12 @@ public class RedisParserVO { this.password = password; } - public String isPolling() { - return isPolling; + public String getMode() { + return mode; } - public void setPolling(String polling) { - isPolling = polling; + public void setMode(String mode) { + this.mode = mode; } public String getPollingInterval() { @@ -76,11 +76,11 @@ public class RedisParserVO { this.pollingInterval = pollingInterval; } - public String getChainDataBase() { + public Integer getChainDataBase() { return chainDataBase; } - public void setChainDataBase(String chainDataBase) { + public void setChainDataBase(Integer chainDataBase) { this.chainDataBase = chainDataBase; } @@ -92,11 +92,11 @@ public class RedisParserVO { this.chainKey = chainKey; } - public String getScriptDataBase() { + public Integer getScriptDataBase() { return scriptDataBase; } - public void setScriptDataBase(String scriptDataBase) { + public void setScriptDataBase(Integer scriptDataBase) { this.scriptDataBase = scriptDataBase; } From fd03e7a029a24038364c2f552653914c6f1430ef Mon Sep 17 00:00:00 2001 From: houxinyu Date: Thu, 6 Jul 2023 23:55:09 +0800 Subject: [PATCH 11/41] fix:log --- .../liteflow/parser/redis/util/RedisParserHelper.java | 7 ++++--- pom.xml | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java index 045e2644..ca1c7364 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java @@ -3,6 +3,9 @@ package com.yomahub.liteflow.parser.redis.util; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.log.LFLog; +import com.yomahub.liteflow.log.LFLoggerManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -17,9 +20,7 @@ import java.util.List; public interface RedisParserHelper { - Logger LOG = LoggerFactory.getLogger(RedisParserHelper.class); - - // LFLog LOG = LFLoggerManager.getLogger(FlowExecutor.class); + LFLog LOG = LFLoggerManager.getLogger(FlowExecutor.class); String REDIS_URL_PATTERN = "redis://{}:{}"; diff --git a/pom.xml b/pom.xml index 03a4f8cb..de5b4983 100644 --- a/pom.xml +++ b/pom.xml @@ -74,7 +74,7 @@ 3.0.1 5.3.3 2.11.0 - 3.20.0 + 3.21.0 From 24304980c6c542f5d205958b67749a16b3937635 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Fri, 7 Jul 2023 23:57:20 +0800 Subject: [PATCH 12/41] add poll --- .../liteflow-rule-redis/pom.xml | 6 ++++ .../parser/redis/RedisXmlELParser.java | 1 - .../redis/util/RedisParserByPolling.java | 32 ++++++++++++++++++- .../redis/util/RedisParserBySubscribe.java | 13 ++++---- pom.xml | 1 + 5 files changed, 44 insertions(+), 9 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/pom.xml b/liteflow-rule-plugin/liteflow-rule-redis/pom.xml index 183bacb0..a1e05b65 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/pom.xml +++ b/liteflow-rule-plugin/liteflow-rule-redis/pom.xml @@ -26,6 +26,12 @@ redisson ${redisson.version} + + + redis.clients + jedis + ${jedis.version} + \ No newline at end of file diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java index ab3529fa..b6a0303c 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java @@ -56,7 +56,6 @@ public class RedisXmlELParser extends ClassXmlFlowELParser { if (StrUtil.equalsIgnoreCase("subscribe", redisParserVO.getMode())) { redisParserHelper = new RedisParserBySubscribe(redisParserVO); } else { - //todo 实例化轮询机制 redisParserHelper = new RedisParserByPolling(redisParserVO); } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java index eae79424..05c3495f 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java @@ -1,6 +1,10 @@ package com.yomahub.liteflow.parser.redis.util; +import cn.hutool.core.util.ObjectUtil; +import com.yomahub.liteflow.parser.redis.exception.RedisException; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; +import com.yomahub.liteflow.spi.holder.ContextAwareHolder; +import redis.clients.jedis.Jedis; /** * Redis 轮询机制实现类 @@ -13,8 +17,34 @@ public class RedisParserByPolling implements RedisParserHelper{ private final RedisParserVO redisParserVO; - public RedisParserByPolling(RedisParserVO redisParserVO) { + private Jedis chainClient; + + private Jedis scriptClient; + + public + RedisParserByPolling(RedisParserVO redisParserVO) { this.redisParserVO = redisParserVO; + + try{ + try{ + this.chainClient = ContextAwareHolder.loadContextAware().getBean("chainJClient"); + this.scriptClient = ContextAwareHolder.loadContextAware().getBean("scriptJClient"); + } + catch (Exception ignored) { + } + if (ObjectUtil.isNull(chainClient)) { + chainClient = new Jedis(redisParserVO.getHost(), Integer.parseInt(redisParserVO.getPort())); + chainClient.select(redisParserVO.getChainDataBase()); + //如果有脚本数据 + if (ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { + scriptClient = new Jedis(redisParserVO.getHost(), Integer.parseInt(redisParserVO.getPort())); + scriptClient.select(redisParserVO.getScriptDataBase()); + } + } + } + catch (Exception e) { + throw new RedisException(e.getMessage()); + } } @Override diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java index 7c2fc733..3e218852 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java @@ -22,7 +22,6 @@ import org.redisson.config.Config; import java.util.ArrayList; import java.util.List; -import java.util.Objects; import java.util.Set; /** @@ -46,8 +45,8 @@ public class RedisParserBySubscribe implements RedisParserHelper { try { try { - this.chainClient = ContextAwareHolder.loadContextAware().getBean("chainClient"); - this.scriptClient = ContextAwareHolder.loadContextAware().getBean("scriptClient"); + this.chainClient = ContextAwareHolder.loadContextAware().getBean("chainRClient"); + this.scriptClient = ContextAwareHolder.loadContextAware().getBean("scriptRClient"); } catch (Exception ignored) { } @@ -55,7 +54,7 @@ public class RedisParserBySubscribe implements RedisParserHelper { Config config = getRedissonConfig(redisParserVO, redisParserVO.getChainDataBase()); this.chainClient = Redisson.create(config); //如果有脚本数据 - if (Objects.isNull(redisParserVO.getScriptDataBase())) { + if (ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { config = getRedissonConfig(redisParserVO, redisParserVO.getScriptDataBase()); this.scriptClient = Redisson.create(config); } @@ -112,7 +111,7 @@ public class RedisParserBySubscribe implements RedisParserHelper { List scriptItemContentList = new ArrayList<>(); for (String scriptKeyValue : scriptKeySet) { NodeSimpleVO nodeSimpleVO = convert(scriptKeyValue); - if (Objects.isNull(nodeSimpleVO)) { + if (ObjectUtil.isNull(nodeSimpleVO)) { throw new RedisException( StrUtil.format("The name of the redis key is invalid:{}", scriptKeyValue)); } @@ -144,7 +143,7 @@ public class RedisParserBySubscribe implements RedisParserHelper { public boolean hasScript() { // 没有scriptClient或没有配置scriptDataBase - if (Objects.isNull(scriptClient) || Objects.isNull(redisParserVO.getScriptDataBase())) { + if (ObjectUtil.isNull(scriptClient) || ObjectUtil.isNull(redisParserVO.getScriptDataBase())) { return false; } try { @@ -182,7 +181,7 @@ public class RedisParserBySubscribe implements RedisParserHelper { }); //监听 script - if (Objects.nonNull(scriptClient) && Objects.isNull(redisParserVO.getScriptDataBase())) { + if (ObjectUtil.isNotNull(scriptClient) && ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { RMapCache scriptKey = scriptClient.getMapCache(redisParserVO.getScriptKey()); //添加 script scriptKey.addListener((EntryCreatedListener) event -> { diff --git a/pom.xml b/pom.xml index de5b4983..5edcba19 100644 --- a/pom.xml +++ b/pom.xml @@ -75,6 +75,7 @@ 5.3.3 2.11.0 3.21.0 + 4.3.1 From 0397ab6af920a606affbcd4e322b010d3300918f Mon Sep 17 00:00:00 2001 From: houxinyu Date: Fri, 7 Jul 2023 23:59:37 +0800 Subject: [PATCH 13/41] fix:lint --- .../liteflow/parser/redis/util/RedisParserByPolling.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java index 05c3495f..ed459a60 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java @@ -21,8 +21,7 @@ public class RedisParserByPolling implements RedisParserHelper{ private Jedis scriptClient; - public - RedisParserByPolling(RedisParserVO redisParserVO) { + public RedisParserByPolling(RedisParserVO redisParserVO) { this.redisParserVO = redisParserVO; try{ From 2bf8f10e3364b3292b041ea14073448ad4a7deb6 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sat, 8 Jul 2023 12:12:03 +0800 Subject: [PATCH 14/41] add poll getcontent() --- .../parser/redis/RedisXmlELParser.java | 11 ++- .../redis/util/RedisParserByPolling.java | 87 ++++++++++++++++++- .../redis/util/RedisParserBySubscribe.java | 17 ++-- 3 files changed, 104 insertions(+), 11 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java index b6a0303c..daaba861 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.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.text.StrFormatter; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.core.FlowInitHook; import com.yomahub.liteflow.parser.el.ClassXmlFlowELParser; @@ -85,11 +86,17 @@ public class RedisXmlELParser extends ClassXmlFlowELParser { } private void checkParserVO(RedisParserVO redisParserVO) { - if (StrUtil.isEmpty(redisParserVO.getHost())) { + if (StrUtil.isBlank(redisParserVO.getHost())) { throw new RedisException(StrFormatter.format(ERROR_MSG_PATTERN, "host")); } - if (StrUtil.isEmpty(redisParserVO.getPort())) { + if (StrUtil.isBlank(redisParserVO.getPort())) { throw new RedisException(StrFormatter.format(ERROR_MSG_PATTERN, "port")); } + if (ObjectUtil.isNull(redisParserVO.getChainDataBase())) { + throw new RedisException(StrFormatter.format(ERROR_MSG_PATTERN, "chainDataBase")); + } + if (StrUtil.isBlank(redisParserVO.getChainKey())) { + throw new RedisException(StrFormatter.format(ERROR_MSG_PATTERN, "chainKey")); + } } } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java index ed459a60..495f7b05 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java @@ -1,11 +1,18 @@ package com.yomahub.liteflow.parser.redis.util; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.parser.redis.exception.RedisException; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import com.yomahub.liteflow.spi.holder.ContextAwareHolder; import redis.clients.jedis.Jedis; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + /** * Redis 轮询机制实现类 * @@ -33,10 +40,16 @@ public class RedisParserByPolling implements RedisParserHelper{ } if (ObjectUtil.isNull(chainClient)) { chainClient = new Jedis(redisParserVO.getHost(), Integer.parseInt(redisParserVO.getPort())); + if (StrUtil.isNotBlank(redisParserVO.getPassword())) { + chainClient.auth(redisParserVO.getPassword()); + } chainClient.select(redisParserVO.getChainDataBase()); //如果有脚本数据 if (ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { scriptClient = new Jedis(redisParserVO.getHost(), Integer.parseInt(redisParserVO.getPort())); + if (StrUtil.isNotBlank(redisParserVO.getPassword())) { + scriptClient.auth(redisParserVO.getPassword()); + } scriptClient.select(redisParserVO.getScriptDataBase()); } } @@ -48,7 +61,79 @@ public class RedisParserByPolling implements RedisParserHelper{ @Override public String getContent() { - return null; + try { + // 检查chainKey下有没有子节点 + String chainKey = redisParserVO.getChainKey(); + Set chainNameSet = chainClient.hkeys(chainKey); + if (CollectionUtil.isEmpty(chainNameSet)) { + throw new RedisException(StrUtil.format("There are no chains in key [{}]", chainKey)); + } + // 获取chainKey下的所有子节点内容List + List chainItemContentList = new ArrayList<>(); + for (String chainName : chainNameSet) { + String chainData = chainClient.hget(chainKey, chainName); + if (StrUtil.isNotBlank(chainData)) { + chainItemContentList.add(StrUtil.format(CHAIN_XML_PATTERN, chainName, chainData)); + } + } + // 合并成所有chain的xml内容 + String chainAllContent = CollUtil.join(chainItemContentList, StrUtil.EMPTY); + + // 检查是否有脚本内容,如果有,进行脚本内容的获取 + String scriptAllContent = StrUtil.EMPTY; + if (hasScript()) { + String scriptKey = redisParserVO.getScriptKey(); + Set scriptFieldSet = scriptClient.hkeys(scriptKey); + + List scriptItemContentList = new ArrayList<>(); + for (String scriptFieldValue : scriptFieldSet) { + NodeSimpleVO nodeSimpleVO = convert(scriptFieldValue); + if (ObjectUtil.isNull(nodeSimpleVO)) { + throw new RedisException( + StrUtil.format("The name of the redis field [{}] in scriptKey [{}] is invalid", + scriptFieldValue, scriptKey)); + } + String scriptData = scriptClient.hget(scriptKey, scriptFieldValue); + + // 有语言类型 + if (StrUtil.isNotBlank(nodeSimpleVO.getLanguage())) { + scriptItemContentList.add(StrUtil.format(NODE_ITEM_WITH_LANGUAGE_XML_PATTERN, + nodeSimpleVO.getNodeId(), nodeSimpleVO.getName(), nodeSimpleVO.getType(), + nodeSimpleVO.getLanguage(), scriptData)); + } + // 没有语言类型 + else { + scriptItemContentList.add(StrUtil.format(NODE_ITEM_XML_PATTERN, nodeSimpleVO.getNodeId(), + nodeSimpleVO.getName(), nodeSimpleVO.getType(), scriptData)); + } + } + + scriptAllContent = StrUtil.format(NODE_XML_PATTERN, + CollUtil.join(scriptItemContentList, StrUtil.EMPTY)); + } + + return StrUtil.format(XML_PATTERN, scriptAllContent, chainAllContent); + } + catch (Exception e) { + throw new RedisException(e.getMessage()); + } + } + + public boolean hasScript() { + if (ObjectUtil.isNull(scriptClient) || ObjectUtil.isNull(redisParserVO.getScriptDataBase())) { + return false; + } + try{ + String scriptKey = redisParserVO.getScriptKey(); + if (StrUtil.isBlank(scriptKey)) { + return false; + } + Set scriptKeySet = scriptClient.hkeys(scriptKey); + return !CollUtil.isEmpty(scriptKeySet); + } + catch (Exception e) { + return false; + } } @Override diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java index 3e218852..d144c9b5 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java @@ -106,16 +106,17 @@ public class RedisParserBySubscribe implements RedisParserHelper { String scriptAllContent = StrUtil.EMPTY; if (hasScript()) { RMapCache scriptKey = scriptClient.getMapCache(redisParserVO.getScriptKey()); - Set scriptKeySet = scriptKey.keySet(); + Set scriptFieldSet = scriptKey.keySet(); List scriptItemContentList = new ArrayList<>(); - for (String scriptKeyValue : scriptKeySet) { - NodeSimpleVO nodeSimpleVO = convert(scriptKeyValue); + for (String scriptFieldValue : scriptFieldSet) { + NodeSimpleVO nodeSimpleVO = convert(scriptFieldValue); if (ObjectUtil.isNull(nodeSimpleVO)) { throw new RedisException( - StrUtil.format("The name of the redis key is invalid:{}", scriptKeyValue)); + StrUtil.format("The name of the redis field [{}] in scriptKey [{}] is invalid", + scriptFieldValue, scriptKey)); } - String scriptData = scriptKey.get(scriptKeyValue); + String scriptData = scriptKey.get(scriptFieldValue); // 有语言类型 if (StrUtil.isNotBlank(nodeSimpleVO.getLanguage())) { @@ -128,10 +129,10 @@ public class RedisParserBySubscribe implements RedisParserHelper { scriptItemContentList.add(StrUtil.format(NODE_ITEM_XML_PATTERN, nodeSimpleVO.getNodeId(), nodeSimpleVO.getName(), nodeSimpleVO.getType(), scriptData)); } - - scriptAllContent = StrUtil.format(NODE_XML_PATTERN, - CollUtil.join(scriptItemContentList, StrUtil.EMPTY)); } + + scriptAllContent = StrUtil.format(NODE_XML_PATTERN, + CollUtil.join(scriptItemContentList, StrUtil.EMPTY)); } return StrUtil.format(XML_PATTERN, scriptAllContent, chainAllContent); From f4c6eab0ccb96834a0b63e17fe7fef1438a7f0e7 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sun, 9 Jul 2023 00:22:02 +0800 Subject: [PATCH 15/41] add poll task of chain --- .../liteflow-rule-redis/pom.xml | 6 + .../redis/util/RedisParserByPolling.java | 148 +++++++++++++++--- .../redis/util/RedisParserBySubscribe.java | 2 +- .../parser/redis/vo/RedisParserVO.java | 4 +- pom.xml | 1 + 5 files changed, 138 insertions(+), 23 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/pom.xml b/liteflow-rule-plugin/liteflow-rule-redis/pom.xml index a1e05b65..4ee4a1c7 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/pom.xml +++ b/liteflow-rule-plugin/liteflow-rule-redis/pom.xml @@ -32,6 +32,12 @@ jedis ${jedis.version} + + + cn.hutool + hutool-crypto + ${hutool-crypto.version} + \ No newline at end of file diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java index 495f7b05..b4984437 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java @@ -4,14 +4,18 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.digest.DigestUtil; +import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; +import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.parser.redis.exception.RedisException; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import com.yomahub.liteflow.spi.holder.ContextAwareHolder; import redis.clients.jedis.Jedis; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; +import java.util.*; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; /** * Redis 轮询机制实现类 @@ -24,33 +28,59 @@ public class RedisParserByPolling implements RedisParserHelper{ private final RedisParserVO redisParserVO; - private Jedis chainClient; + private Jedis chainJedis; - private Jedis scriptClient; + private Jedis scriptJedis; + + //chainKey中chain总数 + private Integer chainFieldNum = 0; + + //scriptKey中script总数 + private Integer scriptFieldNum = 0; + + //chainKey中value的SHA1加密值 用于轮询时确定value是否变化 + private Map chainSHAMap = new HashMap<>(); + + //scriptKey中value的SHA1加密值 用于轮询时确定value是否变化 + private Map scriptSHAMap = new HashMap<>(); + + //计算hash中field数量的lua脚本 + private String luaOfKey = "local keys = redis.call(\"hkeys\", KEYS[1]);\n" + + "return #keys;\n"; + + //计算hash中value的SHA值的lua脚本 + private String luaOfValue = "local key = KEYS[1];\n" + + "local field = KEYS[2];\n" + + "local value, err = redis.call(\"hget\", key, field);\n" + + "if value == false or value == nil then\n" + + " return \"nil\";\n" + + "end\n" + + "local sha1 = redis.sha1hex(value);\n" + + "return sha1;"; public RedisParserByPolling(RedisParserVO redisParserVO) { this.redisParserVO = redisParserVO; try{ try{ - this.chainClient = ContextAwareHolder.loadContextAware().getBean("chainJClient"); - this.scriptClient = ContextAwareHolder.loadContextAware().getBean("scriptJClient"); + this.chainJedis = ContextAwareHolder.loadContextAware().getBean("chainJClient"); + this.scriptJedis = ContextAwareHolder.loadContextAware().getBean("scriptJClient"); } catch (Exception ignored) { } - if (ObjectUtil.isNull(chainClient)) { - chainClient = new Jedis(redisParserVO.getHost(), Integer.parseInt(redisParserVO.getPort())); + if (ObjectUtil.isNull(chainJedis)) { + chainJedis = new Jedis(redisParserVO.getHost(), Integer.parseInt(redisParserVO.getPort())); if (StrUtil.isNotBlank(redisParserVO.getPassword())) { - chainClient.auth(redisParserVO.getPassword()); + chainJedis.auth(redisParserVO.getPassword()); } - chainClient.select(redisParserVO.getChainDataBase()); + chainJedis.select(redisParserVO.getChainDataBase()); //如果有脚本数据 if (ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { - scriptClient = new Jedis(redisParserVO.getHost(), Integer.parseInt(redisParserVO.getPort())); + scriptJedis = new Jedis(redisParserVO.getHost(), Integer.parseInt(redisParserVO.getPort())); if (StrUtil.isNotBlank(redisParserVO.getPassword())) { - scriptClient.auth(redisParserVO.getPassword()); + scriptJedis.auth(redisParserVO.getPassword()); } - scriptClient.select(redisParserVO.getScriptDataBase()); + scriptJedis.select(redisParserVO.getScriptDataBase()); } } } @@ -64,17 +94,22 @@ public class RedisParserByPolling implements RedisParserHelper{ try { // 检查chainKey下有没有子节点 String chainKey = redisParserVO.getChainKey(); - Set chainNameSet = chainClient.hkeys(chainKey); + Set chainNameSet = chainJedis.hkeys(chainKey); if (CollectionUtil.isEmpty(chainNameSet)) { throw new RedisException(StrUtil.format("There are no chains in key [{}]", chainKey)); } + chainFieldNum = chainNameSet.size(); // 获取chainKey下的所有子节点内容List List chainItemContentList = new ArrayList<>(); for (String chainName : chainNameSet) { - String chainData = chainClient.hget(chainKey, chainName); + String chainData = chainJedis.hget(chainKey, chainName); if (StrUtil.isNotBlank(chainData)) { chainItemContentList.add(StrUtil.format(CHAIN_XML_PATTERN, chainName, chainData)); } + + //计算该chainData的SHA值 + String chainSHA = DigestUtil.sha1Hex(chainData); + chainSHAMap.put(chainName, chainSHA); } // 合并成所有chain的xml内容 String chainAllContent = CollUtil.join(chainItemContentList, StrUtil.EMPTY); @@ -83,7 +118,8 @@ public class RedisParserByPolling implements RedisParserHelper{ String scriptAllContent = StrUtil.EMPTY; if (hasScript()) { String scriptKey = redisParserVO.getScriptKey(); - Set scriptFieldSet = scriptClient.hkeys(scriptKey); + Set scriptFieldSet = scriptJedis.hkeys(scriptKey); + scriptFieldNum = scriptFieldSet.size(); List scriptItemContentList = new ArrayList<>(); for (String scriptFieldValue : scriptFieldSet) { @@ -93,7 +129,7 @@ public class RedisParserByPolling implements RedisParserHelper{ StrUtil.format("The name of the redis field [{}] in scriptKey [{}] is invalid", scriptFieldValue, scriptKey)); } - String scriptData = scriptClient.hget(scriptKey, scriptFieldValue); + String scriptData = scriptJedis.hget(scriptKey, scriptFieldValue); // 有语言类型 if (StrUtil.isNotBlank(nodeSimpleVO.getLanguage())) { @@ -106,6 +142,10 @@ public class RedisParserByPolling implements RedisParserHelper{ scriptItemContentList.add(StrUtil.format(NODE_ITEM_XML_PATTERN, nodeSimpleVO.getNodeId(), nodeSimpleVO.getName(), nodeSimpleVO.getType(), scriptData)); } + + //计算scriptData的SHA值 + String scriptSHA = DigestUtil.sha1Hex(scriptData); + scriptSHAMap.put(scriptFieldValue, scriptSHA); } scriptAllContent = StrUtil.format(NODE_XML_PATTERN, @@ -120,7 +160,7 @@ public class RedisParserByPolling implements RedisParserHelper{ } public boolean hasScript() { - if (ObjectUtil.isNull(scriptClient) || ObjectUtil.isNull(redisParserVO.getScriptDataBase())) { + if (ObjectUtil.isNull(scriptJedis) || ObjectUtil.isNull(redisParserVO.getScriptDataBase())) { return false; } try{ @@ -128,7 +168,7 @@ public class RedisParserByPolling implements RedisParserHelper{ if (StrUtil.isBlank(scriptKey)) { return false; } - Set scriptKeySet = scriptClient.hkeys(scriptKey); + Set scriptKeySet = scriptJedis.hkeys(scriptKey); return !CollUtil.isEmpty(scriptKeySet); } catch (Exception e) { @@ -138,6 +178,74 @@ public class RedisParserByPolling implements RedisParserHelper{ @Override public void listenRedis() { + //将lua脚本添加到chainJedis脚本缓存 + String keyLuaOfChain = chainJedis.scriptLoad(luaOfKey); + String valueLuaOfChain = chainJedis.scriptLoad(luaOfValue); + //定时任务线程池 + ScheduledExecutorService pool = Executors.newScheduledThreadPool(10); + //轮询chain内容的定时任务 + pool.scheduleAtFixedRate(pollChainTask(keyLuaOfChain, valueLuaOfChain), + 60, Long.valueOf(redisParserVO.getPollingInterval()), TimeUnit.SECONDS); + } + + + /** + * 用于轮询chain的定时任务 + */ + private Runnable pollChainTask(String keyLua, String valueLua) { + Runnable r = new Runnable() { + @Override + public void run() { + String chainKey = redisParserVO.getChainKey(); + //先判断chainKey中chain数量有无增长 + String keyNum = chainJedis.evalsha(keyLua, 1, chainKey).toString(); + if (Integer.parseInt(keyNum) > chainFieldNum) { + //有新增加的chain,重新从redis中拉取chainId集合, 对比出新增的chain + Set newChainSet = chainJedis.hkeys(chainKey); + Set oldChainSet = chainSHAMap.keySet(); + //求出差集,即新增的chain + Set newAdd = new HashSet<>(); + newAdd.addAll(newChainSet); + newAdd.removeAll(oldChainSet); + for (String newChainName : newAdd) { + String chainData = chainJedis.hget(chainKey, newChainName); + LiteFlowChainELBuilder.createChain().setChainId(newChainName).setEL(chainData).build(); + LOG.info("starting poll flow config... update key={} new value={},", newChainName, chainData); + + //修改SHAMap + chainSHAMap.put(newChainName, DigestUtil.sha1Hex(chainData)); + } + //修改chainFieldNum + chainFieldNum = newChainSet.size(); + } + + //遍历Map,判断各个chain的值有无变化 + for(Map.Entry entry: chainSHAMap.entrySet()) { + String chainName = entry.getKey(); + String oldSHA = entry.getValue(); + String newSHA = chainJedis.evalsha(valueLua, 2, chainKey, chainName).toString(); + if (StrUtil.equals(newSHA, "nil")) { + //新SHA值为nil, 即未获取到该chain,表示该chain已被删除 + FlowBus.removeChain(chainName); + LOG.info("starting reload flow config... delete key={}", chainName); + + //修改SHAMap + chainSHAMap.remove(chainName); + } + else if (!StrUtil.equals(newSHA, oldSHA)) { + //SHA值发生变化 表示该chain的值已被修改 重新拉取变化的chain + String chainData = chainJedis.hget(chainKey, chainName); + LiteFlowChainELBuilder.createChain().setChainId(chainName).setEL(chainData).build(); + LOG.info("starting poll flow config... update key={} new value={},", chainName, chainData); + + //修改SHAMap + chainSHAMap.put(chainName, newSHA); + } + //SHA值无变化 表示该chain未改变 + } + } + }; + return r; } } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java index d144c9b5..934c5034 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java @@ -172,7 +172,7 @@ public class RedisParserBySubscribe implements RedisParserHelper { }); //修改 chain chainKey.addListener((EntryUpdatedListener) event -> { - LOG.info("starting reload flow config... update path={} new value={},", event.getKey(), event.getValue()); + LOG.info("starting reload flow config... update key={} new value={},", event.getKey(), event.getValue()); LiteFlowChainELBuilder.createChain().setChainId(event.getKey()).setEL(event.getValue()).build(); }); //删除 chain diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java index 51e8024d..45d12a4b 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java @@ -21,8 +21,8 @@ public class RedisParserVO { /*监听机制 轮询为poll 订阅为subscribe 默认为poll*/ private String mode = "poll"; - /*轮询时间间隔(ms) 默认1分钟 若选择订阅机制可不配置*/ - private String pollingInterval = "60000"; + /*轮询时间间隔(s) 默认1分钟 若选择订阅机制可不配置*/ + private String pollingInterval = "60"; /*chain表配置的数据库号*/ private Integer chainDataBase; diff --git a/pom.xml b/pom.xml index 5edcba19..306c242e 100644 --- a/pom.xml +++ b/pom.xml @@ -76,6 +76,7 @@ 2.11.0 3.21.0 4.3.1 + 5.8.18 From ed3b6354b449971acaac3372eece050d8bda0ec5 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sun, 9 Jul 2023 00:28:49 +0800 Subject: [PATCH 16/41] add data --- .../liteflow/parser/redis/util/RedisParserByPolling.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java index b4984437..5cdf59b9 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java @@ -187,6 +187,13 @@ public class RedisParserByPolling implements RedisParserHelper{ //轮询chain内容的定时任务 pool.scheduleAtFixedRate(pollChainTask(keyLuaOfChain, valueLuaOfChain), 60, Long.valueOf(redisParserVO.getPollingInterval()), TimeUnit.SECONDS); + + //如果有脚本内容 + if (ObjectUtil.isNotNull(scriptJedis) && ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { + String keyLuaOfScript = scriptJedis.scriptLoad(luaOfKey); + String valueLuaOfScript = scriptJedis.scriptLoad(luaOfValue); + } + } From ae7896569c433a879fe7008b02b4ab10f79a5278 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sun, 9 Jul 2023 16:51:42 +0800 Subject: [PATCH 17/41] fix:bug --- .../parser/redis/RedisXmlELParser.java | 2 +- .../redis/util/RedisParserByPolling.java | 74 ++++++++++++------- .../redis/util/RedisParserBySubscribe.java | 12 +-- .../parser/redis/vo/RedisParserVO.java | 6 +- 4 files changed, 60 insertions(+), 34 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java index daaba861..23961a50 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java @@ -89,7 +89,7 @@ public class RedisXmlELParser extends ClassXmlFlowELParser { if (StrUtil.isBlank(redisParserVO.getHost())) { throw new RedisException(StrFormatter.format(ERROR_MSG_PATTERN, "host")); } - if (StrUtil.isBlank(redisParserVO.getPort())) { + if (ObjectUtil.isNull(redisParserVO.getPort())) { throw new RedisException(StrFormatter.format(ERROR_MSG_PATTERN, "port")); } if (ObjectUtil.isNull(redisParserVO.getChainDataBase())) { diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java index 5cdf59b9..3eb48e0c 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java @@ -63,20 +63,21 @@ public class RedisParserByPolling implements RedisParserHelper{ try{ try{ - this.chainJedis = ContextAwareHolder.loadContextAware().getBean("chainJClient"); - this.scriptJedis = ContextAwareHolder.loadContextAware().getBean("scriptJClient"); + this.chainJedis = ContextAwareHolder.loadContextAware().getBean("chainJedis"); + this.scriptJedis = ContextAwareHolder.loadContextAware().getBean("scriptJedis"); } catch (Exception ignored) { } if (ObjectUtil.isNull(chainJedis)) { - chainJedis = new Jedis(redisParserVO.getHost(), Integer.parseInt(redisParserVO.getPort())); + chainJedis = new Jedis(redisParserVO.getHost(), redisParserVO.getPort()); + //如果配置了密码 if (StrUtil.isNotBlank(redisParserVO.getPassword())) { chainJedis.auth(redisParserVO.getPassword()); } chainJedis.select(redisParserVO.getChainDataBase()); //如果有脚本数据 if (ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { - scriptJedis = new Jedis(redisParserVO.getHost(), Integer.parseInt(redisParserVO.getPort())); + scriptJedis = new Jedis(redisParserVO.getHost(), redisParserVO.getPort()); if (StrUtil.isNotBlank(redisParserVO.getPassword())) { scriptJedis.auth(redisParserVO.getPassword()); } @@ -176,6 +177,9 @@ public class RedisParserByPolling implements RedisParserHelper{ } } + /** + * 定时轮询拉取Redis中变化的数据 + */ @Override public void listenRedis() { //将lua脚本添加到chainJedis脚本缓存 @@ -188,8 +192,10 @@ public class RedisParserByPolling implements RedisParserHelper{ pool.scheduleAtFixedRate(pollChainTask(keyLuaOfChain, valueLuaOfChain), 60, Long.valueOf(redisParserVO.getPollingInterval()), TimeUnit.SECONDS); - //如果有脚本内容 - if (ObjectUtil.isNotNull(scriptJedis) && ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { + //如果有脚本 + if (ObjectUtil.isNotNull(scriptJedis) && ObjectUtil.isNotNull(redisParserVO.getScriptDataBase()) + && StrUtil.isNotBlank(redisParserVO.getScriptKey())) { + //将lua脚本添加到scriptJedis脚本缓存 String keyLuaOfScript = scriptJedis.scriptLoad(luaOfKey); String valueLuaOfScript = scriptJedis.scriptLoad(luaOfValue); } @@ -199,6 +205,8 @@ public class RedisParserByPolling implements RedisParserHelper{ /** * 用于轮询chain的定时任务 + * 首先根据hash中field数量的变化拉取新增的chain + * 再根据hash中value的SHA值修改变化的和被删除的chain */ private Runnable pollChainTask(String keyLua, String valueLua) { Runnable r = new Runnable() { @@ -207,6 +215,8 @@ public class RedisParserByPolling implements RedisParserHelper{ String chainKey = redisParserVO.getChainKey(); //先判断chainKey中chain数量有无增长 String keyNum = chainJedis.evalsha(keyLua, 1, chainKey).toString(); + //修改chainFieldNum为最新chain数量 + chainFieldNum = Integer.parseInt(keyNum); if (Integer.parseInt(keyNum) > chainFieldNum) { //有新增加的chain,重新从redis中拉取chainId集合, 对比出新增的chain Set newChainSet = chainJedis.hkeys(chainKey); @@ -215,41 +225,55 @@ public class RedisParserByPolling implements RedisParserHelper{ Set newAdd = new HashSet<>(); newAdd.addAll(newChainSet); newAdd.removeAll(oldChainSet); - for (String newChainName : newAdd) { - String chainData = chainJedis.hget(chainKey, newChainName); - LiteFlowChainELBuilder.createChain().setChainId(newChainName).setEL(chainData).build(); - LOG.info("starting poll flow config... update key={} new value={},", newChainName, chainData); + for (String newChainId : newAdd) { + String chainData = chainJedis.hget(chainKey, newChainId); + LiteFlowChainELBuilder.createChain().setChainId(newChainId).setEL(chainData).build(); + LOG.info("starting poll flow config... update key={} new value={},", newChainId, chainData); //修改SHAMap - chainSHAMap.put(newChainName, DigestUtil.sha1Hex(chainData)); + chainSHAMap.put(newChainId, DigestUtil.sha1Hex(chainData)); } - //修改chainFieldNum - chainFieldNum = newChainSet.size(); } //遍历Map,判断各个chain的值有无变化 for(Map.Entry entry: chainSHAMap.entrySet()) { - String chainName = entry.getKey(); + String chainId = entry.getKey(); String oldSHA = entry.getValue(); - String newSHA = chainJedis.evalsha(valueLua, 2, chainKey, chainName).toString(); + String newSHA = chainJedis.evalsha(valueLua, 2, chainKey, chainId).toString(); if (StrUtil.equals(newSHA, "nil")) { - //新SHA值为nil, 即未获取到该chain,表示该chain已被删除 - FlowBus.removeChain(chainName); - LOG.info("starting reload flow config... delete key={}", chainName); + //新SHA值为nil, 即未获取到该chain,表示该chain已被删除 + FlowBus.removeChain(chainId); + LOG.info("starting reload flow config... delete key={}", chainId); //修改SHAMap - chainSHAMap.remove(chainName); + chainSHAMap.remove(chainId); } else if (!StrUtil.equals(newSHA, oldSHA)) { - //SHA值发生变化 表示该chain的值已被修改 重新拉取变化的chain - String chainData = chainJedis.hget(chainKey, chainName); - LiteFlowChainELBuilder.createChain().setChainId(chainName).setEL(chainData).build(); - LOG.info("starting poll flow config... update key={} new value={},", chainName, chainData); + //SHA值发生变化,表示该chain的值已被修改,重新拉取变化的chain + String chainData = chainJedis.hget(chainKey, chainId); + LiteFlowChainELBuilder.createChain().setChainId(chainId).setEL(chainData).build(); + LOG.info("starting poll flow config... update key={} new value={},", chainId, chainData); //修改SHAMap - chainSHAMap.put(chainName, newSHA); + chainSHAMap.put(chainId, newSHA); + } + //SHA值无变化,表示该chain未改变 + } + + if (chainFieldNum > chainSHAMap.size()) { + //如果封装的SHAMap数量比新的chain总数少, 说明有修改了chainId的情况 + //因为遍历到旧的id时会取到nil,SHAMap会把原来的chainId删掉,但没有机会添加新的chainId + //在此处重新拉取所有chainId集合,补充添加新chainId + Set newChainSet = chainJedis.hkeys(chainKey); + for (String chainId : newChainSet) { + if (chainSHAMap.get(chainId) == null) { + //将新chainId添加到LiteFlowChainELBuilder和SHAMap + String chainData = chainJedis.hget(chainKey, chainId); + LiteFlowChainELBuilder.createChain().setChainId(chainId).setEL(chainData).build(); + LOG.info("starting poll flow config... update key={} new value={},", chainId, chainData); + chainSHAMap.put(chainId, DigestUtil.sha1Hex(chainData)); + } } - //SHA值无变化 表示该chain未改变 } } }; diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java index 934c5034..4ee4cea1 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java @@ -45,8 +45,8 @@ public class RedisParserBySubscribe implements RedisParserHelper { try { try { - this.chainClient = ContextAwareHolder.loadContextAware().getBean("chainRClient"); - this.scriptClient = ContextAwareHolder.loadContextAware().getBean("scriptRClient"); + this.chainClient = ContextAwareHolder.loadContextAware().getBean("chainClient"); + this.scriptClient = ContextAwareHolder.loadContextAware().getBean("scriptClient"); } catch (Exception ignored) { } @@ -69,11 +69,13 @@ public class RedisParserBySubscribe implements RedisParserHelper { private Config getRedissonConfig(RedisParserVO redisParserVO, Integer dataBase) { Config config = new Config(); String redisAddress = StrFormatter.format(REDIS_URL_PATTERN, redisParserVO.getHost(), redisParserVO.getPort()); + //如果配置了密码 if (StrUtil.isNotBlank(redisParserVO.getPassword())) { config.useSingleServer().setAddress(redisAddress) .setPassword(redisParserVO.getPassword()) .setDatabase(dataBase); } + //没有配置密码 else { config.useSingleServer().setAddress(redisAddress) .setDatabase(dataBase); @@ -93,10 +95,10 @@ public class RedisParserBySubscribe implements RedisParserHelper { } // 获取chainKey下的所有子节点内容List List chainItemContentList = new ArrayList<>(); - for (String chainName : chainNameSet) { - String chainData = chainKey.get(chainName); + for (String chainId : chainNameSet) { + String chainData = chainKey.get(chainId); if (StrUtil.isNotBlank(chainData)) { - chainItemContentList.add(StrUtil.format(CHAIN_XML_PATTERN, chainName, chainData)); + chainItemContentList.add(StrUtil.format(CHAIN_XML_PATTERN, chainId, chainData)); } } // 合并成所有chain的xml内容 diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java index 45d12a4b..d3f53f54 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java @@ -13,7 +13,7 @@ public class RedisParserVO { private String host; /*端口号*/ - private String port; + private Integer port; /*密码*/ private String password; @@ -44,11 +44,11 @@ public class RedisParserVO { this.host = host; } - public String getPort() { + public Integer getPort() { return port; } - public void setPort(String port) { + public void setPort(Integer port) { this.port = port; } From 7bdda07129b1455faff94e276a516de462a813a5 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sun, 9 Jul 2023 17:01:01 +0800 Subject: [PATCH 18/41] fix:logic --- .../redis/util/RedisParserByPolling.java | 27 +++++-------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java index 3eb48e0c..18d91152 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java @@ -213,29 +213,12 @@ public class RedisParserByPolling implements RedisParserHelper{ @Override public void run() { String chainKey = redisParserVO.getChainKey(); - //先判断chainKey中chain数量有无增长 + //先获取chainKey中最新的chain数量 String keyNum = chainJedis.evalsha(keyLua, 1, chainKey).toString(); //修改chainFieldNum为最新chain数量 chainFieldNum = Integer.parseInt(keyNum); - if (Integer.parseInt(keyNum) > chainFieldNum) { - //有新增加的chain,重新从redis中拉取chainId集合, 对比出新增的chain - Set newChainSet = chainJedis.hkeys(chainKey); - Set oldChainSet = chainSHAMap.keySet(); - //求出差集,即新增的chain - Set newAdd = new HashSet<>(); - newAdd.addAll(newChainSet); - newAdd.removeAll(oldChainSet); - for (String newChainId : newAdd) { - String chainData = chainJedis.hget(chainKey, newChainId); - LiteFlowChainELBuilder.createChain().setChainId(newChainId).setEL(chainData).build(); - LOG.info("starting poll flow config... update key={} new value={},", newChainId, chainData); - //修改SHAMap - chainSHAMap.put(newChainId, DigestUtil.sha1Hex(chainData)); - } - } - - //遍历Map,判断各个chain的值有无变化 + //遍历Map,判断各个chain的value有无变化:修改变化了值的chain和被删除的chain for(Map.Entry entry: chainSHAMap.entrySet()) { String chainId = entry.getKey(); String oldSHA = entry.getValue(); @@ -260,9 +243,11 @@ public class RedisParserByPolling implements RedisParserHelper{ //SHA值无变化,表示该chain未改变 } + //处理新添加chain和chainId被修改的情况 if (chainFieldNum > chainSHAMap.size()) { - //如果封装的SHAMap数量比新的chain总数少, 说明有修改了chainId的情况 - //因为遍历到旧的id时会取到nil,SHAMap会把原来的chainId删掉,但没有机会添加新的chainId + //如果封装的SHAMap数量比新的chain总数少, 说明有两种情况: + // 1、添加了新chain + // 2、修改了chainId:因为遍历到旧的id时会取到nil,SHAMap会把原来的chainId删掉,但没有机会添加新的chainId //在此处重新拉取所有chainId集合,补充添加新chainId Set newChainSet = chainJedis.hkeys(chainKey); for (String chainId : newChainSet) { From c16a38341b4033e4c00b5381106cdd63430b645c Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sun, 9 Jul 2023 17:25:10 +0800 Subject: [PATCH 19/41] fix:lambda --- .../redis/util/RedisParserByPolling.java | 86 +++++++++---------- 1 file changed, 42 insertions(+), 44 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java index 18d91152..2ac5853b 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java @@ -209,55 +209,53 @@ public class RedisParserByPolling implements RedisParserHelper{ * 再根据hash中value的SHA值修改变化的和被删除的chain */ private Runnable pollChainTask(String keyLua, String valueLua) { - Runnable r = new Runnable() { - @Override - public void run() { - String chainKey = redisParserVO.getChainKey(); - //先获取chainKey中最新的chain数量 - String keyNum = chainJedis.evalsha(keyLua, 1, chainKey).toString(); - //修改chainFieldNum为最新chain数量 - chainFieldNum = Integer.parseInt(keyNum); + Runnable r = () -> { + String chainKey = redisParserVO.getChainKey(); + //先获取chainKey中最新的chain数量 + String keyNum = chainJedis.evalsha(keyLua, 1, chainKey).toString(); + //修改chainFieldNum为最新chain数量 + chainFieldNum = Integer.parseInt(keyNum); - //遍历Map,判断各个chain的value有无变化:修改变化了值的chain和被删除的chain - for(Map.Entry entry: chainSHAMap.entrySet()) { - String chainId = entry.getKey(); - String oldSHA = entry.getValue(); - String newSHA = chainJedis.evalsha(valueLua, 2, chainKey, chainId).toString(); - if (StrUtil.equals(newSHA, "nil")) { - //新SHA值为nil, 即未获取到该chain,表示该chain已被删除 - FlowBus.removeChain(chainId); - LOG.info("starting reload flow config... delete key={}", chainId); + //遍历Map,判断各个chain的value有无变化:修改变化了值的chain和被删除的chain + for(Map.Entry entry: chainSHAMap.entrySet()) { + String chainId = entry.getKey(); + String oldSHA = entry.getValue(); + String newSHA = chainJedis.evalsha(valueLua, 2, chainKey, chainId).toString(); + if (StrUtil.equals(newSHA, "nil")) { + //新SHA值为nil, 即未获取到该chain,表示该chain已被删除 + FlowBus.removeChain(chainId); + LOG.info("starting reload flow config... delete key={}", chainId); - //修改SHAMap - chainSHAMap.remove(chainId); - } - else if (!StrUtil.equals(newSHA, oldSHA)) { - //SHA值发生变化,表示该chain的值已被修改,重新拉取变化的chain + //修改SHAMap + chainSHAMap.remove(chainId); + } + else if (!StrUtil.equals(newSHA, oldSHA)) { + //SHA值发生变化,表示该chain的值已被修改,重新拉取变化的chain + String chainData = chainJedis.hget(chainKey, chainId); + LiteFlowChainELBuilder.createChain().setChainId(chainId).setEL(chainData).build(); + LOG.info("starting poll flow config... update key={} new value={},", chainId, chainData); + + //修改SHAMap + chainSHAMap.put(chainId, newSHA); + } + //SHA值无变化,表示该chain未改变 + } + + //处理新添加chain和chainId被修改的情况 + if (chainFieldNum > chainSHAMap.size()) { + //如果封装的SHAMap数量比最新chain总数少, 说明有两种情况: + // 1、添加了新chain + // 2、修改了chainId:因为遍历到旧的id时会取到nil,SHAMap会把原来的chainId删掉,但没有机会添加新的chainId + // 3、上述两者结合 + //在此处重新拉取所有chainId集合,补充添加新chain + Set newChainSet = chainJedis.hkeys(chainKey); + for (String chainId : newChainSet) { + if (chainSHAMap.get(chainId) == null) { + //将新chainId添加到LiteFlowChainELBuilder和SHAMap String chainData = chainJedis.hget(chainKey, chainId); LiteFlowChainELBuilder.createChain().setChainId(chainId).setEL(chainData).build(); LOG.info("starting poll flow config... update key={} new value={},", chainId, chainData); - - //修改SHAMap - chainSHAMap.put(chainId, newSHA); - } - //SHA值无变化,表示该chain未改变 - } - - //处理新添加chain和chainId被修改的情况 - if (chainFieldNum > chainSHAMap.size()) { - //如果封装的SHAMap数量比新的chain总数少, 说明有两种情况: - // 1、添加了新chain - // 2、修改了chainId:因为遍历到旧的id时会取到nil,SHAMap会把原来的chainId删掉,但没有机会添加新的chainId - //在此处重新拉取所有chainId集合,补充添加新chainId - Set newChainSet = chainJedis.hkeys(chainKey); - for (String chainId : newChainSet) { - if (chainSHAMap.get(chainId) == null) { - //将新chainId添加到LiteFlowChainELBuilder和SHAMap - String chainData = chainJedis.hget(chainKey, chainId); - LiteFlowChainELBuilder.createChain().setChainId(chainId).setEL(chainData).build(); - LOG.info("starting poll flow config... update key={} new value={},", chainId, chainData); - chainSHAMap.put(chainId, DigestUtil.sha1Hex(chainData)); - } + chainSHAMap.put(chainId, DigestUtil.sha1Hex(chainData)); } } } From e6348b08cc2e424b1b4991a2bc485a28a54a6cf4 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sun, 9 Jul 2023 18:22:32 +0800 Subject: [PATCH 20/41] add poll script task --- .../redis/util/RedisParserByPolling.java | 85 ++++++++++++++++--- .../redis/util/RedisParserBySubscribe.java | 30 +------ .../parser/redis/util/RedisParserHelper.java | 31 +++++++ .../parser/redis/vo/RedisParserVO.java | 1 + 4 files changed, 110 insertions(+), 37 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java index 2ac5853b..f5dba400 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java @@ -33,10 +33,10 @@ public class RedisParserByPolling implements RedisParserHelper{ private Jedis scriptJedis; //chainKey中chain总数 - private Integer chainFieldNum = 0; + private Integer chainNum = 0; //scriptKey中script总数 - private Integer scriptFieldNum = 0; + private Integer scriptNum = 0; //chainKey中value的SHA1加密值 用于轮询时确定value是否变化 private Map chainSHAMap = new HashMap<>(); @@ -99,7 +99,7 @@ public class RedisParserByPolling implements RedisParserHelper{ if (CollectionUtil.isEmpty(chainNameSet)) { throw new RedisException(StrUtil.format("There are no chains in key [{}]", chainKey)); } - chainFieldNum = chainNameSet.size(); + chainNum = chainNameSet.size(); // 获取chainKey下的所有子节点内容List List chainItemContentList = new ArrayList<>(); for (String chainName : chainNameSet) { @@ -120,7 +120,7 @@ public class RedisParserByPolling implements RedisParserHelper{ if (hasScript()) { String scriptKey = redisParserVO.getScriptKey(); Set scriptFieldSet = scriptJedis.hkeys(scriptKey); - scriptFieldNum = scriptFieldSet.size(); + scriptNum = scriptFieldSet.size(); List scriptItemContentList = new ArrayList<>(); for (String scriptFieldValue : scriptFieldSet) { @@ -188,7 +188,7 @@ public class RedisParserByPolling implements RedisParserHelper{ //定时任务线程池 ScheduledExecutorService pool = Executors.newScheduledThreadPool(10); - //轮询chain内容的定时任务 + //添加轮询chain的定时任务 pool.scheduleAtFixedRate(pollChainTask(keyLuaOfChain, valueLuaOfChain), 60, Long.valueOf(redisParserVO.getPollingInterval()), TimeUnit.SECONDS); @@ -198,8 +198,10 @@ public class RedisParserByPolling implements RedisParserHelper{ //将lua脚本添加到scriptJedis脚本缓存 String keyLuaOfScript = scriptJedis.scriptLoad(luaOfKey); String valueLuaOfScript = scriptJedis.scriptLoad(luaOfValue); + //添加轮询script的定时任务 + pool.scheduleAtFixedRate(pollScriptTask(keyLuaOfScript, valueLuaOfScript), + 60, Long.valueOf(redisParserVO.getPollingInterval()), TimeUnit.SECONDS); } - } @@ -211,15 +213,16 @@ public class RedisParserByPolling implements RedisParserHelper{ private Runnable pollChainTask(String keyLua, String valueLua) { Runnable r = () -> { String chainKey = redisParserVO.getChainKey(); - //先获取chainKey中最新的chain数量 + //Lua获取chainKey中最新的chain数量 String keyNum = chainJedis.evalsha(keyLua, 1, chainKey).toString(); - //修改chainFieldNum为最新chain数量 - chainFieldNum = Integer.parseInt(keyNum); + //修改chainNum为最新chain数量 + chainNum = Integer.parseInt(keyNum); //遍历Map,判断各个chain的value有无变化:修改变化了值的chain和被删除的chain for(Map.Entry entry: chainSHAMap.entrySet()) { String chainId = entry.getKey(); String oldSHA = entry.getValue(); + //在redis服务端通过Lua脚本计算SHA值 String newSHA = chainJedis.evalsha(valueLua, 2, chainKey, chainId).toString(); if (StrUtil.equals(newSHA, "nil")) { //新SHA值为nil, 即未获取到该chain,表示该chain已被删除 @@ -242,7 +245,7 @@ public class RedisParserByPolling implements RedisParserHelper{ } //处理新添加chain和chainId被修改的情况 - if (chainFieldNum > chainSHAMap.size()) { + if (chainNum > chainSHAMap.size()) { //如果封装的SHAMap数量比最新chain总数少, 说明有两种情况: // 1、添加了新chain // 2、修改了chainId:因为遍历到旧的id时会取到nil,SHAMap会把原来的chainId删掉,但没有机会添加新的chainId @@ -262,4 +265,66 @@ public class RedisParserByPolling implements RedisParserHelper{ }; return r; } + + /** + * 用于轮询script的定时任务 + * 首先根据hash中field数量的变化拉取新增的script + * 再根据hash中value的SHA值修改变化的和被删除的script + */ + private Runnable pollScriptTask(String keyLua, String valueLua) { + Runnable r = () -> { + String scriptKey = redisParserVO.getScriptKey(); + //Lua获取scriptKey中最新的script数量 + String keyNum = scriptJedis.evalsha(keyLua, 1, scriptKey).toString(); + //修改scriptNum为最新script数量 + scriptNum = Integer.parseInt(keyNum); + + //遍历Map,判断各个script的value有无变化:修改变化了值的script和被删除的script + for(Map.Entry entry: scriptSHAMap.entrySet()) { + String scriptFieldValue = entry.getKey(); + String oldSHA = entry.getValue(); + //在redis服务端通过Lua脚本计算SHA值 + String newSHA = scriptJedis.evalsha(valueLua, 2, scriptKey, scriptFieldValue).toString(); + if (StrUtil.equals(newSHA, "nil")) { + //新SHA值为nil, 即未获取到该script,表示该script已被删除 + NodeSimpleVO nodeSimpleVO = convert(scriptFieldValue); + FlowBus.getNodeMap().remove(nodeSimpleVO.getNodeId()); + LOG.info("starting reload flow config... delete key={}", scriptFieldValue); + + //修改SHAMap + scriptSHAMap.remove(scriptFieldValue); + } + else if (!StrUtil.equals(newSHA, oldSHA)) { + //SHA值发生变化,表示该script的值已被修改,重新拉取变化的script + String scriptData = scriptJedis.hget(scriptKey, scriptFieldValue); + changeScriptNode(scriptFieldValue, scriptData); + LOG.info("starting reload flow config... update key={} new value={},", scriptFieldValue, scriptData); + + //修改SHAMap + scriptSHAMap.put(scriptFieldValue, newSHA); + } + //SHA值无变化,表示该script未改变 + } + + //处理新添加script和script名被修改的情况 + if (scriptNum > scriptSHAMap.size()) { + //如果封装的SHAMap数量比最新script总数少, 说明有两种情况: + // 1、添加了新script + // 2、修改了script名:因为遍历到旧的id时会取到nil,SHAMap会把原来的script删掉,但没有机会添加新的script + // 3、上述两者结合 + //在此处重新拉取所有script名集合,补充添加新script + Set newScriptSet = scriptJedis.hkeys(scriptKey); + for (String scriptFieldValue : newScriptSet) { + if (scriptSHAMap.get(scriptFieldValue) == null) { + //将新script添加到LiteFlowChainELBuilder和SHAMap + String scriptData = scriptJedis.hget(scriptKey, scriptFieldValue); + changeScriptNode(scriptFieldValue, scriptData); + LOG.info("starting reload flow config... update key={} new value={},", scriptFieldValue, scriptData); + scriptSHAMap.put(scriptFieldValue, DigestUtil.sha1Hex(scriptData)); + } + } + } + }; + return r; + } } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java index 4ee4cea1..9a7fc796 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java @@ -189,14 +189,12 @@ public class RedisParserBySubscribe implements RedisParserHelper { //添加 script scriptKey.addListener((EntryCreatedListener) event -> { LOG.info("starting reload flow config... create key={} value={},", event.getKey(), event.getValue()); - NodeSimpleVO nodeSimpleVO = convert(event.getKey()); - changeScriptNode(nodeSimpleVO, event.getValue()); + changeScriptNode(event.getKey(), event.getValue()); }); //修改 script scriptKey.addListener((EntryUpdatedListener) event -> { - LOG.info("starting reload flow config... update path={} new value={},", event.getKey(), event.getValue()); - NodeSimpleVO nodeSimpleVO = convert(event.getKey()); - changeScriptNode(nodeSimpleVO, event.getValue()); + LOG.info("starting reload flow config... update key={} new value={},", event.getKey(), event.getValue()); + changeScriptNode(event.getKey(), event.getValue()); }); //删除 script scriptKey.addListener((EntryRemovedListener) event -> { @@ -206,26 +204,4 @@ public class RedisParserBySubscribe implements RedisParserHelper { }); } } - - private void changeScriptNode(NodeSimpleVO nodeSimpleVO, String newValue) { - // 有语言类型 - if (StrUtil.isNotBlank(nodeSimpleVO.getLanguage())) { - LiteFlowNodeBuilder.createScriptNode() - .setId(nodeSimpleVO.getNodeId()) - .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType())) - .setName(nodeSimpleVO.getName()) - .setScript(newValue) - .setLanguage(nodeSimpleVO.getLanguage()) - .build(); - } - // 没有语言类型 - else { - LiteFlowNodeBuilder.createScriptNode() - .setId(nodeSimpleVO.getNodeId()) - .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType())) - .setName(nodeSimpleVO.getName()) - .setScript(newValue) - .build(); - } - } } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java index ca1c7364..821ab3f7 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java @@ -3,7 +3,9 @@ package com.yomahub.liteflow.parser.redis.util; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; +import com.yomahub.liteflow.builder.LiteFlowNodeBuilder; import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.enums.NodeTypeEnum; import com.yomahub.liteflow.log.LFLog; import com.yomahub.liteflow.log.LFLoggerManager; import org.slf4j.Logger; @@ -38,6 +40,35 @@ public interface RedisParserHelper { void listenRedis(); + + /** + * script节点的修改/添加 + * @param scriptFieldValue 新的script名 + * @param newValue 新的script值 + */ + default void changeScriptNode(String scriptFieldValue, String newValue) { + NodeSimpleVO nodeSimpleVO = convert(scriptFieldValue); + // 有语言类型 + if (StrUtil.isNotBlank(nodeSimpleVO.getLanguage())) { + LiteFlowNodeBuilder.createScriptNode() + .setId(nodeSimpleVO.getNodeId()) + .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType())) + .setName(nodeSimpleVO.getName()) + .setScript(newValue) + .setLanguage(nodeSimpleVO.getLanguage()) + .build(); + } + // 没有语言类型 + else { + LiteFlowNodeBuilder.createScriptNode() + .setId(nodeSimpleVO.getNodeId()) + .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType())) + .setName(nodeSimpleVO.getName()) + .setScript(newValue) + .build(); + } + } + default NodeSimpleVO convert(String str) { // 不需要去理解这串正则,就是一个匹配冒号的 // 一定得是a:b,或是a:b:c...这种完整类型的字符串的 diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java index d3f53f54..1848ecb1 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java @@ -22,6 +22,7 @@ public class RedisParserVO { private String mode = "poll"; /*轮询时间间隔(s) 默认1分钟 若选择订阅机制可不配置*/ + //todo 确定类型是string还是long,若为string需校验 private String pollingInterval = "60"; /*chain表配置的数据库号*/ From e0d6f875aea70ac4d2342dcefa34e83cf0953863 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sat, 15 Jul 2023 16:51:26 +0800 Subject: [PATCH 21/41] fix:enum --- .../parser/redis/RedisXmlELParser.java | 15 ++++++++--- .../redis/util/RedisParserByPolling.java | 4 +-- .../parser/redis/vo/RedisModeEnum.java | 25 +++++++++++++++++++ .../parser/redis/vo/RedisParserVO.java | 13 +++++++--- .../pom.xml | 19 ++++++++++++++ .../com/yomahub/liteflow/test/BaseTest.java | 4 +++ .../redis/RedisWithXmlELSpringbootTest.java | 4 +++ .../yomahub/liteflow/test/redis/cmp/ACmp.java | 4 +++ .../yomahub/liteflow/test/redis/cmp/BCmp.java | 4 +++ .../yomahub/liteflow/test/redis/cmp/CCmp.java | 4 +++ liteflow-testcase-el/pom.xml | 1 + 11 files changed, 88 insertions(+), 9 deletions(-) create mode 100644 liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisModeEnum.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-redis-springboot/pom.xml create mode 100644 liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/BaseTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSpringbootTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/ACmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/BCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/CCmp.java diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java index 23961a50..0abec86d 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java @@ -12,6 +12,7 @@ import com.yomahub.liteflow.parser.redis.exception.RedisException; import com.yomahub.liteflow.parser.redis.util.RedisParserByPolling; import com.yomahub.liteflow.parser.redis.util.RedisParserBySubscribe; import com.yomahub.liteflow.parser.redis.util.RedisParserHelper; +import com.yomahub.liteflow.parser.redis.vo.RedisModeEnum; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import com.yomahub.liteflow.property.LiteflowConfig; import com.yomahub.liteflow.property.LiteflowConfigGetter; @@ -54,10 +55,16 @@ public class RedisXmlELParser extends ClassXmlFlowELParser { checkParserVO(redisParserVO); //选择订阅机制 or 轮询机制 - if (StrUtil.equalsIgnoreCase("subscribe", redisParserVO.getMode())) { - redisParserHelper = new RedisParserBySubscribe(redisParserVO); - } else { - redisParserHelper = new RedisParserByPolling(redisParserVO); + RedisModeEnum mode = redisParserVO.getMode(); + switch (mode) { + case SUB: + case SUBSCRIBE: + redisParserHelper = new RedisParserBySubscribe(redisParserVO); + break; + case POLL: + default: + redisParserHelper = new RedisParserByPolling(redisParserVO); + break; } } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java index f5dba400..590f3d73 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java @@ -207,8 +207,8 @@ public class RedisParserByPolling implements RedisParserHelper{ /** * 用于轮询chain的定时任务 - * 首先根据hash中field数量的变化拉取新增的chain - * 再根据hash中value的SHA值修改变化的和被删除的chain + * 先根据hash中value的SHA值修改变化的和被删除的chain + * 再根据hash中field数量的变化拉取新增的chain */ private Runnable pollChainTask(String keyLua, String valueLua) { Runnable r = () -> { diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisModeEnum.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisModeEnum.java new file mode 100644 index 00000000..e7437421 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisModeEnum.java @@ -0,0 +1,25 @@ +package com.yomahub.liteflow.parser.redis.vo; + +/** + * 用于定义redis规则存储和监听方式的枚举类 + * + * @author hxinyu + * @since 2.10.6 + */ +public enum RedisModeEnum { + + //poll为轮询模式,subscribe/sub为订阅模式,默认为poll + POLL("poll"), + SUB("subscribe"), + SUBSCRIBE("subscribe"); + + private String mode; + + RedisModeEnum(String mode) { + this.mode = mode; + } + + public String getMode() { + return mode; + } +} diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java index 1848ecb1..72b94454 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java @@ -19,7 +19,7 @@ public class RedisParserVO { private String password; /*监听机制 轮询为poll 订阅为subscribe 默认为poll*/ - private String mode = "poll"; + private RedisModeEnum mode = RedisModeEnum.POLL; /*轮询时间间隔(s) 默认1分钟 若选择订阅机制可不配置*/ //todo 确定类型是string还是long,若为string需校验 @@ -61,12 +61,19 @@ public class RedisParserVO { this.password = password; } - public String getMode() { + public RedisModeEnum getMode() { return mode; } public void setMode(String mode) { - this.mode = mode; + mode = mode.toUpperCase(); + try{ + RedisModeEnum m = RedisModeEnum.valueOf(mode); + this.mode = m; + } + catch (Exception ignored) { + //枚举类转换出错默认为轮询方式 + } } public String getPollingInterval() { diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/pom.xml b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/pom.xml new file mode 100644 index 00000000..4f142cd6 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/pom.xml @@ -0,0 +1,19 @@ + + + + liteflow-testcase-el + com.yomahub + ${revision} + ../pom.xml + + 4.0.0 + + liteflow-testcase-el-redis-springboot + + + + + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/BaseTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/BaseTest.java new file mode 100644 index 00000000..5ea79be7 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/BaseTest.java @@ -0,0 +1,4 @@ +package com.yomahub.liteflow.test; + +public class BaseTest { +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSpringbootTest.java new file mode 100644 index 00000000..b3373438 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSpringbootTest.java @@ -0,0 +1,4 @@ +package com.yomahub.liteflow.test.redis; + +public class RedisWithXmlELSpringbootTest { +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/ACmp.java new file mode 100644 index 00000000..5ee118ef --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/ACmp.java @@ -0,0 +1,4 @@ +package com.yomahub.liteflow.test.redis.cmp; + +public class ACmp { +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/BCmp.java new file mode 100644 index 00000000..ab191401 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/BCmp.java @@ -0,0 +1,4 @@ +package com.yomahub.liteflow.test.redis.cmp; + +public class BCmp { +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/CCmp.java new file mode 100644 index 00000000..277bdbe0 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/CCmp.java @@ -0,0 +1,4 @@ +package com.yomahub.liteflow.test.redis.cmp; + +public class CCmp { +} diff --git a/liteflow-testcase-el/pom.xml b/liteflow-testcase-el/pom.xml index 2d53f349..6a2189ce 100644 --- a/liteflow-testcase-el/pom.xml +++ b/liteflow-testcase-el/pom.xml @@ -34,6 +34,7 @@ liteflow-testcase-el-script-lua-springboot liteflow-testcase-el-script-multi-language-springboot liteflow-testcase-el-script-aviator-springboot + liteflow-testcase-el-redis-springboot From 414b3503a56ab4bd01724dedf3ba51415d88582b Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sat, 15 Jul 2023 19:47:17 +0800 Subject: [PATCH 22/41] fix:package structure --- .../parser/redis/RedisXmlELParser.java | 14 +- .../{util => mode}/RedisParserHelper.java | 10 +- .../RedisParserMode.java} | 6 +- .../redis/mode/polling/ChainPollingTask.java | 102 ++++++++++++ .../polling/RedisParserPollingMode.java} | 151 ++---------------- .../redis/mode/polling/ScriptPollingTask.java | 101 ++++++++++++ .../subscribe/RedisParserSubscribeMode.java} | 17 +- .../parser/redis/vo/RedisParserVO.java | 8 +- 8 files changed, 245 insertions(+), 164 deletions(-) rename liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/{util => mode}/RedisParserHelper.java (92%) rename liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/{vo/RedisModeEnum.java => mode/RedisParserMode.java} (76%) create mode 100644 liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java rename liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/{util/RedisParserByPolling.java => mode/polling/RedisParserPollingMode.java} (50%) create mode 100644 liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java rename liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/{util/RedisParserBySubscribe.java => mode/subscribe/RedisParserSubscribeMode.java} (93%) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java index 0abec86d..07ab1f8a 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java @@ -9,10 +9,10 @@ import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.core.FlowInitHook; import com.yomahub.liteflow.parser.el.ClassXmlFlowELParser; import com.yomahub.liteflow.parser.redis.exception.RedisException; -import com.yomahub.liteflow.parser.redis.util.RedisParserByPolling; -import com.yomahub.liteflow.parser.redis.util.RedisParserBySubscribe; -import com.yomahub.liteflow.parser.redis.util.RedisParserHelper; -import com.yomahub.liteflow.parser.redis.vo.RedisModeEnum; +import com.yomahub.liteflow.parser.redis.mode.polling.RedisParserPollingMode; +import com.yomahub.liteflow.parser.redis.mode.subscribe.RedisParserSubscribeMode; +import com.yomahub.liteflow.parser.redis.mode.RedisParserHelper; +import com.yomahub.liteflow.parser.redis.mode.RedisParserMode; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import com.yomahub.liteflow.property.LiteflowConfig; import com.yomahub.liteflow.property.LiteflowConfigGetter; @@ -55,15 +55,15 @@ public class RedisXmlELParser extends ClassXmlFlowELParser { checkParserVO(redisParserVO); //选择订阅机制 or 轮询机制 - RedisModeEnum mode = redisParserVO.getMode(); + RedisParserMode mode = redisParserVO.getMode(); switch (mode) { case SUB: case SUBSCRIBE: - redisParserHelper = new RedisParserBySubscribe(redisParserVO); + redisParserHelper = new RedisParserSubscribeMode(redisParserVO); break; case POLL: default: - redisParserHelper = new RedisParserByPolling(redisParserVO); + redisParserHelper = new RedisParserPollingMode(redisParserVO); break; } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java similarity index 92% rename from liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java rename to liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java index 821ab3f7..ee054167 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java @@ -1,4 +1,4 @@ -package com.yomahub.liteflow.parser.redis.util; +package com.yomahub.liteflow.parser.redis.mode; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ReUtil; @@ -8,8 +8,6 @@ import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.enums.NodeTypeEnum; import com.yomahub.liteflow.log.LFLog; import com.yomahub.liteflow.log.LFLoggerManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.util.List; @@ -22,7 +20,7 @@ import java.util.List; public interface RedisParserHelper { - LFLog LOG = LFLoggerManager.getLogger(FlowExecutor.class); + LFLog LOG = LFLoggerManager.getLogger(FlowExecutor.class); String REDIS_URL_PATTERN = "redis://{}:{}"; @@ -46,7 +44,7 @@ public interface RedisParserHelper { * @param scriptFieldValue 新的script名 * @param newValue 新的script值 */ - default void changeScriptNode(String scriptFieldValue, String newValue) { + static void changeScriptNode(String scriptFieldValue, String newValue) { NodeSimpleVO nodeSimpleVO = convert(scriptFieldValue); // 有语言类型 if (StrUtil.isNotBlank(nodeSimpleVO.getLanguage())) { @@ -69,7 +67,7 @@ public interface RedisParserHelper { } } - default NodeSimpleVO convert(String str) { + static NodeSimpleVO convert(String str) { // 不需要去理解这串正则,就是一个匹配冒号的 // 一定得是a:b,或是a:b:c...这种完整类型的字符串的 List matchItemList = ReUtil.findAllGroup0("(?<=[^:]:)[^:]+|[^:]+(?=:[^:])", str); diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisModeEnum.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserMode.java similarity index 76% rename from liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisModeEnum.java rename to liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserMode.java index e7437421..7709943d 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisModeEnum.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserMode.java @@ -1,4 +1,4 @@ -package com.yomahub.liteflow.parser.redis.vo; +package com.yomahub.liteflow.parser.redis.mode; /** * 用于定义redis规则存储和监听方式的枚举类 @@ -6,7 +6,7 @@ package com.yomahub.liteflow.parser.redis.vo; * @author hxinyu * @since 2.10.6 */ -public enum RedisModeEnum { +public enum RedisParserMode { //poll为轮询模式,subscribe/sub为订阅模式,默认为poll POLL("poll"), @@ -15,7 +15,7 @@ public enum RedisModeEnum { private String mode; - RedisModeEnum(String mode) { + RedisParserMode(String mode) { this.mode = mode; } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java new file mode 100644 index 00000000..c12bf94e --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java @@ -0,0 +1,102 @@ +package com.yomahub.liteflow.parser.redis.mode.polling; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.digest.DigestUtil; +import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; +import com.yomahub.liteflow.flow.FlowBus; +import com.yomahub.liteflow.log.LFLog; +import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; +import redis.clients.jedis.Jedis; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * 用于轮询chain的定时任务 + * + * @author hxinyu + * @since 2.10.6 + */ +public class ChainPollingTask { + + private RedisParserVO redisParserVO; + + private Jedis chainJedis; + + private Integer chainNum; + + private Map chainSHAMap; + + LFLog LOG; + + public ChainPollingTask(RedisParserVO redisParserVO, Jedis chainJedis, Integer chainNum, Map chainSHAMap, LFLog LOG) { + this.redisParserVO = redisParserVO; + this.chainJedis = chainJedis; + this.chainNum = chainNum; + this.chainSHAMap = chainSHAMap; + this.LOG = LOG; + } + + + /** + * 用于返回chain轮询任务的Runnable实例 + * 先根据hash中value的SHA值修改变化的和被删除的chain + * 再根据hash中field数量的变化拉取新增的chain + */ + public Runnable pollChainTask(String keyLua, String valueLua) { + Runnable r = () -> { + String chainKey = redisParserVO.getChainKey(); + //Lua获取chainKey中最新的chain数量 + String keyNum = chainJedis.evalsha(keyLua, 1, chainKey).toString(); + //修改chainNum为最新chain数量 + chainNum = Integer.parseInt(keyNum); + + //遍历Map,判断各个chain的value有无变化:修改变化了值的chain和被删除的chain + for(Map.Entry entry: chainSHAMap.entrySet()) { + String chainId = entry.getKey(); + String oldSHA = entry.getValue(); + //在redis服务端通过Lua脚本计算SHA值 + String newSHA = chainJedis.evalsha(valueLua, 2, chainKey, chainId).toString(); + if (StrUtil.equals(newSHA, "nil")) { + //新SHA值为nil, 即未获取到该chain,表示该chain已被删除 + FlowBus.removeChain(chainId); + LOG.info("starting reload flow config... delete key={}", chainId); + + //修改SHAMap + chainSHAMap.remove(chainId); + } + else if (!StrUtil.equals(newSHA, oldSHA)) { + //SHA值发生变化,表示该chain的值已被修改,重新拉取变化的chain + String chainData = chainJedis.hget(chainKey, chainId); + LiteFlowChainELBuilder.createChain().setChainId(chainId).setEL(chainData).build(); + LOG.info("starting poll flow config... update key={} new value={},", chainId, chainData); + + //修改SHAMap + chainSHAMap.put(chainId, newSHA); + } + //SHA值无变化,表示该chain未改变 + } + + //处理新添加chain和chainId被修改的情况 + if (chainNum > chainSHAMap.size()) { + //如果封装的SHAMap数量比最新chain总数少, 说明有两种情况: + // 1、添加了新chain + // 2、修改了chainId:因为遍历到旧的id时会取到nil,SHAMap会把原来的chainId删掉,但没有机会添加新的chainId + // 3、上述两者结合 + //在此处重新拉取所有chainId集合,补充添加新chain + Set newChainSet = chainJedis.hkeys(chainKey); + for (String chainId : newChainSet) { + if (chainSHAMap.get(chainId) == null) { + //将新chainId添加到LiteFlowChainELBuilder和SHAMap + String chainData = chainJedis.hget(chainKey, chainId); + LiteFlowChainELBuilder.createChain().setChainId(chainId).setEL(chainData).build(); + LOG.info("starting poll flow config... update key={} new value={},", chainId, chainData); + chainSHAMap.put(chainId, DigestUtil.sha1Hex(chainData)); + } + } + } + }; + return r; + } +} diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java similarity index 50% rename from liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java rename to liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java index 590f3d73..15ac2c06 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserByPolling.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java @@ -1,13 +1,12 @@ -package com.yomahub.liteflow.parser.redis.util; +package com.yomahub.liteflow.parser.redis.mode.polling; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.digest.DigestUtil; -import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; -import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.parser.redis.exception.RedisException; +import com.yomahub.liteflow.parser.redis.mode.RedisParserHelper; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import com.yomahub.liteflow.spi.holder.ContextAwareHolder; import redis.clients.jedis.Jedis; @@ -24,7 +23,7 @@ import java.util.concurrent.TimeUnit; * @since 2.10.6 */ -public class RedisParserByPolling implements RedisParserHelper{ +public class RedisParserPollingMode implements RedisParserHelper { private final RedisParserVO redisParserVO; @@ -45,11 +44,11 @@ public class RedisParserByPolling implements RedisParserHelper{ private Map scriptSHAMap = new HashMap<>(); //计算hash中field数量的lua脚本 - private String luaOfKey = "local keys = redis.call(\"hkeys\", KEYS[1]);\n" + + private final String luaOfKey = "local keys = redis.call(\"hkeys\", KEYS[1]);\n" + "return #keys;\n"; //计算hash中value的SHA值的lua脚本 - private String luaOfValue = "local key = KEYS[1];\n" + + private final String luaOfValue = "local key = KEYS[1];\n" + "local field = KEYS[2];\n" + "local value, err = redis.call(\"hget\", key, field);\n" + "if value == false or value == nil then\n" + @@ -58,7 +57,7 @@ public class RedisParserByPolling implements RedisParserHelper{ "local sha1 = redis.sha1hex(value);\n" + "return sha1;"; - public RedisParserByPolling(RedisParserVO redisParserVO) { + public RedisParserPollingMode(RedisParserVO redisParserVO) { this.redisParserVO = redisParserVO; try{ @@ -124,7 +123,7 @@ public class RedisParserByPolling implements RedisParserHelper{ List scriptItemContentList = new ArrayList<>(); for (String scriptFieldValue : scriptFieldSet) { - NodeSimpleVO nodeSimpleVO = convert(scriptFieldValue); + NodeSimpleVO nodeSimpleVO = RedisParserHelper.convert(scriptFieldValue); if (ObjectUtil.isNull(nodeSimpleVO)) { throw new RedisException( StrUtil.format("The name of the redis field [{}] in scriptKey [{}] is invalid", @@ -188,9 +187,11 @@ public class RedisParserByPolling implements RedisParserHelper{ //定时任务线程池 ScheduledExecutorService pool = Executors.newScheduledThreadPool(10); + //添加轮询chain的定时任务 - pool.scheduleAtFixedRate(pollChainTask(keyLuaOfChain, valueLuaOfChain), - 60, Long.valueOf(redisParserVO.getPollingInterval()), TimeUnit.SECONDS); + ChainPollingTask chainTask = new ChainPollingTask(redisParserVO, chainJedis, chainNum, chainSHAMap, LOG); + pool.scheduleAtFixedRate(chainTask.pollChainTask(keyLuaOfChain, valueLuaOfChain), + 60, Long.parseLong(redisParserVO.getPollingInterval()), TimeUnit.SECONDS); //如果有脚本 if (ObjectUtil.isNotNull(scriptJedis) && ObjectUtil.isNotNull(redisParserVO.getScriptDataBase()) @@ -198,133 +199,11 @@ public class RedisParserByPolling implements RedisParserHelper{ //将lua脚本添加到scriptJedis脚本缓存 String keyLuaOfScript = scriptJedis.scriptLoad(luaOfKey); String valueLuaOfScript = scriptJedis.scriptLoad(luaOfValue); + //添加轮询script的定时任务 - pool.scheduleAtFixedRate(pollScriptTask(keyLuaOfScript, valueLuaOfScript), - 60, Long.valueOf(redisParserVO.getPollingInterval()), TimeUnit.SECONDS); + ScriptPollingTask scriptTask = new ScriptPollingTask(redisParserVO, scriptJedis, scriptNum, scriptSHAMap, LOG); + pool.scheduleAtFixedRate(scriptTask.pollScriptTask(keyLuaOfScript, valueLuaOfScript), + 60, Long.parseLong(redisParserVO.getPollingInterval()), TimeUnit.SECONDS); } } - - - /** - * 用于轮询chain的定时任务 - * 先根据hash中value的SHA值修改变化的和被删除的chain - * 再根据hash中field数量的变化拉取新增的chain - */ - private Runnable pollChainTask(String keyLua, String valueLua) { - Runnable r = () -> { - String chainKey = redisParserVO.getChainKey(); - //Lua获取chainKey中最新的chain数量 - String keyNum = chainJedis.evalsha(keyLua, 1, chainKey).toString(); - //修改chainNum为最新chain数量 - chainNum = Integer.parseInt(keyNum); - - //遍历Map,判断各个chain的value有无变化:修改变化了值的chain和被删除的chain - for(Map.Entry entry: chainSHAMap.entrySet()) { - String chainId = entry.getKey(); - String oldSHA = entry.getValue(); - //在redis服务端通过Lua脚本计算SHA值 - String newSHA = chainJedis.evalsha(valueLua, 2, chainKey, chainId).toString(); - if (StrUtil.equals(newSHA, "nil")) { - //新SHA值为nil, 即未获取到该chain,表示该chain已被删除 - FlowBus.removeChain(chainId); - LOG.info("starting reload flow config... delete key={}", chainId); - - //修改SHAMap - chainSHAMap.remove(chainId); - } - else if (!StrUtil.equals(newSHA, oldSHA)) { - //SHA值发生变化,表示该chain的值已被修改,重新拉取变化的chain - String chainData = chainJedis.hget(chainKey, chainId); - LiteFlowChainELBuilder.createChain().setChainId(chainId).setEL(chainData).build(); - LOG.info("starting poll flow config... update key={} new value={},", chainId, chainData); - - //修改SHAMap - chainSHAMap.put(chainId, newSHA); - } - //SHA值无变化,表示该chain未改变 - } - - //处理新添加chain和chainId被修改的情况 - if (chainNum > chainSHAMap.size()) { - //如果封装的SHAMap数量比最新chain总数少, 说明有两种情况: - // 1、添加了新chain - // 2、修改了chainId:因为遍历到旧的id时会取到nil,SHAMap会把原来的chainId删掉,但没有机会添加新的chainId - // 3、上述两者结合 - //在此处重新拉取所有chainId集合,补充添加新chain - Set newChainSet = chainJedis.hkeys(chainKey); - for (String chainId : newChainSet) { - if (chainSHAMap.get(chainId) == null) { - //将新chainId添加到LiteFlowChainELBuilder和SHAMap - String chainData = chainJedis.hget(chainKey, chainId); - LiteFlowChainELBuilder.createChain().setChainId(chainId).setEL(chainData).build(); - LOG.info("starting poll flow config... update key={} new value={},", chainId, chainData); - chainSHAMap.put(chainId, DigestUtil.sha1Hex(chainData)); - } - } - } - }; - return r; - } - - /** - * 用于轮询script的定时任务 - * 首先根据hash中field数量的变化拉取新增的script - * 再根据hash中value的SHA值修改变化的和被删除的script - */ - private Runnable pollScriptTask(String keyLua, String valueLua) { - Runnable r = () -> { - String scriptKey = redisParserVO.getScriptKey(); - //Lua获取scriptKey中最新的script数量 - String keyNum = scriptJedis.evalsha(keyLua, 1, scriptKey).toString(); - //修改scriptNum为最新script数量 - scriptNum = Integer.parseInt(keyNum); - - //遍历Map,判断各个script的value有无变化:修改变化了值的script和被删除的script - for(Map.Entry entry: scriptSHAMap.entrySet()) { - String scriptFieldValue = entry.getKey(); - String oldSHA = entry.getValue(); - //在redis服务端通过Lua脚本计算SHA值 - String newSHA = scriptJedis.evalsha(valueLua, 2, scriptKey, scriptFieldValue).toString(); - if (StrUtil.equals(newSHA, "nil")) { - //新SHA值为nil, 即未获取到该script,表示该script已被删除 - NodeSimpleVO nodeSimpleVO = convert(scriptFieldValue); - FlowBus.getNodeMap().remove(nodeSimpleVO.getNodeId()); - LOG.info("starting reload flow config... delete key={}", scriptFieldValue); - - //修改SHAMap - scriptSHAMap.remove(scriptFieldValue); - } - else if (!StrUtil.equals(newSHA, oldSHA)) { - //SHA值发生变化,表示该script的值已被修改,重新拉取变化的script - String scriptData = scriptJedis.hget(scriptKey, scriptFieldValue); - changeScriptNode(scriptFieldValue, scriptData); - LOG.info("starting reload flow config... update key={} new value={},", scriptFieldValue, scriptData); - - //修改SHAMap - scriptSHAMap.put(scriptFieldValue, newSHA); - } - //SHA值无变化,表示该script未改变 - } - - //处理新添加script和script名被修改的情况 - if (scriptNum > scriptSHAMap.size()) { - //如果封装的SHAMap数量比最新script总数少, 说明有两种情况: - // 1、添加了新script - // 2、修改了script名:因为遍历到旧的id时会取到nil,SHAMap会把原来的script删掉,但没有机会添加新的script - // 3、上述两者结合 - //在此处重新拉取所有script名集合,补充添加新script - Set newScriptSet = scriptJedis.hkeys(scriptKey); - for (String scriptFieldValue : newScriptSet) { - if (scriptSHAMap.get(scriptFieldValue) == null) { - //将新script添加到LiteFlowChainELBuilder和SHAMap - String scriptData = scriptJedis.hget(scriptKey, scriptFieldValue); - changeScriptNode(scriptFieldValue, scriptData); - LOG.info("starting reload flow config... update key={} new value={},", scriptFieldValue, scriptData); - scriptSHAMap.put(scriptFieldValue, DigestUtil.sha1Hex(scriptData)); - } - } - } - }; - return r; - } } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java new file mode 100644 index 00000000..540d86a9 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java @@ -0,0 +1,101 @@ +package com.yomahub.liteflow.parser.redis.mode.polling; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.digest.DigestUtil; +import com.yomahub.liteflow.flow.FlowBus; +import com.yomahub.liteflow.log.LFLog; +import com.yomahub.liteflow.parser.redis.mode.RedisParserHelper; +import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; +import redis.clients.jedis.Jedis; + +import java.util.Map; +import java.util.Set; + +/** + * 用于轮询script的定时任务 + * + * @author hxinyu + * @since 2.10.6 + */ +public class ScriptPollingTask { + + private RedisParserVO redisParserVO; + + private Jedis scriptJedis; + + private Integer scriptNum; + + private Map scriptSHAMap; + + LFLog LOG; + + public ScriptPollingTask(RedisParserVO redisParserVO, Jedis scriptJedis, Integer scriptNum, Map scriptSHAMap, LFLog LOG) { + this.redisParserVO = redisParserVO; + this.scriptJedis = scriptJedis; + this.scriptNum = scriptNum; + this.scriptSHAMap = scriptSHAMap; + this.LOG = LOG; + } + + + /** + * 用于返回script轮询任务的Runnable实例 + * 首先根据hash中field数量的变化拉取新增的script + * 再根据hash中value的SHA值修改变化的和被删除的script + */ + public Runnable pollScriptTask(String keyLua, String valueLua) { + Runnable r = () -> { + String scriptKey = redisParserVO.getScriptKey(); + //Lua获取scriptKey中最新的script数量 + String keyNum = scriptJedis.evalsha(keyLua, 1, scriptKey).toString(); + //修改scriptNum为最新script数量 + scriptNum = Integer.parseInt(keyNum); + + //遍历Map,判断各个script的value有无变化:修改变化了值的script和被删除的script + for (Map.Entry entry : scriptSHAMap.entrySet()) { + String scriptFieldValue = entry.getKey(); + String oldSHA = entry.getValue(); + //在redis服务端通过Lua脚本计算SHA值 + String newSHA = scriptJedis.evalsha(valueLua, 2, scriptKey, scriptFieldValue).toString(); + if (StrUtil.equals(newSHA, "nil")) { + //新SHA值为nil, 即未获取到该script,表示该script已被删除 + RedisParserHelper.NodeSimpleVO nodeSimpleVO = RedisParserHelper.convert(scriptFieldValue); + FlowBus.getNodeMap().remove(nodeSimpleVO.getNodeId()); + LOG.info("starting reload flow config... delete key={}", scriptFieldValue); + + //修改SHAMap + scriptSHAMap.remove(scriptFieldValue); + } else if (!StrUtil.equals(newSHA, oldSHA)) { + //SHA值发生变化,表示该script的值已被修改,重新拉取变化的script + String scriptData = scriptJedis.hget(scriptKey, scriptFieldValue); + RedisParserHelper.changeScriptNode(scriptFieldValue, scriptData); + LOG.info("starting reload flow config... update key={} new value={},", scriptFieldValue, scriptData); + + //修改SHAMap + scriptSHAMap.put(scriptFieldValue, newSHA); + } + //SHA值无变化,表示该script未改变 + } + + //处理新添加script和script名被修改的情况 + if (scriptNum > scriptSHAMap.size()) { + //如果封装的SHAMap数量比最新script总数少, 说明有两种情况: + // 1、添加了新script + // 2、修改了script名:因为遍历到旧的id时会取到nil,SHAMap会把原来的script删掉,但没有机会添加新的script + // 3、上述两者结合 + //在此处重新拉取所有script名集合,补充添加新script + Set newScriptSet = scriptJedis.hkeys(scriptKey); + for (String scriptFieldValue : newScriptSet) { + if (scriptSHAMap.get(scriptFieldValue) == null) { + //将新script添加到LiteFlowChainELBuilder和SHAMap + String scriptData = scriptJedis.hget(scriptKey, scriptFieldValue); + RedisParserHelper.changeScriptNode(scriptFieldValue, scriptData); + LOG.info("starting reload flow config... update key={} new value={},", scriptFieldValue, scriptData); + scriptSHAMap.put(scriptFieldValue, DigestUtil.sha1Hex(scriptData)); + } + } + } + }; + return r; + } +} \ No newline at end of file diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java similarity index 93% rename from liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java rename to liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java index 9a7fc796..41162fa3 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/util/RedisParserBySubscribe.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java @@ -1,15 +1,14 @@ -package com.yomahub.liteflow.parser.redis.util; +package com.yomahub.liteflow.parser.redis.mode.subscribe; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.text.StrFormatter; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; -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.redis.exception.RedisException; +import com.yomahub.liteflow.parser.redis.mode.RedisParserHelper; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import com.yomahub.liteflow.spi.holder.ContextAwareHolder; import org.redisson.Redisson; @@ -32,7 +31,7 @@ import java.util.Set; * @since 2.10.6 */ -public class RedisParserBySubscribe implements RedisParserHelper { +public class RedisParserSubscribeMode implements RedisParserHelper { private final RedisParserVO redisParserVO; @@ -40,7 +39,7 @@ public class RedisParserBySubscribe implements RedisParserHelper { private RedissonClient scriptClient; - public RedisParserBySubscribe(RedisParserVO redisParserVO) { + public RedisParserSubscribeMode(RedisParserVO redisParserVO) { this.redisParserVO = redisParserVO; try { @@ -112,7 +111,7 @@ public class RedisParserBySubscribe implements RedisParserHelper { List scriptItemContentList = new ArrayList<>(); for (String scriptFieldValue : scriptFieldSet) { - NodeSimpleVO nodeSimpleVO = convert(scriptFieldValue); + NodeSimpleVO nodeSimpleVO = RedisParserHelper.convert(scriptFieldValue); if (ObjectUtil.isNull(nodeSimpleVO)) { throw new RedisException( StrUtil.format("The name of the redis field [{}] in scriptKey [{}] is invalid", @@ -189,17 +188,17 @@ public class RedisParserBySubscribe implements RedisParserHelper { //添加 script scriptKey.addListener((EntryCreatedListener) event -> { LOG.info("starting reload flow config... create key={} value={},", event.getKey(), event.getValue()); - changeScriptNode(event.getKey(), event.getValue()); + RedisParserHelper.changeScriptNode(event.getKey(), event.getValue()); }); //修改 script scriptKey.addListener((EntryUpdatedListener) event -> { LOG.info("starting reload flow config... update key={} new value={},", event.getKey(), event.getValue()); - changeScriptNode(event.getKey(), event.getValue()); + RedisParserHelper.changeScriptNode(event.getKey(), event.getValue()); }); //删除 script scriptKey.addListener((EntryRemovedListener) event -> { LOG.info("starting reload flow config... delete key={}", event.getKey()); - NodeSimpleVO nodeSimpleVO = convert(event.getKey()); + NodeSimpleVO nodeSimpleVO = RedisParserHelper.convert(event.getKey()); FlowBus.getNodeMap().remove(nodeSimpleVO.getNodeId()); }); } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java index 72b94454..1420596a 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java @@ -1,5 +1,7 @@ package com.yomahub.liteflow.parser.redis.vo; +import com.yomahub.liteflow.parser.redis.mode.RedisParserMode; + /** * 用于解析RuleSourceExtData的vo类,用于Redis模式中 * @@ -19,7 +21,7 @@ public class RedisParserVO { private String password; /*监听机制 轮询为poll 订阅为subscribe 默认为poll*/ - private RedisModeEnum mode = RedisModeEnum.POLL; + private RedisParserMode mode = RedisParserMode.POLL; /*轮询时间间隔(s) 默认1分钟 若选择订阅机制可不配置*/ //todo 确定类型是string还是long,若为string需校验 @@ -61,14 +63,14 @@ public class RedisParserVO { this.password = password; } - public RedisModeEnum getMode() { + public RedisParserMode getMode() { return mode; } public void setMode(String mode) { mode = mode.toUpperCase(); try{ - RedisModeEnum m = RedisModeEnum.valueOf(mode); + RedisParserMode m = RedisParserMode.valueOf(mode); this.mode = m; } catch (Exception ignored) { From 8db6cef414ce905d9402786c5b58ae77fb0ff747 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sat, 15 Jul 2023 19:54:33 +0800 Subject: [PATCH 23/41] fix:vo --- .../parser/redis/mode/polling/ChainPollingTask.java | 2 +- .../parser/redis/mode/polling/RedisParserPollingMode.java | 4 ++-- .../parser/redis/mode/polling/ScriptPollingTask.java | 2 +- .../yomahub/liteflow/parser/redis/vo/RedisParserVO.java | 7 +++---- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java index c12bf94e..d0c0e301 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java @@ -87,7 +87,7 @@ public class ChainPollingTask { //在此处重新拉取所有chainId集合,补充添加新chain Set newChainSet = chainJedis.hkeys(chainKey); for (String chainId : newChainSet) { - if (chainSHAMap.get(chainId) == null) { + if (!chainSHAMap.containsKey(chainId)) { //将新chainId添加到LiteFlowChainELBuilder和SHAMap String chainData = chainJedis.hget(chainKey, chainId); LiteFlowChainELBuilder.createChain().setChainId(chainId).setEL(chainData).build(); diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java index 15ac2c06..a9eb5937 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java @@ -191,7 +191,7 @@ public class RedisParserPollingMode implements RedisParserHelper { //添加轮询chain的定时任务 ChainPollingTask chainTask = new ChainPollingTask(redisParserVO, chainJedis, chainNum, chainSHAMap, LOG); pool.scheduleAtFixedRate(chainTask.pollChainTask(keyLuaOfChain, valueLuaOfChain), - 60, Long.parseLong(redisParserVO.getPollingInterval()), TimeUnit.SECONDS); + 60, redisParserVO.getPollingInterval().longValue(), TimeUnit.SECONDS); //如果有脚本 if (ObjectUtil.isNotNull(scriptJedis) && ObjectUtil.isNotNull(redisParserVO.getScriptDataBase()) @@ -203,7 +203,7 @@ public class RedisParserPollingMode implements RedisParserHelper { //添加轮询script的定时任务 ScriptPollingTask scriptTask = new ScriptPollingTask(redisParserVO, scriptJedis, scriptNum, scriptSHAMap, LOG); pool.scheduleAtFixedRate(scriptTask.pollScriptTask(keyLuaOfScript, valueLuaOfScript), - 60, Long.parseLong(redisParserVO.getPollingInterval()), TimeUnit.SECONDS); + 60, redisParserVO.getPollingInterval().longValue(), TimeUnit.SECONDS); } } } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java index 540d86a9..274c8207 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java @@ -86,7 +86,7 @@ public class ScriptPollingTask { //在此处重新拉取所有script名集合,补充添加新script Set newScriptSet = scriptJedis.hkeys(scriptKey); for (String scriptFieldValue : newScriptSet) { - if (scriptSHAMap.get(scriptFieldValue) == null) { + if (!scriptSHAMap.containsKey(scriptFieldValue)) { //将新script添加到LiteFlowChainELBuilder和SHAMap String scriptData = scriptJedis.hget(scriptKey, scriptFieldValue); RedisParserHelper.changeScriptNode(scriptFieldValue, scriptData); diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java index 1420596a..c55b7964 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java @@ -24,8 +24,7 @@ public class RedisParserVO { private RedisParserMode mode = RedisParserMode.POLL; /*轮询时间间隔(s) 默认1分钟 若选择订阅机制可不配置*/ - //todo 确定类型是string还是long,若为string需校验 - private String pollingInterval = "60"; + private Integer pollingInterval = 60; /*chain表配置的数据库号*/ private Integer chainDataBase; @@ -78,11 +77,11 @@ public class RedisParserVO { } } - public String getPollingInterval() { + public Integer getPollingInterval() { return pollingInterval; } - public void setPollingInterval(String pollingInterval) { + public void setPollingInterval(Integer pollingInterval) { this.pollingInterval = pollingInterval; } From c00ecbe8d01e9b8d41b15f3c041c320b84ea95e5 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sun, 23 Jul 2023 12:56:04 +0800 Subject: [PATCH 24/41] update version --- .../parser/redis/RedisXmlELParser.java | 2 +- .../redis/exception/RedisException.java | 2 +- .../parser/redis/mode/RedisParserHelper.java | 2 +- .../parser/redis/mode/RedisParserMode.java | 2 +- .../redis/mode/polling/ChainPollingTask.java | 2 +- .../mode/polling/RedisParserPollingMode.java | 25 +++++++++++++------ .../redis/mode/polling/ScriptPollingTask.java | 2 +- .../subscribe/RedisParserSubscribeMode.java | 2 +- .../parser/redis/vo/RedisParserVO.java | 2 +- .../spi/redis/RedisParserClassNameSpi.java | 3 +++ 10 files changed, 29 insertions(+), 15 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java index 07ab1f8a..547b291c 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/RedisXmlELParser.java @@ -24,7 +24,7 @@ import java.util.Objects; * Redis解析器实现,只支持EL形式的XML,不支持其他的形式 * * @author hxinyu - * @since 2.10.6 + * @since 2.11.0 */ public class RedisXmlELParser extends ClassXmlFlowELParser { diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/exception/RedisException.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/exception/RedisException.java index 3882bfb9..1b6ee435 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/exception/RedisException.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/exception/RedisException.java @@ -4,7 +4,7 @@ package com.yomahub.liteflow.parser.redis.exception; * Redis解析异常 * * @author hxinyu - * @since 2.10.6 + * @since 2.11.0 */ public class RedisException extends RuntimeException{ diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java index ee054167..5b176219 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java @@ -15,7 +15,7 @@ import java.util.List; * Redis 解析器通用接口 * * @author hxinyu - * @since 2.10.6 + * @since 2.11.0 */ public interface RedisParserHelper { diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserMode.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserMode.java index 7709943d..13c4b875 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserMode.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserMode.java @@ -4,7 +4,7 @@ package com.yomahub.liteflow.parser.redis.mode; * 用于定义redis规则存储和监听方式的枚举类 * * @author hxinyu - * @since 2.10.6 + * @since 2.11.0 */ public enum RedisParserMode { diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java index d0c0e301..127028c1 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java @@ -16,7 +16,7 @@ import java.util.Set; * 用于轮询chain的定时任务 * * @author hxinyu - * @since 2.10.6 + * @since 2.11.0 */ public class ChainPollingTask { diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java index a9eb5937..a7483a31 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java @@ -12,15 +12,13 @@ import com.yomahub.liteflow.spi.holder.ContextAwareHolder; import redis.clients.jedis.Jedis; import java.util.*; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; /** * Redis 轮询机制实现类 * * @author hxinyu - * @since 2.10.6 + * @since 2.11.0 */ public class RedisParserPollingMode implements RedisParserHelper { @@ -43,6 +41,15 @@ public class RedisParserPollingMode implements RedisParserHelper { //scriptKey中value的SHA1加密值 用于轮询时确定value是否变化 private Map scriptSHAMap = new HashMap<>(); + //定时任务线程池参数配置 + private static final int CORE_POOL_SIZE = 1; + + private static final int MAX_POOL_SIZE = 1; + + private static final int QUEUE_CAPACITY = 5; + + private static final Long KEEP_ALIVE_TIME = 1L; + //计算hash中field数量的lua脚本 private final String luaOfKey = "local keys = redis.call(\"hkeys\", KEYS[1]);\n" + "return #keys;\n"; @@ -186,11 +193,15 @@ public class RedisParserPollingMode implements RedisParserHelper { String valueLuaOfChain = chainJedis.scriptLoad(luaOfValue); //定时任务线程池 - ScheduledExecutorService pool = Executors.newScheduledThreadPool(10); + ScheduledExecutorService pool = Executors.newScheduledThreadPool(1); + ScheduledThreadPoolExecutor pollExecutor = new ScheduledThreadPoolExecutor( + CORE_POOL_SIZE, + new ThreadPoolExecutor.DiscardOldestPolicy()); + //添加轮询chain的定时任务 ChainPollingTask chainTask = new ChainPollingTask(redisParserVO, chainJedis, chainNum, chainSHAMap, LOG); - pool.scheduleAtFixedRate(chainTask.pollChainTask(keyLuaOfChain, valueLuaOfChain), + pollExecutor.scheduleAtFixedRate(chainTask.pollChainTask(keyLuaOfChain, valueLuaOfChain), 60, redisParserVO.getPollingInterval().longValue(), TimeUnit.SECONDS); //如果有脚本 @@ -202,7 +213,7 @@ public class RedisParserPollingMode implements RedisParserHelper { //添加轮询script的定时任务 ScriptPollingTask scriptTask = new ScriptPollingTask(redisParserVO, scriptJedis, scriptNum, scriptSHAMap, LOG); - pool.scheduleAtFixedRate(scriptTask.pollScriptTask(keyLuaOfScript, valueLuaOfScript), + pollExecutor.scheduleAtFixedRate(scriptTask.pollScriptTask(keyLuaOfScript, valueLuaOfScript), 60, redisParserVO.getPollingInterval().longValue(), TimeUnit.SECONDS); } } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java index 274c8207..0c4ad610 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java @@ -15,7 +15,7 @@ import java.util.Set; * 用于轮询script的定时任务 * * @author hxinyu - * @since 2.10.6 + * @since 2.11.0 */ public class ScriptPollingTask { diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java index 41162fa3..2a79a524 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java @@ -28,7 +28,7 @@ import java.util.Set; * Redisson客户端 RMapCache存储结构 * * @author hxinyu - * @since 2.10.6 + * @since 2.11.0 */ public class RedisParserSubscribeMode implements RedisParserHelper { diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java index c55b7964..ded77058 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java @@ -6,7 +6,7 @@ import com.yomahub.liteflow.parser.redis.mode.RedisParserMode; * 用于解析RuleSourceExtData的vo类,用于Redis模式中 * * @author hxinyu - * @since 2.10.6 + * @since 2.11.0 */ public class RedisParserVO { diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/spi/redis/RedisParserClassNameSpi.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/spi/redis/RedisParserClassNameSpi.java index 7fe750c1..51aeabfd 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/spi/redis/RedisParserClassNameSpi.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/spi/redis/RedisParserClassNameSpi.java @@ -5,6 +5,9 @@ import com.yomahub.liteflow.parser.spi.ParserClassNameSpi; /** * Redis 解析器 SPI 实现 + * + * @author hxinyu + * @since 2.11.0 */ public class RedisParserClassNameSpi implements ParserClassNameSpi { From eb1bec207801e039a7a7d5ab0bde20f6e13f4cab Mon Sep 17 00:00:00 2001 From: houxinyu Date: Mon, 24 Jul 2023 21:01:02 +0800 Subject: [PATCH 25/41] fix:bug && add junit test --- .../redis/mode/polling/ChainPollingTask.java | 19 ++- .../mode/polling/RedisParserPollingMode.java | 10 +- .../redis/mode/polling/ScriptPollingTask.java | 18 +- .../parser/redis/vo/RedisParserVO.java | 2 +- ...hub.liteflow.parser.spi.ParserClassNameSpi | 1 + .../pom.xml | 29 ++++ .../com/yomahub/liteflow/test/BaseTest.java | 18 ++ .../RedisWithXmlELPollSpringbootTest.java | 122 ++++++++++++++ .../redis/RedisWithXmlELSpringbootTest.java | 4 - ...RedisWithXmlELSubscribeSpringbootTest.java | 155 ++++++++++++++++++ .../yomahub/liteflow/test/redis/cmp/ACmp.java | 19 ++- .../yomahub/liteflow/test/redis/cmp/BCmp.java | 19 ++- .../yomahub/liteflow/test/redis/cmp/CCmp.java | 21 ++- .../redis/application-poll-xml.properties | 10 ++ .../redis/application-sub-xml.properties | 10 ++ 15 files changed, 428 insertions(+), 29 deletions(-) create mode 100644 liteflow-rule-plugin/liteflow-rule-redis/src/main/resources/META-INF/services/com.yomahub.liteflow.parser.spi.ParserClassNameSpi create mode 100644 liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSpringbootTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-poll-xml.properties create mode 100644 liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-sub-xml.properties diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java index 127028c1..fb127531 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java @@ -8,9 +8,7 @@ import com.yomahub.liteflow.log.LFLog; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import redis.clients.jedis.Jedis; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 用于轮询chain的定时任务 @@ -52,6 +50,7 @@ public class ChainPollingTask { //修改chainNum为最新chain数量 chainNum = Integer.parseInt(keyNum); + List needDelete = new ArrayList<>(); //遍历Map,判断各个chain的value有无变化:修改变化了值的chain和被删除的chain for(Map.Entry entry: chainSHAMap.entrySet()) { String chainId = entry.getKey(); @@ -63,14 +62,15 @@ public class ChainPollingTask { FlowBus.removeChain(chainId); LOG.info("starting reload flow config... delete key={}", chainId); - //修改SHAMap - chainSHAMap.remove(chainId); + //添加到待删除的list 后续统一从SHAMap中移除 + //不在这里直接移除是为了避免先删除导致chainSHAMap并没有完全遍历完 chain删除不全 + needDelete.add(chainId); } else if (!StrUtil.equals(newSHA, oldSHA)) { //SHA值发生变化,表示该chain的值已被修改,重新拉取变化的chain String chainData = chainJedis.hget(chainKey, chainId); LiteFlowChainELBuilder.createChain().setChainId(chainId).setEL(chainData).build(); - LOG.info("starting poll flow config... update key={} new value={},", chainId, chainData); + LOG.info("starting reload flow config... update key={} new value={},", chainId, chainData); //修改SHAMap chainSHAMap.put(chainId, newSHA); @@ -78,6 +78,11 @@ public class ChainPollingTask { //SHA值无变化,表示该chain未改变 } + //统一从SHAMap中移除要删除的chain + for (String chainId : needDelete) { + chainSHAMap.remove(chainId); + } + //处理新添加chain和chainId被修改的情况 if (chainNum > chainSHAMap.size()) { //如果封装的SHAMap数量比最新chain总数少, 说明有两种情况: @@ -91,7 +96,7 @@ public class ChainPollingTask { //将新chainId添加到LiteFlowChainELBuilder和SHAMap String chainData = chainJedis.hget(chainKey, chainId); LiteFlowChainELBuilder.createChain().setChainId(chainId).setEL(chainData).build(); - LOG.info("starting poll flow config... update key={} new value={},", chainId, chainData); + LOG.info("starting reload flow config... create key={} new value={},", chainId, chainData); chainSHAMap.put(chainId, DigestUtil.sha1Hex(chainData)); } } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java index a7483a31..8b796b22 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java @@ -41,15 +41,9 @@ public class RedisParserPollingMode implements RedisParserHelper { //scriptKey中value的SHA1加密值 用于轮询时确定value是否变化 private Map scriptSHAMap = new HashMap<>(); - //定时任务线程池参数配置 + //定时任务线程池核心线程数 private static final int CORE_POOL_SIZE = 1; - private static final int MAX_POOL_SIZE = 1; - - private static final int QUEUE_CAPACITY = 5; - - private static final Long KEEP_ALIVE_TIME = 1L; - //计算hash中field数量的lua脚本 private final String luaOfKey = "local keys = redis.call(\"hkeys\", KEYS[1]);\n" + "return #keys;\n"; @@ -193,12 +187,10 @@ public class RedisParserPollingMode implements RedisParserHelper { String valueLuaOfChain = chainJedis.scriptLoad(luaOfValue); //定时任务线程池 - ScheduledExecutorService pool = Executors.newScheduledThreadPool(1); ScheduledThreadPoolExecutor pollExecutor = new ScheduledThreadPoolExecutor( CORE_POOL_SIZE, new ThreadPoolExecutor.DiscardOldestPolicy()); - //添加轮询chain的定时任务 ChainPollingTask chainTask = new ChainPollingTask(redisParserVO, chainJedis, chainNum, chainSHAMap, LOG); pollExecutor.scheduleAtFixedRate(chainTask.pollChainTask(keyLuaOfChain, valueLuaOfChain), diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java index 0c4ad610..e00af848 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java @@ -8,6 +8,8 @@ import com.yomahub.liteflow.parser.redis.mode.RedisParserHelper; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import redis.clients.jedis.Jedis; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Set; @@ -51,6 +53,7 @@ public class ScriptPollingTask { //修改scriptNum为最新script数量 scriptNum = Integer.parseInt(keyNum); + List needDelete = new ArrayList<>(); //遍历Map,判断各个script的value有无变化:修改变化了值的script和被删除的script for (Map.Entry entry : scriptSHAMap.entrySet()) { String scriptFieldValue = entry.getKey(); @@ -63,9 +66,11 @@ public class ScriptPollingTask { FlowBus.getNodeMap().remove(nodeSimpleVO.getNodeId()); LOG.info("starting reload flow config... delete key={}", scriptFieldValue); - //修改SHAMap - scriptSHAMap.remove(scriptFieldValue); - } else if (!StrUtil.equals(newSHA, oldSHA)) { + //添加到待删除的list 后续统一从SHAMap中移除 + //不在这里直接移除是为了避免先删除导致scriptSHAMap并没有完全遍历完 script删除不全 + needDelete.add(scriptFieldValue); + } + else if (!StrUtil.equals(newSHA, oldSHA)) { //SHA值发生变化,表示该script的值已被修改,重新拉取变化的script String scriptData = scriptJedis.hget(scriptKey, scriptFieldValue); RedisParserHelper.changeScriptNode(scriptFieldValue, scriptData); @@ -77,6 +82,11 @@ public class ScriptPollingTask { //SHA值无变化,表示该script未改变 } + //统一从SHAMap中移除要删除的script + for (String scriptFieldValue : needDelete) { + scriptSHAMap.remove(scriptFieldValue); + } + //处理新添加script和script名被修改的情况 if (scriptNum > scriptSHAMap.size()) { //如果封装的SHAMap数量比最新script总数少, 说明有两种情况: @@ -90,7 +100,7 @@ public class ScriptPollingTask { //将新script添加到LiteFlowChainELBuilder和SHAMap String scriptData = scriptJedis.hget(scriptKey, scriptFieldValue); RedisParserHelper.changeScriptNode(scriptFieldValue, scriptData); - LOG.info("starting reload flow config... update key={} new value={},", scriptFieldValue, scriptData); + LOG.info("starting reload flow config... create key={} new value={},", scriptFieldValue, scriptData); scriptSHAMap.put(scriptFieldValue, DigestUtil.sha1Hex(scriptData)); } } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java index ded77058..beeee195 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java @@ -42,7 +42,7 @@ public class RedisParserVO { return host; } - public void setHost(String url) { + public void setHost(String host) { this.host = host; } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/resources/META-INF/services/com.yomahub.liteflow.parser.spi.ParserClassNameSpi b/liteflow-rule-plugin/liteflow-rule-redis/src/main/resources/META-INF/services/com.yomahub.liteflow.parser.spi.ParserClassNameSpi new file mode 100644 index 00000000..3e341b98 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/resources/META-INF/services/com.yomahub.liteflow.parser.spi.ParserClassNameSpi @@ -0,0 +1 @@ +com.yomahub.liteflow.parser.spi.redis.RedisParserClassNameSpi \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/pom.xml b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/pom.xml index 4f142cd6..90fe5ef9 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/pom.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/pom.xml @@ -13,7 +13,36 @@ liteflow-testcase-el-redis-springboot + + com.yomahub + liteflow-spring-boot-starter + ${revision} + + + com.yomahub + liteflow-rule-redis + ${revision} + test + + + + org.springframework.boot + spring-boot-starter-test + + + + com.yomahub + liteflow-script-groovy + ${revision} + + + + com.yomahub + liteflow-script-graaljs + ${revision} + test + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/BaseTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/BaseTest.java index 5ea79be7..e282c0fd 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/BaseTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/BaseTest.java @@ -1,4 +1,22 @@ package com.yomahub.liteflow.test; +import com.yomahub.liteflow.core.FlowInitHook; +import com.yomahub.liteflow.flow.FlowBus; +import com.yomahub.liteflow.property.LiteflowConfigGetter; +import com.yomahub.liteflow.spi.holder.SpiFactoryCleaner; +import com.yomahub.liteflow.spring.ComponentScanner; +import com.yomahub.liteflow.thread.ExecutorHelper; +import org.junit.jupiter.api.AfterAll; + public class BaseTest { + + @AfterAll + public static void cleanScanCache() { + ComponentScanner.cleanCache(); + FlowBus.cleanCache(); + ExecutorHelper.loadInstance().clearExecutorServiceMap(); + SpiFactoryCleaner.clean(); + LiteflowConfigGetter.clean(); + FlowInitHook.cleanHook(); + } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java new file mode 100644 index 00000000..9341434b --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java @@ -0,0 +1,122 @@ +package com.yomahub.liteflow.test.redis; + +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.property.LiteflowConfigGetter; +import com.yomahub.liteflow.util.JsonUtil; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.redisson.api.RMapCache; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import redis.clients.jedis.Jedis; + +import javax.annotation.Resource; + +/** + * springboot环境下的redis配置源轮询拉取模式功能测试 + * + * @author hxinyu + * @since 2.11.0 + */ +@ExtendWith(SpringExtension.class) +@TestPropertySource(value = "classpath:/redis/application-poll-xml.properties") +@SpringBootTest(classes = RedisWithXmlELPollSpringbootTest.class) +@EnableAutoConfiguration +@ComponentScan({"com.yomahub.liteflow.test.redis.cmp"}) +public class RedisWithXmlELPollSpringbootTest { + + private static Jedis jedis; + + @Resource + private FlowExecutor flowExecutor; + + @BeforeAll + public static void setUpBeforeClass() { + jedis = new Jedis("localhost", 6379); + jedis.select(1); + jedis.hset("pollScriptKey", "s1:script:脚本s1:groovy", "defaultContext.setData(\"test1\",\"hello s1\");"); + jedis.hset("pollScriptKey", "s2:script:脚本s2:js", "defaultContext.setData(\"test2\",\"hello s2\");"); + jedis.hset("pollScriptKey", "s3:script:脚本s3", "defaultContext.setData(\"test3\",\"hello s3\");"); + + jedis.hset("pollChainKey", "chain1", "THEN(a, b, c);"); + jedis.hset("pollChainKey", "chain2", "THEN(a, b, c, s3);"); + jedis.hset("pollChainKey", "chain3", "THEN(a, b, c, s1, s2);"); + } + + @Test + public void testPollWithXml() throws InterruptedException { + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertEquals("a==>b==>c", response.getExecuteStepStr()); + + + //修改redis中规则 + changeXMLData(); + //重新加载规则 定时任务1分钟后开始第一次轮询 所以这里休眠1分钟 + Thread.sleep(65000); + Assertions.assertEquals("a==>c==>b", flowExecutor.execute2Resp("chain1", "arg").getExecuteStepStr()); + + //删除redis中规则 + deleteXMLData(); + //重新加载规则 + Thread.sleep(5000); + response = flowExecutor.execute2Resp("chain1", "arg"); + Assertions.assertTrue(!response.isSuccess()); + response = flowExecutor.execute2Resp("chain2", "arg"); + Assertions.assertTrue(!response.isSuccess()); + + + //添加redis中规则 + addXMLData(); + //重新加载规则 + Thread.sleep(5000); + Assertions.assertEquals("b==>c", flowExecutor.execute2Resp("chain4", "arg").getExecuteStepStr()); + } + + + /** + * 修改redisson中的chain + */ + public void changeXMLData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + jedis.hset(redisParserVO.getChainKey(), "chain1", "THEN(a, c, b);"); + } + + /** + * 删除redisson中的chain + */ + public void deleteXMLData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + jedis.hdel(redisParserVO.getChainKey(), "chain1"); + jedis.hdel(redisParserVO.getChainKey(), "chain2"); + } + + + /** + * 新增redisson中的chain + */ + public void addXMLData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + jedis.hset(redisParserVO.getChainKey(), "chain4", "THEN(b, c);"); + } + + /** + * 修改redisson中的脚本 + */ + public void changeScriptData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + jedis.hset(redisParserVO.getScriptKey(), "s1:script:脚本s1:groovy", "defaultContext.setData(\"test1\",\"hello s1 version2\");"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSpringbootTest.java deleted file mode 100644 index b3373438..00000000 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSpringbootTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.yomahub.liteflow.test.redis; - -public class RedisWithXmlELSpringbootTest { -} diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java new file mode 100644 index 00000000..fbb6d9dd --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java @@ -0,0 +1,155 @@ +package com.yomahub.liteflow.test.redis; + +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.property.LiteflowConfigGetter; +import com.yomahub.liteflow.slot.DefaultContext; +import com.yomahub.liteflow.util.JsonUtil; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.redisson.Redisson; +import org.redisson.api.RMapCache; +import org.redisson.api.RedissonClient; +import org.redisson.config.Config; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import javax.annotation.Resource; +import java.util.Set; + +/** + * springboot环境下的redis配置源订阅模式功能测试 + * + * @author hxinyu + * @since 2.11.0 + */ +@ExtendWith(SpringExtension.class) +@TestPropertySource(value = "classpath:/redis/application-sub-xml.properties") +@SpringBootTest(classes = RedisWithXmlELSubscribeSpringbootTest.class) +@EnableAutoConfiguration +@ComponentScan({"com.yomahub.liteflow.test.redis.cmp"}) +public class RedisWithXmlELSubscribeSpringbootTest { + + private static RedissonClient redissonClient; + + @Resource + private FlowExecutor flowExecutor; + + @BeforeAll + public static void setUpBeforeClass() { + Config config = new Config(); + config.useSingleServer().setAddress("redis://127.0.0.1:6379").setDatabase(1); + redissonClient = Redisson.create(config); + RMapCache chainKey = redissonClient.getMapCache("chainKey"); + RMapCache scriptKey = redissonClient.getMapCache("scriptKey"); + scriptKey.put("s1:script:脚本s1:groovy", "defaultContext.setData(\"test1\",\"hello s1\");"); + scriptKey.put("s2:script:脚本s2:js", "defaultContext.setData(\"test2\",\"hello s2\");"); + scriptKey.put("s3:script:脚本s3", "defaultContext.setData(\"test3\",\"hello s3\");"); + chainKey.put("chain1", "THEN(a, b, c);"); + chainKey.put("chain2", "THEN(a, b, c, s3);"); + chainKey.put("chain3", "THEN(a, b, c, s1, s2);"); + } + + @Test + public void testSubWithXml() throws InterruptedException { + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertEquals("a==>b==>c", response.getExecuteStepStr()); + + //修改redis中规则 + changeXMLData(); + //重新加载规则 + Thread.sleep(50); + Assertions.assertEquals("a==>c==>b", flowExecutor.execute2Resp("chain1", "arg").getExecuteStepStr()); + + //删除redis中规则 + deleteXMLData(); + //重新加载规则 + Thread.sleep(50); + response = flowExecutor.execute2Resp("chain1", "arg"); + Assertions.assertTrue(!response.isSuccess()); + + //添加redis中规则 + addXMLData(); + //重新加载规则 + Thread.sleep(50); + Assertions.assertEquals("b==>c", flowExecutor.execute2Resp("chain4", "arg").getExecuteStepStr()); + } + + @Test + public void testSubWithScriptXml() throws InterruptedException { + LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg"); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertEquals("hello s1", context.getData("test1")); + Assertions.assertEquals("a==>b==>c==>s1[脚本s1]==>s2[脚本s2]", response.getExecuteStepStrWithoutTime()); + + //添加和删除脚本 + addAndDeleteScriptData(); + //修改redis脚本 + changeScriptData(); + Thread.sleep(50); + context = flowExecutor.execute2Resp("chain3", "arg").getFirstContextBean(); + Assertions.assertEquals("hello s1 version2", context.getData("test1")); + } + + /** + * 修改redisson中的chain + */ + public void changeXMLData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + RMapCache chainKey = redissonClient.getMapCache(redisParserVO.getChainKey()); + chainKey.put("chain1", "THEN(a, c, b);"); + } + + /** + * 删除redisson中的chain + */ + public void deleteXMLData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + RMapCache chainKey = redissonClient.getMapCache(redisParserVO.getChainKey()); + chainKey.remove("chain1"); + chainKey.remove("chain4"); + } + + /** + * 新增redisson中的chain + */ + public void addXMLData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + RMapCache chainKey = redissonClient.getMapCache(redisParserVO.getChainKey()); + chainKey.put("chain4","THEN(b, c);"); + } + + /** + * 修改redisson中的脚本 + */ + public void changeScriptData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + RMapCache scriptKey = redissonClient.getMapCache(redisParserVO.getScriptKey()); + scriptKey.put("s1:script:脚本s1:groovy", "defaultContext.setData(\"test1\",\"hello s1 version2\");"); + } + + /** + * 新增和删除redisson中的chain + */ + public void addAndDeleteScriptData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + RMapCache scriptKey = redissonClient.getMapCache(redisParserVO.getScriptKey()); + scriptKey.remove("s4:script:脚本s4"); + scriptKey.remove("s5:script:脚本s5:groovy"); + scriptKey.put("s5:script:脚本s5:groovy", "defaultContext.setData(\"test1\",\"hello s5\");"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/ACmp.java index 5ee118ef..34aae4c0 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/ACmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/ACmp.java @@ -1,4 +1,21 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ package com.yomahub.liteflow.test.redis.cmp; -public class ACmp { +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +@Component("a") +public class ACmp extends NodeComponent { + + @Override + public void process() { + System.out.println("ACmp executed!"); + } + } diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/BCmp.java index ab191401..86ea7f13 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/BCmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/BCmp.java @@ -1,4 +1,21 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ package com.yomahub.liteflow.test.redis.cmp; -public class BCmp { +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +@Component("b") +public class BCmp extends NodeComponent { + + @Override + public void process() { + System.out.println("BCmp executed!"); + } + } diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/CCmp.java index 277bdbe0..983980a0 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/CCmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/cmp/CCmp.java @@ -1,4 +1,21 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ package com.yomahub.liteflow.test.redis.cmp; -public class CCmp { -} +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +@Component("c") +public class CCmp extends NodeComponent { + + @Override + public void process() { + System.out.println("CCmp executed!"); + } + +} \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-poll-xml.properties b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-poll-xml.properties new file mode 100644 index 00000000..c89b0866 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-poll-xml.properties @@ -0,0 +1,10 @@ +liteflow.rule-source-ext-data={\ + "host":"localhost",\ + "port":6379,\ + "pollingInterval":1,\ + "chainDataBase":1,\ + "chainKey":"pollChainKey",\ + "scriptDataBase":1,\ + "scriptKey":"pollScriptKey"\ + } +liteflow.parse-on-start=false \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-sub-xml.properties b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-sub-xml.properties new file mode 100644 index 00000000..9bbce2e2 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-sub-xml.properties @@ -0,0 +1,10 @@ +liteflow.rule-source-ext-data={\ + "host":"localhost",\ + "port":6379,\ + "mode":"SUB",\ + "chainDataBase":1,\ + "chainKey":"chainKey",\ + "scriptDataBase":1,\ + "scriptKey":"scriptKey"\ + } +liteflow.parse-on-start=false \ No newline at end of file From 8835997ebc892e3755bdd26ef5ef27cb4be28350 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Tue, 25 Jul 2023 15:32:47 +0800 Subject: [PATCH 26/41] add poll test --- .../parser/redis/mode/RedisParserHelper.java | 2 +- .../RedisWithXmlELPollSpringbootTest.java | 101 ++++++++++++++---- ...RedisWithXmlELSubscribeSpringbootTest.java | 41 ++++++- 3 files changed, 122 insertions(+), 22 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java index 5b176219..afe98fc8 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java @@ -20,7 +20,7 @@ import java.util.List; public interface RedisParserHelper { - LFLog LOG = LFLoggerManager.getLogger(FlowExecutor.class); + LFLog LOG = LFLoggerManager.getLogger(RedisParserHelper.class); String REDIS_URL_PATTERN = "redis://{}:{}"; diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java index 9341434b..f9ed44ce 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java @@ -1,16 +1,22 @@ package com.yomahub.liteflow.test.redis; import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.core.FlowInitHook; +import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.flow.LiteflowResponse; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import com.yomahub.liteflow.property.LiteflowConfig; import com.yomahub.liteflow.property.LiteflowConfigGetter; +import com.yomahub.liteflow.slot.DefaultContext; +import com.yomahub.liteflow.spi.holder.SpiFactoryCleaner; +import com.yomahub.liteflow.spring.ComponentScanner; +import com.yomahub.liteflow.thread.ExecutorHelper; import com.yomahub.liteflow.util.JsonUtil; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.redisson.api.RMapCache; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.ComponentScan; @@ -42,18 +48,18 @@ public class RedisWithXmlELPollSpringbootTest { public static void setUpBeforeClass() { jedis = new Jedis("localhost", 6379); jedis.select(1); - jedis.hset("pollScriptKey", "s1:script:脚本s1:groovy", "defaultContext.setData(\"test1\",\"hello s1\");"); - jedis.hset("pollScriptKey", "s2:script:脚本s2:js", "defaultContext.setData(\"test2\",\"hello s2\");"); - jedis.hset("pollScriptKey", "s3:script:脚本s3", "defaultContext.setData(\"test3\",\"hello s3\");"); + jedis.hset("pollScriptKey", "s11:script:脚本s11:groovy", "defaultContext.setData(\"test11\",\"hello s11\");"); + jedis.hset("pollScriptKey", "s22:script:脚本s22:js", "defaultContext.setData(\"test22\",\"hello s22\");"); + jedis.hset("pollScriptKey", "s33:script:脚本s33", "defaultContext.setData(\"test33\",\"hello s33\");"); - jedis.hset("pollChainKey", "chain1", "THEN(a, b, c);"); - jedis.hset("pollChainKey", "chain2", "THEN(a, b, c, s3);"); - jedis.hset("pollChainKey", "chain3", "THEN(a, b, c, s1, s2);"); + jedis.hset("pollChainKey", "chain11", "THEN(a, b, c);"); + jedis.hset("pollChainKey", "chain22", "THEN(a, b, c, s33);"); + jedis.hset("pollChainKey", "chain33", "THEN(a, b, c, s11, s22);"); } @Test public void testPollWithXml() throws InterruptedException { - LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + LiteflowResponse response = flowExecutor.execute2Resp("chain11", "arg"); Assertions.assertTrue(response.isSuccess()); Assertions.assertEquals("a==>b==>c", response.getExecuteStepStr()); @@ -62,23 +68,42 @@ public class RedisWithXmlELPollSpringbootTest { changeXMLData(); //重新加载规则 定时任务1分钟后开始第一次轮询 所以这里休眠1分钟 Thread.sleep(65000); - Assertions.assertEquals("a==>c==>b", flowExecutor.execute2Resp("chain1", "arg").getExecuteStepStr()); + Assertions.assertEquals("a==>c==>b", flowExecutor.execute2Resp("chain11", "arg").getExecuteStepStr()); //删除redis中规则 deleteXMLData(); //重新加载规则 - Thread.sleep(5000); - response = flowExecutor.execute2Resp("chain1", "arg"); + Thread.sleep(1000); + response = flowExecutor.execute2Resp("chain11", "arg"); Assertions.assertTrue(!response.isSuccess()); - response = flowExecutor.execute2Resp("chain2", "arg"); + response = flowExecutor.execute2Resp("chain22", "arg"); Assertions.assertTrue(!response.isSuccess()); //添加redis中规则 addXMLData(); //重新加载规则 - Thread.sleep(5000); - Assertions.assertEquals("b==>c", flowExecutor.execute2Resp("chain4", "arg").getExecuteStepStr()); + Thread.sleep(1000); + Assertions.assertEquals("b==>c", flowExecutor.execute2Resp("chain44", "arg").getExecuteStepStr()); + } + + @Test + public void testPollWithScriptXml() throws InterruptedException { + LiteflowResponse response = flowExecutor.execute2Resp("chain33", "arg"); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertEquals("hello s11", context.getData("test11")); + Assertions.assertEquals("a==>b==>c==>s11[脚本s11]==>s22[脚本s22]", response.getExecuteStepStrWithoutTime()); + + //添加和删除脚本 + //重新加载脚本 定时任务1分钟后开始第一次轮询 所以这里休眠1分钟 + addAndDeleteScriptData(); + Thread.sleep(62000); + //修改redis脚本 + changeScriptData(); + Thread.sleep(1000); + context = flowExecutor.execute2Resp("chain33", "arg").getFirstContextBean(); + Assertions.assertEquals("hello s11 version2", context.getData("test11")); } @@ -88,7 +113,7 @@ public class RedisWithXmlELPollSpringbootTest { public void changeXMLData() { LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - jedis.hset(redisParserVO.getChainKey(), "chain1", "THEN(a, c, b);"); + jedis.hset(redisParserVO.getChainKey(), "chain11", "THEN(a, c, b);"); } /** @@ -97,8 +122,8 @@ public class RedisWithXmlELPollSpringbootTest { public void deleteXMLData() { LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - jedis.hdel(redisParserVO.getChainKey(), "chain1"); - jedis.hdel(redisParserVO.getChainKey(), "chain2"); + jedis.hdel(redisParserVO.getChainKey(), "chain11"); + jedis.hdel(redisParserVO.getChainKey(), "chain22"); } @@ -108,7 +133,8 @@ public class RedisWithXmlELPollSpringbootTest { public void addXMLData() { LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - jedis.hset(redisParserVO.getChainKey(), "chain4", "THEN(b, c);"); + jedis.hset(redisParserVO.getChainKey(), "chain33", "THEN(a, b, c, s11, s22);"); + jedis.hset(redisParserVO.getChainKey(), "chain44", "THEN(b, c);"); } /** @@ -117,6 +143,43 @@ public class RedisWithXmlELPollSpringbootTest { public void changeScriptData() { LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - jedis.hset(redisParserVO.getScriptKey(), "s1:script:脚本s1:groovy", "defaultContext.setData(\"test1\",\"hello s1 version2\");"); + jedis.hset(redisParserVO.getScriptKey(), "s11:script:脚本s11:groovy", "defaultContext.setData(\"test11\",\"hello s11 version2\");"); + } + + /** + * 新增和删除redisson中的chain + */ + public void addAndDeleteScriptData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + jedis.hdel(redisParserVO.getScriptKey(), "s33:script:脚本s33"); + jedis.hset(redisParserVO.getScriptKey(),"s55:script:脚本s55:groovy", "defaultContext.setData(\"test55\",\"hello s5\");"); + } + +/* //为便于测试的redis内规则数据数据清空 + @Test + public void testCleanData() { + Set scriptKey = jedis.hkeys("pollScriptKey"); + Set chainKey = jedis.hkeys("pollChainKey"); + for (String key : scriptKey) { + jedis.hdel("pollScriptKey", key); + } + for (String key : chainKey) { + jedis.hdel("pollChainKey", key); + } + jedis.hkeys("pollChainKey").forEach(System.out::println); + System.out.println(" "); + jedis.hkeys("pollScriptKey").forEach(System.out::println); + System.out.println("数据清空完成"); + }*/ + + @AfterAll + public static void cleanScanCache() { + ComponentScanner.cleanCache(); + FlowBus.cleanCache(); + ExecutorHelper.loadInstance().clearExecutorServiceMap(); + SpiFactoryCleaner.clean(); + LiteflowConfigGetter.clean(); + FlowInitHook.cleanHook(); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java index fbb6d9dd..b044f589 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java @@ -1,12 +1,18 @@ package com.yomahub.liteflow.test.redis; import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.core.FlowInitHook; +import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.flow.LiteflowResponse; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import com.yomahub.liteflow.property.LiteflowConfig; import com.yomahub.liteflow.property.LiteflowConfigGetter; import com.yomahub.liteflow.slot.DefaultContext; +import com.yomahub.liteflow.spi.holder.SpiFactoryCleaner; +import com.yomahub.liteflow.spring.ComponentScanner; +import com.yomahub.liteflow.thread.ExecutorHelper; import com.yomahub.liteflow.util.JsonUtil; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -98,6 +104,8 @@ public class RedisWithXmlELSubscribeSpringbootTest { Thread.sleep(50); context = flowExecutor.execute2Resp("chain3", "arg").getFirstContextBean(); Assertions.assertEquals("hello s1 version2", context.getData("test1")); + context = flowExecutor.execute2Resp("chain2", "arg").getFirstContextBean(); + Assertions.assertEquals("hello s3 version2", context.getData("test2")); } /** @@ -139,6 +147,7 @@ public class RedisWithXmlELSubscribeSpringbootTest { RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); RMapCache scriptKey = redissonClient.getMapCache(redisParserVO.getScriptKey()); scriptKey.put("s1:script:脚本s1:groovy", "defaultContext.setData(\"test1\",\"hello s1 version2\");"); + scriptKey.put("s3:script:脚本s3", "defaultContext.setData(\"test2\",\"hello s3 version2\");"); } /** @@ -148,8 +157,36 @@ public class RedisWithXmlELSubscribeSpringbootTest { LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); RMapCache scriptKey = redissonClient.getMapCache(redisParserVO.getScriptKey()); - scriptKey.remove("s4:script:脚本s4"); - scriptKey.remove("s5:script:脚本s5:groovy"); + scriptKey.remove("s3:script:脚本s3"); scriptKey.put("s5:script:脚本s5:groovy", "defaultContext.setData(\"test1\",\"hello s5\");"); } + +/* //为便于测试的redis内规则数据数据清空 + @Test + public void testCleanData(){ + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + RMapCache scriptKey = redissonClient.getMapCache(redisParserVO.getScriptKey()); + RMapCache chainKey = redissonClient.getMapCache(redisParserVO.getChainKey()); + for (String key : chainKey.keySet()) { + chainKey.remove(key); + } + for (String key : scriptKey.keySet()) { + scriptKey.remove(key); + } + chainKey.keySet().forEach(System.out::println); + System.out.println(""); + scriptKey.keySet().forEach(System.out::println); + System.out.println("数据清空完成"); + }*/ + + @AfterAll + public static void cleanScanCache() { + ComponentScanner.cleanCache(); + FlowBus.cleanCache(); + ExecutorHelper.loadInstance().clearExecutorServiceMap(); + SpiFactoryCleaner.clean(); + LiteflowConfigGetter.clean(); + FlowInitHook.cleanHook(); + } } From 9e9bfb6822b46086a90abf109c7d56d91b71c99f Mon Sep 17 00:00:00 2001 From: houxinyu Date: Tue, 25 Jul 2023 15:51:40 +0800 Subject: [PATCH 27/41] test mode --- .../src/test/resources/redis/application-sub-xml.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-sub-xml.properties b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-sub-xml.properties index 9bbce2e2..22a58eed 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-sub-xml.properties +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-sub-xml.properties @@ -1,7 +1,7 @@ liteflow.rule-source-ext-data={\ "host":"localhost",\ "port":6379,\ - "mode":"SUB",\ + "mode":"sub",\ "chainDataBase":1,\ "chainKey":"chainKey",\ "scriptDataBase":1,\ From 014393ed35fff756cd8f393dd943b97c84d84eec Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sat, 12 Aug 2023 15:13:17 +0800 Subject: [PATCH 28/41] temp --- .../RedisWithXmlELPollSpringbootTest.java | 14 +- .../RedisWithXmlELPollSpringbootTest2.java | 180 ++++++++++++++++ ...RedisWithXmlELSubscribeSpringbootTest.java | 13 +- ...edisWithXmlELSubscribeSpringbootTest2.java | 192 ++++++++++++++++++ liteflow-testcase-el/pom.xml | 1 + 5 files changed, 377 insertions(+), 23 deletions(-) create mode 100644 liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest2.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest2.java diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java index f9ed44ce..94a851a0 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java @@ -10,6 +10,7 @@ import com.yomahub.liteflow.property.LiteflowConfigGetter; import com.yomahub.liteflow.slot.DefaultContext; import com.yomahub.liteflow.spi.holder.SpiFactoryCleaner; import com.yomahub.liteflow.spring.ComponentScanner; +import com.yomahub.liteflow.test.BaseTest; import com.yomahub.liteflow.thread.ExecutorHelper; import com.yomahub.liteflow.util.JsonUtil; import org.junit.jupiter.api.AfterAll; @@ -37,7 +38,7 @@ import javax.annotation.Resource; @SpringBootTest(classes = RedisWithXmlELPollSpringbootTest.class) @EnableAutoConfiguration @ComponentScan({"com.yomahub.liteflow.test.redis.cmp"}) -public class RedisWithXmlELPollSpringbootTest { +public class RedisWithXmlELPollSpringbootTest extends BaseTest { private static Jedis jedis; @@ -79,7 +80,6 @@ public class RedisWithXmlELPollSpringbootTest { response = flowExecutor.execute2Resp("chain22", "arg"); Assertions.assertTrue(!response.isSuccess()); - //添加redis中规则 addXMLData(); //重新加载规则 @@ -172,14 +172,4 @@ public class RedisWithXmlELPollSpringbootTest { jedis.hkeys("pollScriptKey").forEach(System.out::println); System.out.println("数据清空完成"); }*/ - - @AfterAll - public static void cleanScanCache() { - ComponentScanner.cleanCache(); - FlowBus.cleanCache(); - ExecutorHelper.loadInstance().clearExecutorServiceMap(); - SpiFactoryCleaner.clean(); - LiteflowConfigGetter.clean(); - FlowInitHook.cleanHook(); - } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest2.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest2.java new file mode 100644 index 00000000..2940c395 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest2.java @@ -0,0 +1,180 @@ +package com.yomahub.liteflow.test.redis; + +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.property.LiteflowConfigGetter; +import com.yomahub.liteflow.slot.DefaultContext; +import com.yomahub.liteflow.test.BaseTest; +import com.yomahub.liteflow.util.JsonUtil; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.MockitoAnnotations; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import redis.clients.jedis.Jedis; + +import javax.annotation.Resource; + +/** + * springboot环境下的redis配置源轮询拉取模式功能测试 + * + * @author hxinyu + * @since 2.11.0 + */ +@ExtendWith(SpringExtension.class) +@TestPropertySource(value = "classpath:/redis/application-poll-xml.properties") +@SpringBootTest(classes = RedisWithXmlELPollSpringbootTest2.class) +@EnableAutoConfiguration +@ComponentScan({"com.yomahub.liteflow.test.redis.cmp"}) +public class RedisWithXmlELPollSpringbootTest2 extends BaseTest { + + @MockBean(name = "chainJedis") + private static Jedis chainJedis; + + @MockBean(name = "scriptJedis") + private static Jedis scriptJedis; + + @Resource + private FlowExecutor flowExecutor; + + @BeforeEach + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @BeforeAll + public static void setUpBeforeClass() { + + jedis.hset("pollScriptKey", "s11:script:脚本s11:groovy", "defaultContext.setData(\"test11\",\"hello s11\");"); + jedis.hset("pollScriptKey", "s22:script:脚本s22:js", "defaultContext.setData(\"test22\",\"hello s22\");"); + jedis.hset("pollScriptKey", "s33:script:脚本s33", "defaultContext.setData(\"test33\",\"hello s33\");"); + + jedis.hset("pollChainKey", "chain11", "THEN(a, b, c);"); + jedis.hset("pollChainKey", "chain22", "THEN(a, b, c, s33);"); + jedis.hset("pollChainKey", "chain33", "THEN(a, b, c, s11, s22);"); + } + + @Test + public void testPollWithXml() throws InterruptedException { + LiteflowResponse response = flowExecutor.execute2Resp("chain11", "arg"); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertEquals("a==>b==>c", response.getExecuteStepStr()); + + + //修改redis中规则 + changeXMLData(); + //重新加载规则 定时任务1分钟后开始第一次轮询 所以这里休眠1分钟 + Thread.sleep(65000); + Assertions.assertEquals("a==>c==>b", flowExecutor.execute2Resp("chain11", "arg").getExecuteStepStr()); + + //删除redis中规则 + deleteXMLData(); + //重新加载规则 + Thread.sleep(1000); + response = flowExecutor.execute2Resp("chain11", "arg"); + Assertions.assertTrue(!response.isSuccess()); + response = flowExecutor.execute2Resp("chain22", "arg"); + Assertions.assertTrue(!response.isSuccess()); + + //添加redis中规则 + addXMLData(); + //重新加载规则 + Thread.sleep(1000); + Assertions.assertEquals("b==>c", flowExecutor.execute2Resp("chain44", "arg").getExecuteStepStr()); + } + + @Test + public void testPollWithScriptXml() throws InterruptedException { + LiteflowResponse response = flowExecutor.execute2Resp("chain33", "arg"); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertEquals("hello s11", context.getData("test11")); + Assertions.assertEquals("a==>b==>c==>s11[脚本s11]==>s22[脚本s22]", response.getExecuteStepStrWithoutTime()); + + //添加和删除脚本 + //重新加载脚本 定时任务1分钟后开始第一次轮询 所以这里休眠1分钟 + addAndDeleteScriptData(); + Thread.sleep(62000); + //修改redis脚本 + changeScriptData(); + Thread.sleep(1000); + context = flowExecutor.execute2Resp("chain33", "arg").getFirstContextBean(); + Assertions.assertEquals("hello s11 version2", context.getData("test11")); + } + + + /** + * 修改redisson中的chain + */ + public void changeXMLData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + jedis.hset(redisParserVO.getChainKey(), "chain11", "THEN(a, c, b);"); + } + + /** + * 删除redisson中的chain + */ + public void deleteXMLData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + jedis.hdel(redisParserVO.getChainKey(), "chain11"); + jedis.hdel(redisParserVO.getChainKey(), "chain22"); + } + + + /** + * 新增redisson中的chain + */ + public void addXMLData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + jedis.hset(redisParserVO.getChainKey(), "chain33", "THEN(a, b, c, s11, s22);"); + jedis.hset(redisParserVO.getChainKey(), "chain44", "THEN(b, c);"); + } + + /** + * 修改redisson中的脚本 + */ + public void changeScriptData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + jedis.hset(redisParserVO.getScriptKey(), "s11:script:脚本s11:groovy", "defaultContext.setData(\"test11\",\"hello s11 version2\");"); + } + + /** + * 新增和删除redisson中的chain + */ + public void addAndDeleteScriptData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + jedis.hdel(redisParserVO.getScriptKey(), "s33:script:脚本s33"); + jedis.hset(redisParserVO.getScriptKey(),"s55:script:脚本s55:groovy", "defaultContext.setData(\"test55\",\"hello s5\");"); + } + +/* //为便于测试的redis内规则数据数据清空 + @Test + public void testCleanData() { + Set scriptKey = jedis.hkeys("pollScriptKey"); + Set chainKey = jedis.hkeys("pollChainKey"); + for (String key : scriptKey) { + jedis.hdel("pollScriptKey", key); + } + for (String key : chainKey) { + jedis.hdel("pollChainKey", key); + } + jedis.hkeys("pollChainKey").forEach(System.out::println); + System.out.println(" "); + jedis.hkeys("pollScriptKey").forEach(System.out::println); + System.out.println("数据清空完成"); + }*/ +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java index b044f589..19ed1092 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java @@ -10,6 +10,7 @@ import com.yomahub.liteflow.property.LiteflowConfigGetter; import com.yomahub.liteflow.slot.DefaultContext; import com.yomahub.liteflow.spi.holder.SpiFactoryCleaner; import com.yomahub.liteflow.spring.ComponentScanner; +import com.yomahub.liteflow.test.BaseTest; import com.yomahub.liteflow.thread.ExecutorHelper; import com.yomahub.liteflow.util.JsonUtil; import org.junit.jupiter.api.AfterAll; @@ -41,7 +42,7 @@ import java.util.Set; @SpringBootTest(classes = RedisWithXmlELSubscribeSpringbootTest.class) @EnableAutoConfiguration @ComponentScan({"com.yomahub.liteflow.test.redis.cmp"}) -public class RedisWithXmlELSubscribeSpringbootTest { +public class RedisWithXmlELSubscribeSpringbootTest extends BaseTest { private static RedissonClient redissonClient; @@ -179,14 +180,4 @@ public class RedisWithXmlELSubscribeSpringbootTest { scriptKey.keySet().forEach(System.out::println); System.out.println("数据清空完成"); }*/ - - @AfterAll - public static void cleanScanCache() { - ComponentScanner.cleanCache(); - FlowBus.cleanCache(); - ExecutorHelper.loadInstance().clearExecutorServiceMap(); - SpiFactoryCleaner.clean(); - LiteflowConfigGetter.clean(); - FlowInitHook.cleanHook(); - } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest2.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest2.java new file mode 100644 index 00000000..637112a1 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest2.java @@ -0,0 +1,192 @@ +package com.yomahub.liteflow.test.redis; + +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.property.LiteflowConfigGetter; +import com.yomahub.liteflow.slot.DefaultContext; +import com.yomahub.liteflow.test.BaseTest; +import com.yomahub.liteflow.util.JsonUtil; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.MockitoAnnotations; +import org.redisson.Redisson; +import org.redisson.RedissonMapCache; +import org.redisson.api.RMapCache; +import org.redisson.api.RedissonClient; +import org.redisson.config.Config; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import javax.annotation.Resource; + +/** + * springboot环境下的redis配置源订阅模式功能测试 + * + * @author hxinyu + * @since 2.11.0 + */ +@ExtendWith(SpringExtension.class) +@TestPropertySource(value = "classpath:/redis/application-sub-xml.properties") +@SpringBootTest(classes = RedisWithXmlELSubscribeSpringbootTest2.class) +@EnableAutoConfiguration +@ComponentScan({"com.yomahub.liteflow.test.redis.cmp"}) +public class RedisWithXmlELSubscribeSpringbootTest2 extends BaseTest { + + @MockBean(name = "chainClient") + private static RedissonClient chainClient; + + @MockBean(name = "scriptClient") + private static RedissonClient scriptClient; + + @Resource + private FlowExecutor flowExecutor; + + @BeforeEach + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @BeforeAll + public static void setUpBeforeClass() { + RMapCache chainKey; + chainKey.put("chain1", "THEN(a, b, c);"); + chainKey.put("chain2", "THEN(a, b, c, s3);"); + chainKey.put("chain3", "THEN(a, b, c, s1, s2);"); + + + // RMapCache chainKey = redissonClient.getMapCache("chainKey"); + // RMapCache scriptKey = redissonClient.getMapCache("scriptKey"); +/* scriptKey.put("s1:script:脚本s1:groovy", "defaultContext.setData(\"test1\",\"hello s1\");"); + scriptKey.put("s2:script:脚本s2:js", "defaultContext.setData(\"test2\",\"hello s2\");"); + scriptKey.put("s3:script:脚本s3", "defaultContext.setData(\"test3\",\"hello s3\");"); + chainKey.put("chain1", "THEN(a, b, c);"); + chainKey.put("chain2", "THEN(a, b, c, s3);"); + chainKey.put("chain3", "THEN(a, b, c, s1, s2);");*/ + } + + @Test + public void testSubWithXml() throws InterruptedException { + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertEquals("a==>b==>c", response.getExecuteStepStr()); + + /* //修改redis中规则 + changeXMLData(); + //重新加载规则 + Thread.sleep(50); + Assertions.assertEquals("a==>c==>b", flowExecutor.execute2Resp("chain1", "arg").getExecuteStepStr()); + + //删除redis中规则 + deleteXMLData(); + //重新加载规则 + Thread.sleep(50); + response = flowExecutor.execute2Resp("chain1", "arg"); + Assertions.assertTrue(!response.isSuccess()); + + //添加redis中规则 + addXMLData(); + //重新加载规则 + Thread.sleep(50); + Assertions.assertEquals("b==>c", flowExecutor.execute2Resp("chain4", "arg").getExecuteStepStr());*/ + } + + @Test + public void testSubWithScriptXml() throws InterruptedException { + LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg"); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertEquals("hello s1", context.getData("test1")); + Assertions.assertEquals("a==>b==>c==>s1[脚本s1]==>s2[脚本s2]", response.getExecuteStepStrWithoutTime()); + +/* //添加和删除脚本 + addAndDeleteScriptData(); + //修改redis脚本 + changeScriptData();*/ + Thread.sleep(50); + context = flowExecutor.execute2Resp("chain3", "arg").getFirstContextBean(); + Assertions.assertEquals("hello s1 version2", context.getData("test1")); + context = flowExecutor.execute2Resp("chain2", "arg").getFirstContextBean(); + Assertions.assertEquals("hello s3 version2", context.getData("test2")); + } + +/* *//** + * 修改redisson中的chain + *//* + public void changeXMLData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + RMapCache chainKey = redissonClient.getMapCache(redisParserVO.getChainKey()); + chainKey.put("chain1", "THEN(a, c, b);"); + } + + *//** + * 删除redisson中的chain + *//* + public void deleteXMLData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + RMapCache chainKey = redissonClient.getMapCache(redisParserVO.getChainKey()); + chainKey.remove("chain1"); + chainKey.remove("chain4"); + } + + *//** + * 新增redisson中的chain + *//* + public void addXMLData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + RMapCache chainKey = redissonClient.getMapCache(redisParserVO.getChainKey()); + chainKey.put("chain4","THEN(b, c);"); + } + + *//** + * 修改redisson中的脚本 + *//* + public void changeScriptData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + RMapCache scriptKey = redissonClient.getMapCache(redisParserVO.getScriptKey()); + scriptKey.put("s1:script:脚本s1:groovy", "defaultContext.setData(\"test1\",\"hello s1 version2\");"); + scriptKey.put("s3:script:脚本s3", "defaultContext.setData(\"test2\",\"hello s3 version2\");"); + } + + *//** + * 新增和删除redisson中的chain + *//* + public void addAndDeleteScriptData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + RMapCache scriptKey = redissonClient.getMapCache(redisParserVO.getScriptKey()); + scriptKey.remove("s3:script:脚本s3"); + scriptKey.put("s5:script:脚本s5:groovy", "defaultContext.setData(\"test1\",\"hello s5\");"); + }*/ + +/* //为便于测试的redis内规则数据数据清空 + @Test + public void testCleanData(){ + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + RMapCache scriptKey = redissonClient.getMapCache(redisParserVO.getScriptKey()); + RMapCache chainKey = redissonClient.getMapCache(redisParserVO.getChainKey()); + for (String key : chainKey.keySet()) { + chainKey.remove(key); + } + for (String key : scriptKey.keySet()) { + scriptKey.remove(key); + } + chainKey.keySet().forEach(System.out::println); + System.out.println(""); + scriptKey.keySet().forEach(System.out::println); + System.out.println("数据清空完成"); + }*/ +} diff --git a/liteflow-testcase-el/pom.xml b/liteflow-testcase-el/pom.xml index 8f23e9e9..e824294a 100644 --- a/liteflow-testcase-el/pom.xml +++ b/liteflow-testcase-el/pom.xml @@ -30,6 +30,7 @@ liteflow-testcase-el-nacos-springboot liteflow-testcase-el-etcd-springboot liteflow-testcase-el-apollo-springboot + liteflow-testcase-el-redis-springboot liteflow-testcase-el-script-python-springboot liteflow-testcase-el-script-lua-springboot liteflow-testcase-el-script-multi-language-springboot From 45848fbe48c8053d6bd89965076573b9e8c7d57e Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sat, 12 Aug 2023 16:01:32 +0800 Subject: [PATCH 29/41] fix test --- .../RedisWithXmlELPollSpringbootTest2.java | 167 +++++---------- ...edisWithXmlELSubscribeSpringbootTest2.java | 192 ------------------ 2 files changed, 46 insertions(+), 313 deletions(-) delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest2.java diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest2.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest2.java index 2940c395..d0156090 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest2.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest2.java @@ -1,17 +1,12 @@ package com.yomahub.liteflow.test.redis; import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.flow.LiteflowResponse; -import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; -import com.yomahub.liteflow.property.LiteflowConfig; -import com.yomahub.liteflow.property.LiteflowConfigGetter; import com.yomahub.liteflow.slot.DefaultContext; import com.yomahub.liteflow.test.BaseTest; -import com.yomahub.liteflow.util.JsonUtil; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; +import org.assertj.core.util.Sets; +import org.junit.jupiter.api.*; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.MockitoAnnotations; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; @@ -23,6 +18,11 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import redis.clients.jedis.Jedis; import javax.annotation.Resource; +import java.util.HashSet; +import java.util.Set; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; /** * springboot环境下的redis配置源轮询拉取模式功能测试 @@ -51,130 +51,55 @@ public class RedisWithXmlELPollSpringbootTest2 extends BaseTest { MockitoAnnotations.initMocks(this); } - @BeforeAll - public static void setUpBeforeClass() { - - jedis.hset("pollScriptKey", "s11:script:脚本s11:groovy", "defaultContext.setData(\"test11\",\"hello s11\");"); - jedis.hset("pollScriptKey", "s22:script:脚本s22:js", "defaultContext.setData(\"test22\",\"hello s22\");"); - jedis.hset("pollScriptKey", "s33:script:脚本s33", "defaultContext.setData(\"test33\",\"hello s33\");"); - - jedis.hset("pollChainKey", "chain11", "THEN(a, b, c);"); - jedis.hset("pollChainKey", "chain22", "THEN(a, b, c, s33);"); - jedis.hset("pollChainKey", "chain33", "THEN(a, b, c, s11, s22);"); + @AfterEach + public void after() { + FlowBus.cleanCache(); } + /** + * 测试chain + */ @Test - public void testPollWithXml() throws InterruptedException { + public void testPollWithXml() { + Set chainNameSet = new HashSet<>(); + chainNameSet.add("chain11"); + String chainValue = "THEN(a, b, c);"; + when(chainJedis.hkeys("pollChainKey")).thenReturn(chainNameSet); + when(chainJedis.hget("pollChainKey", "chain11")).thenReturn(chainValue); + LiteflowResponse response = flowExecutor.execute2Resp("chain11", "arg"); Assertions.assertTrue(response.isSuccess()); Assertions.assertEquals("a==>b==>c", response.getExecuteStepStr()); - - - //修改redis中规则 - changeXMLData(); - //重新加载规则 定时任务1分钟后开始第一次轮询 所以这里休眠1分钟 - Thread.sleep(65000); - Assertions.assertEquals("a==>c==>b", flowExecutor.execute2Resp("chain11", "arg").getExecuteStepStr()); - - //删除redis中规则 - deleteXMLData(); - //重新加载规则 - Thread.sleep(1000); - response = flowExecutor.execute2Resp("chain11", "arg"); - Assertions.assertTrue(!response.isSuccess()); - response = flowExecutor.execute2Resp("chain22", "arg"); - Assertions.assertTrue(!response.isSuccess()); - - //添加redis中规则 - addXMLData(); - //重新加载规则 - Thread.sleep(1000); - Assertions.assertEquals("b==>c", flowExecutor.execute2Resp("chain44", "arg").getExecuteStepStr()); } + /** + * 测试script + */ @Test - public void testPollWithScriptXml() throws InterruptedException { - LiteflowResponse response = flowExecutor.execute2Resp("chain33", "arg"); + public void testPollWithScriptXml() { + Set chainNameSet = new HashSet<>(); + chainNameSet.add("chain22"); + String chainValue = "THEN(a, b, c, s11, s22, s33);"; + when(chainJedis.hkeys("pollChainKey")).thenReturn(chainNameSet); + when(chainJedis.hget("pollChainKey", "chain22")).thenReturn(chainValue); + + Set scriptFieldSet = new HashSet<>(); + scriptFieldSet.add("s11:script:脚本s11:groovy"); + scriptFieldSet.add("s22:script:脚本s22:js"); + scriptFieldSet.add("s33:script:脚本s33"); + String s11 = "defaultContext.setData(\"test11\",\"hello s11\");"; + String s22 = "defaultContext.setData(\"test22\",\"hello s22\");"; + String s33 = "defaultContext.setData(\"test33\",\"hello s33\");"; + + when(scriptJedis.hkeys("pollScriptKey")).thenReturn(scriptFieldSet); + when(scriptJedis.hget("pollScriptKey", "s11:script:脚本s11:groovy")).thenReturn(s11); + when(scriptJedis.hget("pollScriptKey", "s22:script:脚本s22:js")).thenReturn(s22); + when(scriptJedis.hget("pollScriptKey", "s33:script:脚本s33")).thenReturn(s33); + + LiteflowResponse response = flowExecutor.execute2Resp("chain22", "arg"); DefaultContext context = response.getFirstContextBean(); Assertions.assertTrue(response.isSuccess()); Assertions.assertEquals("hello s11", context.getData("test11")); - Assertions.assertEquals("a==>b==>c==>s11[脚本s11]==>s22[脚本s22]", response.getExecuteStepStrWithoutTime()); - - //添加和删除脚本 - //重新加载脚本 定时任务1分钟后开始第一次轮询 所以这里休眠1分钟 - addAndDeleteScriptData(); - Thread.sleep(62000); - //修改redis脚本 - changeScriptData(); - Thread.sleep(1000); - context = flowExecutor.execute2Resp("chain33", "arg").getFirstContextBean(); - Assertions.assertEquals("hello s11 version2", context.getData("test11")); + Assertions.assertEquals("a==>b==>c==>s11[脚本s11]==>s22[脚本s22]==>s33[脚本s33]", response.getExecuteStepStrWithoutTime()); } - - - /** - * 修改redisson中的chain - */ - public void changeXMLData() { - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - jedis.hset(redisParserVO.getChainKey(), "chain11", "THEN(a, c, b);"); - } - - /** - * 删除redisson中的chain - */ - public void deleteXMLData() { - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - jedis.hdel(redisParserVO.getChainKey(), "chain11"); - jedis.hdel(redisParserVO.getChainKey(), "chain22"); - } - - - /** - * 新增redisson中的chain - */ - public void addXMLData() { - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - jedis.hset(redisParserVO.getChainKey(), "chain33", "THEN(a, b, c, s11, s22);"); - jedis.hset(redisParserVO.getChainKey(), "chain44", "THEN(b, c);"); - } - - /** - * 修改redisson中的脚本 - */ - public void changeScriptData() { - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - jedis.hset(redisParserVO.getScriptKey(), "s11:script:脚本s11:groovy", "defaultContext.setData(\"test11\",\"hello s11 version2\");"); - } - - /** - * 新增和删除redisson中的chain - */ - public void addAndDeleteScriptData() { - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - jedis.hdel(redisParserVO.getScriptKey(), "s33:script:脚本s33"); - jedis.hset(redisParserVO.getScriptKey(),"s55:script:脚本s55:groovy", "defaultContext.setData(\"test55\",\"hello s5\");"); - } - -/* //为便于测试的redis内规则数据数据清空 - @Test - public void testCleanData() { - Set scriptKey = jedis.hkeys("pollScriptKey"); - Set chainKey = jedis.hkeys("pollChainKey"); - for (String key : scriptKey) { - jedis.hdel("pollScriptKey", key); - } - for (String key : chainKey) { - jedis.hdel("pollChainKey", key); - } - jedis.hkeys("pollChainKey").forEach(System.out::println); - System.out.println(" "); - jedis.hkeys("pollScriptKey").forEach(System.out::println); - System.out.println("数据清空完成"); - }*/ } diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest2.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest2.java deleted file mode 100644 index 637112a1..00000000 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest2.java +++ /dev/null @@ -1,192 +0,0 @@ -package com.yomahub.liteflow.test.redis; - -import com.yomahub.liteflow.core.FlowExecutor; -import com.yomahub.liteflow.flow.LiteflowResponse; -import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; -import com.yomahub.liteflow.property.LiteflowConfig; -import com.yomahub.liteflow.property.LiteflowConfigGetter; -import com.yomahub.liteflow.slot.DefaultContext; -import com.yomahub.liteflow.test.BaseTest; -import com.yomahub.liteflow.util.JsonUtil; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.MockitoAnnotations; -import org.redisson.Redisson; -import org.redisson.RedissonMapCache; -import org.redisson.api.RMapCache; -import org.redisson.api.RedissonClient; -import org.redisson.config.Config; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; - -import javax.annotation.Resource; - -/** - * springboot环境下的redis配置源订阅模式功能测试 - * - * @author hxinyu - * @since 2.11.0 - */ -@ExtendWith(SpringExtension.class) -@TestPropertySource(value = "classpath:/redis/application-sub-xml.properties") -@SpringBootTest(classes = RedisWithXmlELSubscribeSpringbootTest2.class) -@EnableAutoConfiguration -@ComponentScan({"com.yomahub.liteflow.test.redis.cmp"}) -public class RedisWithXmlELSubscribeSpringbootTest2 extends BaseTest { - - @MockBean(name = "chainClient") - private static RedissonClient chainClient; - - @MockBean(name = "scriptClient") - private static RedissonClient scriptClient; - - @Resource - private FlowExecutor flowExecutor; - - @BeforeEach - public void setUp() { - MockitoAnnotations.initMocks(this); - } - - @BeforeAll - public static void setUpBeforeClass() { - RMapCache chainKey; - chainKey.put("chain1", "THEN(a, b, c);"); - chainKey.put("chain2", "THEN(a, b, c, s3);"); - chainKey.put("chain3", "THEN(a, b, c, s1, s2);"); - - - // RMapCache chainKey = redissonClient.getMapCache("chainKey"); - // RMapCache scriptKey = redissonClient.getMapCache("scriptKey"); -/* scriptKey.put("s1:script:脚本s1:groovy", "defaultContext.setData(\"test1\",\"hello s1\");"); - scriptKey.put("s2:script:脚本s2:js", "defaultContext.setData(\"test2\",\"hello s2\");"); - scriptKey.put("s3:script:脚本s3", "defaultContext.setData(\"test3\",\"hello s3\");"); - chainKey.put("chain1", "THEN(a, b, c);"); - chainKey.put("chain2", "THEN(a, b, c, s3);"); - chainKey.put("chain3", "THEN(a, b, c, s1, s2);");*/ - } - - @Test - public void testSubWithXml() throws InterruptedException { - LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); - Assertions.assertTrue(response.isSuccess()); - Assertions.assertEquals("a==>b==>c", response.getExecuteStepStr()); - - /* //修改redis中规则 - changeXMLData(); - //重新加载规则 - Thread.sleep(50); - Assertions.assertEquals("a==>c==>b", flowExecutor.execute2Resp("chain1", "arg").getExecuteStepStr()); - - //删除redis中规则 - deleteXMLData(); - //重新加载规则 - Thread.sleep(50); - response = flowExecutor.execute2Resp("chain1", "arg"); - Assertions.assertTrue(!response.isSuccess()); - - //添加redis中规则 - addXMLData(); - //重新加载规则 - Thread.sleep(50); - Assertions.assertEquals("b==>c", flowExecutor.execute2Resp("chain4", "arg").getExecuteStepStr());*/ - } - - @Test - public void testSubWithScriptXml() throws InterruptedException { - LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg"); - DefaultContext context = response.getFirstContextBean(); - Assertions.assertTrue(response.isSuccess()); - Assertions.assertEquals("hello s1", context.getData("test1")); - Assertions.assertEquals("a==>b==>c==>s1[脚本s1]==>s2[脚本s2]", response.getExecuteStepStrWithoutTime()); - -/* //添加和删除脚本 - addAndDeleteScriptData(); - //修改redis脚本 - changeScriptData();*/ - Thread.sleep(50); - context = flowExecutor.execute2Resp("chain3", "arg").getFirstContextBean(); - Assertions.assertEquals("hello s1 version2", context.getData("test1")); - context = flowExecutor.execute2Resp("chain2", "arg").getFirstContextBean(); - Assertions.assertEquals("hello s3 version2", context.getData("test2")); - } - -/* *//** - * 修改redisson中的chain - *//* - public void changeXMLData() { - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - RMapCache chainKey = redissonClient.getMapCache(redisParserVO.getChainKey()); - chainKey.put("chain1", "THEN(a, c, b);"); - } - - *//** - * 删除redisson中的chain - *//* - public void deleteXMLData() { - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - RMapCache chainKey = redissonClient.getMapCache(redisParserVO.getChainKey()); - chainKey.remove("chain1"); - chainKey.remove("chain4"); - } - - *//** - * 新增redisson中的chain - *//* - public void addXMLData() { - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - RMapCache chainKey = redissonClient.getMapCache(redisParserVO.getChainKey()); - chainKey.put("chain4","THEN(b, c);"); - } - - *//** - * 修改redisson中的脚本 - *//* - public void changeScriptData() { - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - RMapCache scriptKey = redissonClient.getMapCache(redisParserVO.getScriptKey()); - scriptKey.put("s1:script:脚本s1:groovy", "defaultContext.setData(\"test1\",\"hello s1 version2\");"); - scriptKey.put("s3:script:脚本s3", "defaultContext.setData(\"test2\",\"hello s3 version2\");"); - } - - *//** - * 新增和删除redisson中的chain - *//* - public void addAndDeleteScriptData() { - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - RMapCache scriptKey = redissonClient.getMapCache(redisParserVO.getScriptKey()); - scriptKey.remove("s3:script:脚本s3"); - scriptKey.put("s5:script:脚本s5:groovy", "defaultContext.setData(\"test1\",\"hello s5\");"); - }*/ - -/* //为便于测试的redis内规则数据数据清空 - @Test - public void testCleanData(){ - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - RMapCache scriptKey = redissonClient.getMapCache(redisParserVO.getScriptKey()); - RMapCache chainKey = redissonClient.getMapCache(redisParserVO.getChainKey()); - for (String key : chainKey.keySet()) { - chainKey.remove(key); - } - for (String key : scriptKey.keySet()) { - scriptKey.remove(key); - } - chainKey.keySet().forEach(System.out::println); - System.out.println(""); - scriptKey.keySet().forEach(System.out::println); - System.out.println("数据清空完成"); - }*/ -} From 008a58f247b65dba1b8a2e422370c921234de5dd Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sat, 12 Aug 2023 16:03:23 +0800 Subject: [PATCH 30/41] fix test --- .../RedisWithXmlELPollSpringbootTest.java | 182 ++++++------------ .../RedisWithXmlELPollSpringbootTest2.java | 105 ---------- 2 files changed, 55 insertions(+), 232 deletions(-) delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest2.java diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java index 94a851a0..20f7da8f 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java @@ -1,31 +1,26 @@ package com.yomahub.liteflow.test.redis; import com.yomahub.liteflow.core.FlowExecutor; -import com.yomahub.liteflow.core.FlowInitHook; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.flow.LiteflowResponse; -import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; -import com.yomahub.liteflow.property.LiteflowConfig; -import com.yomahub.liteflow.property.LiteflowConfigGetter; import com.yomahub.liteflow.slot.DefaultContext; -import com.yomahub.liteflow.spi.holder.SpiFactoryCleaner; -import com.yomahub.liteflow.spring.ComponentScanner; import com.yomahub.liteflow.test.BaseTest; -import com.yomahub.liteflow.thread.ExecutorHelper; -import com.yomahub.liteflow.util.JsonUtil; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.MockitoAnnotations; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.ComponentScan; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; import redis.clients.jedis.Jedis; import javax.annotation.Resource; +import java.util.HashSet; +import java.util.Set; + +import static org.mockito.Mockito.when; /** * springboot环境下的redis配置源轮询拉取模式功能测试 @@ -40,136 +35,69 @@ import javax.annotation.Resource; @ComponentScan({"com.yomahub.liteflow.test.redis.cmp"}) public class RedisWithXmlELPollSpringbootTest extends BaseTest { - private static Jedis jedis; + @MockBean(name = "chainJedis") + private static Jedis chainJedis; + + @MockBean(name = "scriptJedis") + private static Jedis scriptJedis; @Resource private FlowExecutor flowExecutor; - @BeforeAll - public static void setUpBeforeClass() { - jedis = new Jedis("localhost", 6379); - jedis.select(1); - jedis.hset("pollScriptKey", "s11:script:脚本s11:groovy", "defaultContext.setData(\"test11\",\"hello s11\");"); - jedis.hset("pollScriptKey", "s22:script:脚本s22:js", "defaultContext.setData(\"test22\",\"hello s22\");"); - jedis.hset("pollScriptKey", "s33:script:脚本s33", "defaultContext.setData(\"test33\",\"hello s33\");"); - - jedis.hset("pollChainKey", "chain11", "THEN(a, b, c);"); - jedis.hset("pollChainKey", "chain22", "THEN(a, b, c, s33);"); - jedis.hset("pollChainKey", "chain33", "THEN(a, b, c, s11, s22);"); + @BeforeEach + public void setUp() { + MockitoAnnotations.initMocks(this); } + @AfterEach + public void after() { + FlowBus.cleanCache(); + } + + /** + * 测试chain + */ @Test - public void testPollWithXml() throws InterruptedException { + public void testPollWithXml() { + Set chainNameSet = new HashSet<>(); + chainNameSet.add("chain11"); + String chainValue = "THEN(a, b, c);"; + when(chainJedis.hkeys("pollChainKey")).thenReturn(chainNameSet); + when(chainJedis.hget("pollChainKey", "chain11")).thenReturn(chainValue); + LiteflowResponse response = flowExecutor.execute2Resp("chain11", "arg"); Assertions.assertTrue(response.isSuccess()); Assertions.assertEquals("a==>b==>c", response.getExecuteStepStr()); - - - //修改redis中规则 - changeXMLData(); - //重新加载规则 定时任务1分钟后开始第一次轮询 所以这里休眠1分钟 - Thread.sleep(65000); - Assertions.assertEquals("a==>c==>b", flowExecutor.execute2Resp("chain11", "arg").getExecuteStepStr()); - - //删除redis中规则 - deleteXMLData(); - //重新加载规则 - Thread.sleep(1000); - response = flowExecutor.execute2Resp("chain11", "arg"); - Assertions.assertTrue(!response.isSuccess()); - response = flowExecutor.execute2Resp("chain22", "arg"); - Assertions.assertTrue(!response.isSuccess()); - - //添加redis中规则 - addXMLData(); - //重新加载规则 - Thread.sleep(1000); - Assertions.assertEquals("b==>c", flowExecutor.execute2Resp("chain44", "arg").getExecuteStepStr()); } + /** + * 测试script + */ @Test - public void testPollWithScriptXml() throws InterruptedException { - LiteflowResponse response = flowExecutor.execute2Resp("chain33", "arg"); + public void testPollWithScriptXml() { + Set chainNameSet = new HashSet<>(); + chainNameSet.add("chain22"); + String chainValue = "THEN(a, b, c, s11, s22, s33);"; + when(chainJedis.hkeys("pollChainKey")).thenReturn(chainNameSet); + when(chainJedis.hget("pollChainKey", "chain22")).thenReturn(chainValue); + + Set scriptFieldSet = new HashSet<>(); + scriptFieldSet.add("s11:script:脚本s11:groovy"); + scriptFieldSet.add("s22:script:脚本s22:js"); + scriptFieldSet.add("s33:script:脚本s33"); + String s11 = "defaultContext.setData(\"test11\",\"hello s11\");"; + String s22 = "defaultContext.setData(\"test22\",\"hello s22\");"; + String s33 = "defaultContext.setData(\"test33\",\"hello s33\");"; + + when(scriptJedis.hkeys("pollScriptKey")).thenReturn(scriptFieldSet); + when(scriptJedis.hget("pollScriptKey", "s11:script:脚本s11:groovy")).thenReturn(s11); + when(scriptJedis.hget("pollScriptKey", "s22:script:脚本s22:js")).thenReturn(s22); + when(scriptJedis.hget("pollScriptKey", "s33:script:脚本s33")).thenReturn(s33); + + LiteflowResponse response = flowExecutor.execute2Resp("chain22", "arg"); DefaultContext context = response.getFirstContextBean(); Assertions.assertTrue(response.isSuccess()); Assertions.assertEquals("hello s11", context.getData("test11")); - Assertions.assertEquals("a==>b==>c==>s11[脚本s11]==>s22[脚本s22]", response.getExecuteStepStrWithoutTime()); - - //添加和删除脚本 - //重新加载脚本 定时任务1分钟后开始第一次轮询 所以这里休眠1分钟 - addAndDeleteScriptData(); - Thread.sleep(62000); - //修改redis脚本 - changeScriptData(); - Thread.sleep(1000); - context = flowExecutor.execute2Resp("chain33", "arg").getFirstContextBean(); - Assertions.assertEquals("hello s11 version2", context.getData("test11")); + Assertions.assertEquals("a==>b==>c==>s11[脚本s11]==>s22[脚本s22]==>s33[脚本s33]", response.getExecuteStepStrWithoutTime()); } - - - /** - * 修改redisson中的chain - */ - public void changeXMLData() { - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - jedis.hset(redisParserVO.getChainKey(), "chain11", "THEN(a, c, b);"); - } - - /** - * 删除redisson中的chain - */ - public void deleteXMLData() { - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - jedis.hdel(redisParserVO.getChainKey(), "chain11"); - jedis.hdel(redisParserVO.getChainKey(), "chain22"); - } - - - /** - * 新增redisson中的chain - */ - public void addXMLData() { - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - jedis.hset(redisParserVO.getChainKey(), "chain33", "THEN(a, b, c, s11, s22);"); - jedis.hset(redisParserVO.getChainKey(), "chain44", "THEN(b, c);"); - } - - /** - * 修改redisson中的脚本 - */ - public void changeScriptData() { - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - jedis.hset(redisParserVO.getScriptKey(), "s11:script:脚本s11:groovy", "defaultContext.setData(\"test11\",\"hello s11 version2\");"); - } - - /** - * 新增和删除redisson中的chain - */ - public void addAndDeleteScriptData() { - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - jedis.hdel(redisParserVO.getScriptKey(), "s33:script:脚本s33"); - jedis.hset(redisParserVO.getScriptKey(),"s55:script:脚本s55:groovy", "defaultContext.setData(\"test55\",\"hello s5\");"); - } - -/* //为便于测试的redis内规则数据数据清空 - @Test - public void testCleanData() { - Set scriptKey = jedis.hkeys("pollScriptKey"); - Set chainKey = jedis.hkeys("pollChainKey"); - for (String key : scriptKey) { - jedis.hdel("pollScriptKey", key); - } - for (String key : chainKey) { - jedis.hdel("pollChainKey", key); - } - jedis.hkeys("pollChainKey").forEach(System.out::println); - System.out.println(" "); - jedis.hkeys("pollScriptKey").forEach(System.out::println); - System.out.println("数据清空完成"); - }*/ } diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest2.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest2.java deleted file mode 100644 index d0156090..00000000 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest2.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.yomahub.liteflow.test.redis; - -import com.yomahub.liteflow.core.FlowExecutor; -import com.yomahub.liteflow.flow.FlowBus; -import com.yomahub.liteflow.flow.LiteflowResponse; -import com.yomahub.liteflow.slot.DefaultContext; -import com.yomahub.liteflow.test.BaseTest; -import org.assertj.core.util.Sets; -import org.junit.jupiter.api.*; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.MockitoAnnotations; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; -import redis.clients.jedis.Jedis; - -import javax.annotation.Resource; -import java.util.HashSet; -import java.util.Set; - -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.when; - -/** - * springboot环境下的redis配置源轮询拉取模式功能测试 - * - * @author hxinyu - * @since 2.11.0 - */ -@ExtendWith(SpringExtension.class) -@TestPropertySource(value = "classpath:/redis/application-poll-xml.properties") -@SpringBootTest(classes = RedisWithXmlELPollSpringbootTest2.class) -@EnableAutoConfiguration -@ComponentScan({"com.yomahub.liteflow.test.redis.cmp"}) -public class RedisWithXmlELPollSpringbootTest2 extends BaseTest { - - @MockBean(name = "chainJedis") - private static Jedis chainJedis; - - @MockBean(name = "scriptJedis") - private static Jedis scriptJedis; - - @Resource - private FlowExecutor flowExecutor; - - @BeforeEach - public void setUp() { - MockitoAnnotations.initMocks(this); - } - - @AfterEach - public void after() { - FlowBus.cleanCache(); - } - - /** - * 测试chain - */ - @Test - public void testPollWithXml() { - Set chainNameSet = new HashSet<>(); - chainNameSet.add("chain11"); - String chainValue = "THEN(a, b, c);"; - when(chainJedis.hkeys("pollChainKey")).thenReturn(chainNameSet); - when(chainJedis.hget("pollChainKey", "chain11")).thenReturn(chainValue); - - LiteflowResponse response = flowExecutor.execute2Resp("chain11", "arg"); - Assertions.assertTrue(response.isSuccess()); - Assertions.assertEquals("a==>b==>c", response.getExecuteStepStr()); - } - - /** - * 测试script - */ - @Test - public void testPollWithScriptXml() { - Set chainNameSet = new HashSet<>(); - chainNameSet.add("chain22"); - String chainValue = "THEN(a, b, c, s11, s22, s33);"; - when(chainJedis.hkeys("pollChainKey")).thenReturn(chainNameSet); - when(chainJedis.hget("pollChainKey", "chain22")).thenReturn(chainValue); - - Set scriptFieldSet = new HashSet<>(); - scriptFieldSet.add("s11:script:脚本s11:groovy"); - scriptFieldSet.add("s22:script:脚本s22:js"); - scriptFieldSet.add("s33:script:脚本s33"); - String s11 = "defaultContext.setData(\"test11\",\"hello s11\");"; - String s22 = "defaultContext.setData(\"test22\",\"hello s22\");"; - String s33 = "defaultContext.setData(\"test33\",\"hello s33\");"; - - when(scriptJedis.hkeys("pollScriptKey")).thenReturn(scriptFieldSet); - when(scriptJedis.hget("pollScriptKey", "s11:script:脚本s11:groovy")).thenReturn(s11); - when(scriptJedis.hget("pollScriptKey", "s22:script:脚本s22:js")).thenReturn(s22); - when(scriptJedis.hget("pollScriptKey", "s33:script:脚本s33")).thenReturn(s33); - - LiteflowResponse response = flowExecutor.execute2Resp("chain22", "arg"); - DefaultContext context = response.getFirstContextBean(); - Assertions.assertTrue(response.isSuccess()); - Assertions.assertEquals("hello s11", context.getData("test11")); - Assertions.assertEquals("a==>b==>c==>s11[脚本s11]==>s22[脚本s22]==>s33[脚本s33]", response.getExecuteStepStrWithoutTime()); - } -} From c5e221c9a53d37595c5448fe0af0c61c1a45f174 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sun, 13 Aug 2023 00:53:20 +0800 Subject: [PATCH 31/41] add test --- .../RedisWithXmlELPollSpringbootTest.java | 17 +++- ...edisWithXmlELSubscribeSpringbootTest2.java | 89 +++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest2.java diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java index 20f7da8f..f146a7c5 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java @@ -1,5 +1,6 @@ package com.yomahub.liteflow.test.redis; +import cn.hutool.crypto.digest.DigestUtil; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.flow.LiteflowResponse; @@ -20,6 +21,8 @@ import javax.annotation.Resource; import java.util.HashSet; import java.util.Set; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.when; /** @@ -62,12 +65,24 @@ public class RedisWithXmlELPollSpringbootTest extends BaseTest { Set chainNameSet = new HashSet<>(); chainNameSet.add("chain11"); String chainValue = "THEN(a, b, c);"; + Object chainSHA = DigestUtil.sha1Hex(chainValue); + + //SHA值用于测试修改chain的轮询刷新功能 + String changeChainValue = "THEN(a, c);"; + Object changeChainSHA = DigestUtil.sha1Hex(changeChainValue); when(chainJedis.hkeys("pollChainKey")).thenReturn(chainNameSet); - when(chainJedis.hget("pollChainKey", "chain11")).thenReturn(chainValue); + when(chainJedis.hget("pollChainKey", "chain11")).thenReturn(chainValue).thenReturn(changeChainValue); + when(chainJedis.evalsha(anyString(), anyInt(), anyString())).thenReturn(chainSHA).thenReturn(changeChainSHA); LiteflowResponse response = flowExecutor.execute2Resp("chain11", "arg"); Assertions.assertTrue(response.isSuccess()); Assertions.assertEquals("a==>b==>c", response.getExecuteStepStr()); + + flowExecutor.reloadRule(); + + response = flowExecutor.execute2Resp("chain11", "arg"); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertEquals("a==>c", response.getExecuteStepStr()); } /** diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest2.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest2.java new file mode 100644 index 00000000..ff89921e --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest2.java @@ -0,0 +1,89 @@ +package com.yomahub.liteflow.test.redis; + +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.slot.DefaultContext; +import com.yomahub.liteflow.test.BaseTest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.redisson.api.RMapCache; +import org.redisson.api.RedissonClient; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import javax.annotation.Resource; + +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +/** + * springboot环境下的redis配置源订阅模式功能测试 + * + * @author hxinyu + * @since 2.11.0 + */ +@ExtendWith(SpringExtension.class) +@TestPropertySource(value = "classpath:/redis/application-sub-xml.properties") +@SpringBootTest(classes = RedisWithXmlELSubscribeSpringbootTest2.class) +@EnableAutoConfiguration +@ComponentScan({"com.yomahub.liteflow.test.redis.cmp"}) +public class RedisWithXmlELSubscribeSpringbootTest2 extends BaseTest { + + @MockBean(name = "chainClient") + private static RedissonClient chainClient; + + @MockBean(name = "scriptClient") + private static RedissonClient scriptClient; + + @Resource + private FlowExecutor flowExecutor; + + @BeforeEach + public void setUp() { + MockitoAnnotations.initMocks(this); + } + +/* @BeforeAll + public static void setUpBeforeClass() { + Config config = new Config(); + config.useSingleServer().setAddress("redis://127.0.0.1:6379").setDatabase(1); + redissonClient = Redisson.create(config); + RMapCache chainKey = redissonClient.getMapCache("chainKey"); + RMapCache scriptKey = redissonClient.getMapCache("scriptKey"); + scriptKey.put("s1:script:脚本s1:groovy", "defaultContext.setData(\"test1\",\"hello s1\");"); + scriptKey.put("s2:script:脚本s2:js", "defaultContext.setData(\"test2\",\"hello s2\");"); + scriptKey.put("s3:script:脚本s3", "defaultContext.setData(\"test3\",\"hello s3\");"); + chainKey.put("chain1", "THEN(a, b, c);"); + chainKey.put("chain2", "THEN(a, b, c, s3);"); + chainKey.put("chain3", "THEN(a, b, c, s1, s2);"); + }*/ + + @Test + public void testSubWithXml() throws InterruptedException { + RMapCache chainKey = chainClient.getMapCache(""); + System.out.println(chainKey); + +/* LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertEquals("a==>b==>c", response.getExecuteStepStr());*/ + } + + @Test + public void testSubWithScriptXml() throws InterruptedException { + LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg"); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertEquals("hello s1", context.getData("test1")); + Assertions.assertEquals("a==>b==>c==>s1[脚本s1]==>s2[脚本s2]", response.getExecuteStepStrWithoutTime()); + } +} From 8242c97f24905a673aac288ecc4c50c59df104bd Mon Sep 17 00:00:00 2001 From: houxinyu Date: Mon, 14 Aug 2023 20:41:43 +0800 Subject: [PATCH 32/41] feat client & add test --- .../parser/redis/mode/subscribe/RClient.java | 59 +++++ .../subscribe/RedisParserSubscribeMode.java | 54 +++-- .../RedisWithXmlELPollSpringbootTest.java | 31 ++- ...RedisWithXmlELSubscribeSpringbootTest.java | 203 +++++++----------- ...edisWithXmlELSubscribeSpringbootTest2.java | 89 -------- 5 files changed, 185 insertions(+), 251 deletions(-) create mode 100644 liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RClient.java delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest2.java diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RClient.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RClient.java new file mode 100644 index 00000000..70cd92f9 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RClient.java @@ -0,0 +1,59 @@ +package com.yomahub.liteflow.parser.redis.mode.subscribe; + +import cn.hutool.core.collection.CollectionUtil; +import org.redisson.api.RMapCache; +import org.redisson.api.RedissonClient; +import org.redisson.api.map.event.MapEntryListener; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * Redisson 客户端封装类. + * + * @author hxinyu + * @since 2.11.0 + */ +public class RClient { + + private final RedissonClient redissonClient; + + private Map map = new HashMap<>(); + + public RClient(RedissonClient redissonClient) { + this.redissonClient = redissonClient; + } + + + /** + * get hashmap of the key + * + * @param key + * @return hashmap + */ + public Map getMap(String key) { + RMapCache mapCache = redissonClient.getMapCache(key); + Set mapFieldSet = mapCache.keySet(); + if (CollectionUtil.isEmpty(mapFieldSet)) { + return map; + } + for (String field : mapFieldSet) { + String value = mapCache.get(field); + map.put(field, value); + } + return map; + } + + + /** + * add listener of the key + * @param key + * @param listener + * @return listener id + */ + public int addListener(String key, MapEntryListener listener) { + RMapCache mapCache = redissonClient.getMapCache(key); + return mapCache.addListener(listener); + } +} diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java index 2a79a524..99ad264f 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java @@ -21,11 +21,12 @@ import org.redisson.config.Config; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Set; /** * Redis Pub/Sub机制实现类 - * Redisson客户端 RMapCache存储结构 + * 使用 Redisson客户端 RMapCache存储结构 * * @author hxinyu * @since 2.11.0 @@ -35,9 +36,9 @@ public class RedisParserSubscribeMode implements RedisParserHelper { private final RedisParserVO redisParserVO; - private RedissonClient chainClient; + private RClient chainClient; - private RedissonClient scriptClient; + private RClient scriptClient; public RedisParserSubscribeMode(RedisParserVO redisParserVO) { this.redisParserVO = redisParserVO; @@ -51,11 +52,11 @@ public class RedisParserSubscribeMode implements RedisParserHelper { } if (ObjectUtil.isNull(chainClient)) { Config config = getRedissonConfig(redisParserVO, redisParserVO.getChainDataBase()); - this.chainClient = Redisson.create(config); + this.chainClient = new RClient(Redisson.create(config)); //如果有脚本数据 if (ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { config = getRedissonConfig(redisParserVO, redisParserVO.getScriptDataBase()); - this.scriptClient = Redisson.create(config); + this.scriptClient = new RClient(Redisson.create(config)); } } } @@ -86,16 +87,16 @@ public class RedisParserSubscribeMode implements RedisParserHelper { public String getContent() { try { // 检查chainKey下有没有子节点 - RMapCache chainKey = chainClient.getMapCache(redisParserVO.getChainKey()); - Set chainNameSet = chainKey.keySet(); - if (CollectionUtil.isEmpty(chainNameSet)) { + Map chainMap = chainClient.getMap(redisParserVO.getChainKey()); + if (CollectionUtil.isEmpty(chainMap)) { throw new RedisException(StrUtil.format("There are no chains in key [{}]", redisParserVO.getChainKey())); } // 获取chainKey下的所有子节点内容List List chainItemContentList = new ArrayList<>(); - for (String chainId : chainNameSet) { - String chainData = chainKey.get(chainId); + for (Map.Entry entry : chainMap.entrySet()) { + String chainId = entry.getKey(); + String chainData = entry.getValue(); if (StrUtil.isNotBlank(chainData)) { chainItemContentList.add(StrUtil.format(CHAIN_XML_PATTERN, chainId, chainData)); } @@ -106,19 +107,17 @@ public class RedisParserSubscribeMode implements RedisParserHelper { // 检查是否有脚本内容,如果有,进行脚本内容的获取 String scriptAllContent = StrUtil.EMPTY; if (hasScript()) { - RMapCache scriptKey = scriptClient.getMapCache(redisParserVO.getScriptKey()); - Set scriptFieldSet = scriptKey.keySet(); - + Map scriptMap = scriptClient.getMap(redisParserVO.getScriptKey()); List scriptItemContentList = new ArrayList<>(); - for (String scriptFieldValue : scriptFieldSet) { + for (Map.Entry entry : scriptMap.entrySet()) { + String scriptFieldValue = entry.getKey(); + String scriptData = entry.getValue(); NodeSimpleVO nodeSimpleVO = RedisParserHelper.convert(scriptFieldValue); if (ObjectUtil.isNull(nodeSimpleVO)) { throw new RedisException( StrUtil.format("The name of the redis field [{}] in scriptKey [{}] is invalid", - scriptFieldValue, scriptKey)); + scriptFieldValue, redisParserVO.getScriptKey())); } - String scriptData = scriptKey.get(scriptFieldValue); - // 有语言类型 if (StrUtil.isNotBlank(nodeSimpleVO.getLanguage())) { scriptItemContentList.add(StrUtil.format(NODE_ITEM_WITH_LANGUAGE_XML_PATTERN, @@ -150,9 +149,8 @@ public class RedisParserSubscribeMode implements RedisParserHelper { } try { // 存在这个节点,但是子节点不存在 - RMapCache scriptKey = scriptClient.getMapCache(redisParserVO.getScriptKey()); - Set scriptKeySet = scriptKey.keySet(); - return !CollUtil.isEmpty(scriptKeySet); + Map scriptMap = scriptClient.getMap(redisParserVO.getScriptKey()); + return !CollUtil.isEmpty(scriptMap); } catch (Exception e) { return false; @@ -165,38 +163,38 @@ public class RedisParserSubscribeMode implements RedisParserHelper { @Override public void listenRedis() { //监听 chain - RMapCache chainKey = chainClient.getMapCache(redisParserVO.getChainKey()); + String chainKey = redisParserVO.getChainKey(); //添加新 chain - chainKey.addListener((EntryCreatedListener) event -> { + chainClient.addListener(chainKey, (EntryCreatedListener) event -> { LOG.info("starting reload flow config... create key={} value={},", event.getKey(), event.getValue()); LiteFlowChainELBuilder.createChain().setChainId(event.getKey()).setEL(event.getValue()).build(); }); //修改 chain - chainKey.addListener((EntryUpdatedListener) event -> { + chainClient.addListener(chainKey, (EntryUpdatedListener) event -> { LOG.info("starting reload flow config... update key={} new value={},", event.getKey(), event.getValue()); LiteFlowChainELBuilder.createChain().setChainId(event.getKey()).setEL(event.getValue()).build(); }); //删除 chain - chainKey.addListener((EntryRemovedListener) event -> { + chainClient.addListener(chainKey, (EntryRemovedListener) event -> { LOG.info("starting reload flow config... delete key={}", event.getKey()); FlowBus.removeChain(event.getKey()); }); //监听 script if (ObjectUtil.isNotNull(scriptClient) && ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { - RMapCache scriptKey = scriptClient.getMapCache(redisParserVO.getScriptKey()); + String scriptKey = redisParserVO.getScriptKey(); //添加 script - scriptKey.addListener((EntryCreatedListener) event -> { + scriptClient.addListener(scriptKey, (EntryCreatedListener) event -> { LOG.info("starting reload flow config... create key={} value={},", event.getKey(), event.getValue()); RedisParserHelper.changeScriptNode(event.getKey(), event.getValue()); }); //修改 script - scriptKey.addListener((EntryUpdatedListener) event -> { + scriptClient.addListener(scriptKey, (EntryUpdatedListener) event -> { LOG.info("starting reload flow config... update key={} new value={},", event.getKey(), event.getValue()); RedisParserHelper.changeScriptNode(event.getKey(), event.getValue()); }); //删除 script - scriptKey.addListener((EntryRemovedListener) event -> { + scriptClient.addListener(scriptKey, (EntryRemovedListener) event -> { LOG.info("starting reload flow config... delete key={}", event.getKey()); NodeSimpleVO nodeSimpleVO = RedisParserHelper.convert(event.getKey()); FlowBus.getNodeMap().remove(nodeSimpleVO.getNodeId()); diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java index f146a7c5..62e40f8a 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java @@ -21,8 +21,7 @@ import javax.annotation.Resource; import java.util.HashSet; import java.util.Set; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.when; /** @@ -65,21 +64,24 @@ public class RedisWithXmlELPollSpringbootTest extends BaseTest { Set chainNameSet = new HashSet<>(); chainNameSet.add("chain11"); String chainValue = "THEN(a, b, c);"; + //SHA值用于测试修改chain的轮询刷新功能 Object chainSHA = DigestUtil.sha1Hex(chainValue); - //SHA值用于测试修改chain的轮询刷新功能 + //修改chain并更新SHA值 String changeChainValue = "THEN(a, c);"; Object changeChainSHA = DigestUtil.sha1Hex(changeChainValue); when(chainJedis.hkeys("pollChainKey")).thenReturn(chainNameSet); when(chainJedis.hget("pollChainKey", "chain11")).thenReturn(chainValue).thenReturn(changeChainValue); when(chainJedis.evalsha(anyString(), anyInt(), anyString())).thenReturn(chainSHA).thenReturn(changeChainSHA); + //测试修改前的chain LiteflowResponse response = flowExecutor.execute2Resp("chain11", "arg"); Assertions.assertTrue(response.isSuccess()); Assertions.assertEquals("a==>b==>c", response.getExecuteStepStr()); flowExecutor.reloadRule(); + //测试修改后的chain response = flowExecutor.execute2Resp("chain11", "arg"); Assertions.assertTrue(response.isSuccess()); Assertions.assertEquals("a==>c", response.getExecuteStepStr()); @@ -103,16 +105,37 @@ public class RedisWithXmlELPollSpringbootTest extends BaseTest { String s11 = "defaultContext.setData(\"test11\",\"hello s11\");"; String s22 = "defaultContext.setData(\"test22\",\"hello s22\");"; String s33 = "defaultContext.setData(\"test33\",\"hello s33\");"; + //SHA值用于测试修改script的轮询刷新功能 + Object s11SHA = DigestUtil.sha1Hex(s11); + Object s22SHA = DigestUtil.sha1Hex(s22); + Object s33SHA = DigestUtil.sha1Hex(s33); + //修改script值并更新SHA值 + String changeS11 = "defaultContext.setData(\"test11\",\"hello world\");"; + Object changeS11SHA = DigestUtil.sha1Hex(changeS11); when(scriptJedis.hkeys("pollScriptKey")).thenReturn(scriptFieldSet); - when(scriptJedis.hget("pollScriptKey", "s11:script:脚本s11:groovy")).thenReturn(s11); + when(scriptJedis.hget("pollScriptKey", "s11:script:脚本s11:groovy")).thenReturn(s11).thenReturn(changeS11); when(scriptJedis.hget("pollScriptKey", "s22:script:脚本s22:js")).thenReturn(s22); when(scriptJedis.hget("pollScriptKey", "s33:script:脚本s33")).thenReturn(s33); + //分别模拟三个script的evalsha指纹值计算的返回值, 其中s11脚本修改 指纹值变化 + when(scriptJedis.evalsha(anyString(), eq(2), eq("pollScriptKey"), eq("s11:script:脚本s11:groovy"))).thenReturn(s11SHA).thenReturn(changeS11SHA); + when(scriptJedis.evalsha(anyString(), eq(2), eq("pollScriptKey"), eq("s22:script:脚本s22:js"))).thenReturn(s22SHA); + when(scriptJedis.evalsha(anyString(), eq(2), eq("pollScriptKey"), eq("s33:script:脚本s33"))).thenReturn(s33SHA); + //测试修改前的script LiteflowResponse response = flowExecutor.execute2Resp("chain22", "arg"); DefaultContext context = response.getFirstContextBean(); Assertions.assertTrue(response.isSuccess()); Assertions.assertEquals("hello s11", context.getData("test11")); + Assertions.assertEquals("hello s22", context.getData("test22")); Assertions.assertEquals("a==>b==>c==>s11[脚本s11]==>s22[脚本s22]==>s33[脚本s33]", response.getExecuteStepStrWithoutTime()); + + flowExecutor.reloadRule(); + + //测试修改后的script + response = flowExecutor.execute2Resp("chain22", "arg"); + context = response.getFirstContextBean(); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertEquals("hello world", context.getData("test11")); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java index 19ed1092..9c5c3179 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java @@ -1,35 +1,31 @@ package com.yomahub.liteflow.test.redis; import com.yomahub.liteflow.core.FlowExecutor; -import com.yomahub.liteflow.core.FlowInitHook; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.flow.LiteflowResponse; -import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; -import com.yomahub.liteflow.property.LiteflowConfig; -import com.yomahub.liteflow.property.LiteflowConfigGetter; +import com.yomahub.liteflow.parser.redis.mode.subscribe.RClient; import com.yomahub.liteflow.slot.DefaultContext; -import com.yomahub.liteflow.spi.holder.SpiFactoryCleaner; -import com.yomahub.liteflow.spring.ComponentScanner; import com.yomahub.liteflow.test.BaseTest; -import com.yomahub.liteflow.thread.ExecutorHelper; -import com.yomahub.liteflow.util.JsonUtil; -import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.redisson.Redisson; -import org.redisson.api.RMapCache; -import org.redisson.api.RedissonClient; -import org.redisson.config.Config; +import org.mockito.MockitoAnnotations; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.ComponentScan; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; import javax.annotation.Resource; -import java.util.Set; + +import java.util.HashMap; +import java.util.Map; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; /** * springboot环境下的redis配置源订阅模式功能测试 @@ -44,140 +40,87 @@ import java.util.Set; @ComponentScan({"com.yomahub.liteflow.test.redis.cmp"}) public class RedisWithXmlELSubscribeSpringbootTest extends BaseTest { - private static RedissonClient redissonClient; + @MockBean(name = "chainClient") + private static RClient chainClient; + + @MockBean(name = "scriptClient") + private static RClient scriptClient; @Resource private FlowExecutor flowExecutor; - @BeforeAll - public static void setUpBeforeClass() { - Config config = new Config(); - config.useSingleServer().setAddress("redis://127.0.0.1:6379").setDatabase(1); - redissonClient = Redisson.create(config); - RMapCache chainKey = redissonClient.getMapCache("chainKey"); - RMapCache scriptKey = redissonClient.getMapCache("scriptKey"); - scriptKey.put("s1:script:脚本s1:groovy", "defaultContext.setData(\"test1\",\"hello s1\");"); - scriptKey.put("s2:script:脚本s2:js", "defaultContext.setData(\"test2\",\"hello s2\");"); - scriptKey.put("s3:script:脚本s3", "defaultContext.setData(\"test3\",\"hello s3\");"); - chainKey.put("chain1", "THEN(a, b, c);"); - chainKey.put("chain2", "THEN(a, b, c, s3);"); - chainKey.put("chain3", "THEN(a, b, c, s1, s2);"); + @BeforeEach + public void setUp() { + MockitoAnnotations.initMocks(this); } + @AfterEach + public void after() { + FlowBus.cleanCache(); + } + + /** + * 测试 chain + */ @Test - public void testSubWithXml() throws InterruptedException { + public void testSubWithXml() { + Map chainMap = new HashMap<>(); + chainMap.put("chain1", "THEN(a, b, c);"); + //修改chain值 + Map changeChainMap = new HashMap<>(); + changeChainMap.put("chain1", "THEN(a, c);"); + when(chainClient.getMap("chainKey")).thenReturn(chainMap).thenReturn(changeChainMap); + + //测试修改前的chain LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); Assertions.assertTrue(response.isSuccess()); Assertions.assertEquals("a==>b==>c", response.getExecuteStepStr()); - //修改redis中规则 - changeXMLData(); - //重新加载规则 - Thread.sleep(50); - Assertions.assertEquals("a==>c==>b", flowExecutor.execute2Resp("chain1", "arg").getExecuteStepStr()); + flowExecutor.reloadRule(); - //删除redis中规则 - deleteXMLData(); - //重新加载规则 - Thread.sleep(50); + //测试修改后的chain response = flowExecutor.execute2Resp("chain1", "arg"); - Assertions.assertTrue(!response.isSuccess()); - - //添加redis中规则 - addXMLData(); - //重新加载规则 - Thread.sleep(50); - Assertions.assertEquals("b==>c", flowExecutor.execute2Resp("chain4", "arg").getExecuteStepStr()); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertEquals("a==>c", response.getExecuteStepStr()); } @Test - public void testSubWithScriptXml() throws InterruptedException { - LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg"); + public void testSubWithScriptXml() { + Map chainMap = new HashMap<>(); + chainMap.put("chain2", "THEN(a, b, c, s1, s2, s3);"); + + Map scriptMap = new HashMap<>(); + scriptMap.put("s1:script:脚本s1:groovy", "defaultContext.setData(\"test1\",\"hello s1\");"); + scriptMap.put("s2:script:脚本s2:js", "defaultContext.setData(\"test2\",\"hello s2\");"); + scriptMap.put("s3:script:脚本s3", "defaultContext.setData(\"test3\",\"hello s3\");"); + //修改chain值和script值 + Map changeChainMap = new HashMap<>(); + changeChainMap.put("chain2", "THEN(a, c, s1, s3);"); + Map changeScriptMap = new HashMap<>(); + changeScriptMap.put("s1:script:脚本s1:groovy", "defaultContext.setData(\"test1\",\"hello world\");"); + changeScriptMap.put("s2:script:脚本s2:js", "defaultContext.setData(\"test2\",\"hello s2\");"); + changeScriptMap.put("s3:script:脚本s3", "defaultContext.setData(\"test3\",\"hello s3\");"); + + when(chainClient.getMap("chainKey")).thenReturn(chainMap).thenReturn(changeChainMap); + //这里是因为脚本的getMap方法在一次流程里会执行到两次 + when(scriptClient.getMap("scriptKey")).thenReturn(scriptMap).thenReturn(scriptMap) + .thenReturn(changeScriptMap).thenReturn(changeScriptMap); + + //测试修改前的chain和script + LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg"); DefaultContext context = response.getFirstContextBean(); Assertions.assertTrue(response.isSuccess()); Assertions.assertEquals("hello s1", context.getData("test1")); - Assertions.assertEquals("a==>b==>c==>s1[脚本s1]==>s2[脚本s2]", response.getExecuteStepStrWithoutTime()); + Assertions.assertEquals("hello s2", context.getData("test2")); + Assertions.assertEquals("a==>b==>c==>s1[脚本s1]==>s2[脚本s2]==>s3[脚本s3]", response.getExecuteStepStrWithoutTime()); - //添加和删除脚本 - addAndDeleteScriptData(); - //修改redis脚本 - changeScriptData(); - Thread.sleep(50); - context = flowExecutor.execute2Resp("chain3", "arg").getFirstContextBean(); - Assertions.assertEquals("hello s1 version2", context.getData("test1")); - context = flowExecutor.execute2Resp("chain2", "arg").getFirstContextBean(); - Assertions.assertEquals("hello s3 version2", context.getData("test2")); + flowExecutor.reloadRule(); + + //测试修改后的chain和script + response = flowExecutor.execute2Resp("chain2", "arg"); + context = response.getFirstContextBean(); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertEquals("hello world", context.getData("test1")); + Assertions.assertEquals("a==>c==>s1[脚本s1]==>s3[脚本s3]", response.getExecuteStepStrWithoutTime()); } - - /** - * 修改redisson中的chain - */ - public void changeXMLData() { - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - RMapCache chainKey = redissonClient.getMapCache(redisParserVO.getChainKey()); - chainKey.put("chain1", "THEN(a, c, b);"); - } - - /** - * 删除redisson中的chain - */ - public void deleteXMLData() { - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - RMapCache chainKey = redissonClient.getMapCache(redisParserVO.getChainKey()); - chainKey.remove("chain1"); - chainKey.remove("chain4"); - } - - /** - * 新增redisson中的chain - */ - public void addXMLData() { - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - RMapCache chainKey = redissonClient.getMapCache(redisParserVO.getChainKey()); - chainKey.put("chain4","THEN(b, c);"); - } - - /** - * 修改redisson中的脚本 - */ - public void changeScriptData() { - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - RMapCache scriptKey = redissonClient.getMapCache(redisParserVO.getScriptKey()); - scriptKey.put("s1:script:脚本s1:groovy", "defaultContext.setData(\"test1\",\"hello s1 version2\");"); - scriptKey.put("s3:script:脚本s3", "defaultContext.setData(\"test2\",\"hello s3 version2\");"); - } - - /** - * 新增和删除redisson中的chain - */ - public void addAndDeleteScriptData() { - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - RMapCache scriptKey = redissonClient.getMapCache(redisParserVO.getScriptKey()); - scriptKey.remove("s3:script:脚本s3"); - scriptKey.put("s5:script:脚本s5:groovy", "defaultContext.setData(\"test1\",\"hello s5\");"); - } - -/* //为便于测试的redis内规则数据数据清空 - @Test - public void testCleanData(){ - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); - RMapCache scriptKey = redissonClient.getMapCache(redisParserVO.getScriptKey()); - RMapCache chainKey = redissonClient.getMapCache(redisParserVO.getChainKey()); - for (String key : chainKey.keySet()) { - chainKey.remove(key); - } - for (String key : scriptKey.keySet()) { - scriptKey.remove(key); - } - chainKey.keySet().forEach(System.out::println); - System.out.println(""); - scriptKey.keySet().forEach(System.out::println); - System.out.println("数据清空完成"); - }*/ } diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest2.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest2.java deleted file mode 100644 index ff89921e..00000000 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest2.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.yomahub.liteflow.test.redis; - -import com.yomahub.liteflow.core.FlowExecutor; -import com.yomahub.liteflow.flow.LiteflowResponse; -import com.yomahub.liteflow.slot.DefaultContext; -import com.yomahub.liteflow.test.BaseTest; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import org.redisson.api.RMapCache; -import org.redisson.api.RedissonClient; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; - -import javax.annotation.Resource; - -import java.util.List; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; - -/** - * springboot环境下的redis配置源订阅模式功能测试 - * - * @author hxinyu - * @since 2.11.0 - */ -@ExtendWith(SpringExtension.class) -@TestPropertySource(value = "classpath:/redis/application-sub-xml.properties") -@SpringBootTest(classes = RedisWithXmlELSubscribeSpringbootTest2.class) -@EnableAutoConfiguration -@ComponentScan({"com.yomahub.liteflow.test.redis.cmp"}) -public class RedisWithXmlELSubscribeSpringbootTest2 extends BaseTest { - - @MockBean(name = "chainClient") - private static RedissonClient chainClient; - - @MockBean(name = "scriptClient") - private static RedissonClient scriptClient; - - @Resource - private FlowExecutor flowExecutor; - - @BeforeEach - public void setUp() { - MockitoAnnotations.initMocks(this); - } - -/* @BeforeAll - public static void setUpBeforeClass() { - Config config = new Config(); - config.useSingleServer().setAddress("redis://127.0.0.1:6379").setDatabase(1); - redissonClient = Redisson.create(config); - RMapCache chainKey = redissonClient.getMapCache("chainKey"); - RMapCache scriptKey = redissonClient.getMapCache("scriptKey"); - scriptKey.put("s1:script:脚本s1:groovy", "defaultContext.setData(\"test1\",\"hello s1\");"); - scriptKey.put("s2:script:脚本s2:js", "defaultContext.setData(\"test2\",\"hello s2\");"); - scriptKey.put("s3:script:脚本s3", "defaultContext.setData(\"test3\",\"hello s3\");"); - chainKey.put("chain1", "THEN(a, b, c);"); - chainKey.put("chain2", "THEN(a, b, c, s3);"); - chainKey.put("chain3", "THEN(a, b, c, s1, s2);"); - }*/ - - @Test - public void testSubWithXml() throws InterruptedException { - RMapCache chainKey = chainClient.getMapCache(""); - System.out.println(chainKey); - -/* LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); - Assertions.assertTrue(response.isSuccess()); - Assertions.assertEquals("a==>b==>c", response.getExecuteStepStr());*/ - } - - @Test - public void testSubWithScriptXml() throws InterruptedException { - LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg"); - DefaultContext context = response.getFirstContextBean(); - Assertions.assertTrue(response.isSuccess()); - Assertions.assertEquals("hello s1", context.getData("test1")); - Assertions.assertEquals("a==>b==>c==>s1[脚本s1]==>s2[脚本s2]", response.getExecuteStepStrWithoutTime()); - } -} From aa532dda6d3c88add0a0e41f51af86842b0ef540 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Tue, 15 Aug 2023 14:17:44 +0800 Subject: [PATCH 33/41] add rclient --- .../liteflow/parser/redis/mode/RClient.java | 109 ++++++++++++++++++ .../parser/redis/mode/subscribe/RClient.java | 59 ---------- .../subscribe/RedisParserSubscribeMode.java | 4 +- ...RedisWithXmlELSubscribeSpringbootTest.java | 2 +- 4 files changed, 111 insertions(+), 63 deletions(-) create mode 100644 liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RClient.java delete mode 100644 liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RClient.java diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RClient.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RClient.java new file mode 100644 index 00000000..79fd53f4 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RClient.java @@ -0,0 +1,109 @@ +package com.yomahub.liteflow.parser.redis.mode; + +import cn.hutool.core.collection.CollectionUtil; +import org.redisson.api.RMap; +import org.redisson.api.RMapCache; +import org.redisson.api.RScript; +import org.redisson.api.RedissonClient; +import org.redisson.api.map.event.MapEntryListener; +import org.redisson.client.codec.StringCodec; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * Redisson 客户端封装类. + * + * @author hxinyu + * @since 2.11.0 + */ +public class RClient { + + private final RedissonClient redissonClient; + + private Map map = new HashMap<>(); + + public RClient(RedissonClient redissonClient) { + this.redissonClient = redissonClient; + } + + + /** + * get hashmap of the key + * + * @param key + * @return hashmap + */ + public Map getMap(String key) { + RMapCache mapCache = redissonClient.getMapCache(key); + Set mapFieldSet = mapCache.keySet(); + if (CollectionUtil.isEmpty(mapFieldSet)) { + return map; + } + for (String field : mapFieldSet) { + String value = mapCache.get(field); + map.put(field, value); + } + return map; + } + + + /** + * add listener of the key + * + * @param key + * @param listener + * @return listener id + */ + public int addListener(String key, MapEntryListener listener) { + RMapCache mapCache = redissonClient.getMapCache(key); + return mapCache.addListener(listener); + } + + /** + * get all keys of hash + * + * @param key + * @return + */ + public Set hkeys(String key) { + RMap map = redissonClient.getMap(key, new StringCodec()); + return map.readAllKeySet(); + } + + /** + * gey value of the key + * + * @param key + * @param field + * @return + */ + public String hget(String key, String field) { + RMap map = redissonClient.getMap(key, new StringCodec()); + return map.get(field); + } + + /** + * Loads Lua script into Redis scripts cache and returns its SHA-1 digest + * @param luaScript + * @return shaDigest + */ + public String scriptLoad(String luaScript) { + RScript script = redissonClient.getScript(new StringCodec()); + return script.scriptLoad(luaScript); + } + + /** + * Executes Lua script stored in Redis scripts cache by SHA-1 digest + * @param shaDigest + * @param args + * @return + */ + public String evalSha(String shaDigest, String... args){ + RScript script = redissonClient.getScript(new StringCodec()); + return script.evalSha(RScript.Mode.READ_ONLY, shaDigest, RScript.ReturnType.VALUE, + Arrays.asList(args)).toString(); + } +} diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RClient.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RClient.java deleted file mode 100644 index 70cd92f9..00000000 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RClient.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.yomahub.liteflow.parser.redis.mode.subscribe; - -import cn.hutool.core.collection.CollectionUtil; -import org.redisson.api.RMapCache; -import org.redisson.api.RedissonClient; -import org.redisson.api.map.event.MapEntryListener; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -/** - * Redisson 客户端封装类. - * - * @author hxinyu - * @since 2.11.0 - */ -public class RClient { - - private final RedissonClient redissonClient; - - private Map map = new HashMap<>(); - - public RClient(RedissonClient redissonClient) { - this.redissonClient = redissonClient; - } - - - /** - * get hashmap of the key - * - * @param key - * @return hashmap - */ - public Map getMap(String key) { - RMapCache mapCache = redissonClient.getMapCache(key); - Set mapFieldSet = mapCache.keySet(); - if (CollectionUtil.isEmpty(mapFieldSet)) { - return map; - } - for (String field : mapFieldSet) { - String value = mapCache.get(field); - map.put(field, value); - } - return map; - } - - - /** - * add listener of the key - * @param key - * @param listener - * @return listener id - */ - public int addListener(String key, MapEntryListener listener) { - RMapCache mapCache = redissonClient.getMapCache(key); - return mapCache.addListener(listener); - } -} diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java index 99ad264f..eb8acd7a 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java @@ -8,12 +8,11 @@ import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.parser.redis.exception.RedisException; +import com.yomahub.liteflow.parser.redis.mode.RClient; import com.yomahub.liteflow.parser.redis.mode.RedisParserHelper; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import com.yomahub.liteflow.spi.holder.ContextAwareHolder; import org.redisson.Redisson; -import org.redisson.api.RMapCache; -import org.redisson.api.RedissonClient; import org.redisson.api.map.event.EntryCreatedListener; import org.redisson.api.map.event.EntryRemovedListener; import org.redisson.api.map.event.EntryUpdatedListener; @@ -22,7 +21,6 @@ import org.redisson.config.Config; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Set; /** * Redis Pub/Sub机制实现类 diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java index 9c5c3179..efc161a6 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java @@ -3,7 +3,7 @@ package com.yomahub.liteflow.test.redis; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.flow.LiteflowResponse; -import com.yomahub.liteflow.parser.redis.mode.subscribe.RClient; +import com.yomahub.liteflow.parser.redis.mode.RClient; import com.yomahub.liteflow.slot.DefaultContext; import com.yomahub.liteflow.test.BaseTest; import org.junit.jupiter.api.AfterEach; From c2339044df2b8b10678e2ca6e0c6741369adc841 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Tue, 15 Aug 2023 16:23:55 +0800 Subject: [PATCH 34/41] add test --- .../liteflow-rule-redis/pom.xml | 6 -- .../liteflow/parser/redis/mode/RClient.java | 24 ++++---- .../parser/redis/mode/RedisParserHelper.java | 32 ++++++++++- .../redis/mode/polling/ChainPollingTask.java | 18 +++--- .../mode/polling/RedisParserPollingMode.java | 55 +++++++++---------- .../redis/mode/polling/ScriptPollingTask.java | 18 +++--- .../subscribe/RedisParserSubscribeMode.java | 18 ------ .../RedisWithXmlELPollSpringbootTest.java | 45 +++++++-------- pom.xml | 1 - 9 files changed, 107 insertions(+), 110 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/pom.xml b/liteflow-rule-plugin/liteflow-rule-redis/pom.xml index 4ee4a1c7..a5e98349 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/pom.xml +++ b/liteflow-rule-plugin/liteflow-rule-redis/pom.xml @@ -27,12 +27,6 @@ ${redisson.version} - - redis.clients - jedis - ${jedis.version} - - cn.hutool hutool-crypto diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RClient.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RClient.java index 79fd53f4..6d9afbce 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RClient.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RClient.java @@ -33,7 +33,7 @@ public class RClient { /** * get hashmap of the key * - * @param key + * @param key hash name * @return hashmap */ public Map getMap(String key) { @@ -53,8 +53,8 @@ public class RClient { /** * add listener of the key * - * @param key - * @param listener + * @param key hash name + * @param listener listener * @return listener id */ public int addListener(String key, MapEntryListener listener) { @@ -65,8 +65,8 @@ public class RClient { /** * get all keys of hash * - * @param key - * @return + * @param key hash name + * @return keySet */ public Set hkeys(String key) { RMap map = redissonClient.getMap(key, new StringCodec()); @@ -76,9 +76,9 @@ public class RClient { /** * gey value of the key * - * @param key - * @param field - * @return + * @param key hash name + * @param field hash field + * @return hash value */ public String hget(String key, String field) { RMap map = redissonClient.getMap(key, new StringCodec()); @@ -87,7 +87,7 @@ public class RClient { /** * Loads Lua script into Redis scripts cache and returns its SHA-1 digest - * @param luaScript + * @param luaScript script * @return shaDigest */ public String scriptLoad(String luaScript) { @@ -97,9 +97,9 @@ public class RClient { /** * Executes Lua script stored in Redis scripts cache by SHA-1 digest - * @param shaDigest - * @param args - * @return + * @param shaDigest script cache by sha-1 + * @param args script args + * @return string */ public String evalSha(String shaDigest, String... args){ RScript script = redissonClient.getScript(new StringCodec()); diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java index afe98fc8..356e86a5 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java @@ -1,13 +1,15 @@ package com.yomahub.liteflow.parser.redis.mode; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.text.StrFormatter; import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.builder.LiteFlowNodeBuilder; -import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.enums.NodeTypeEnum; import com.yomahub.liteflow.log.LFLog; import com.yomahub.liteflow.log.LFLoggerManager; +import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; +import org.redisson.config.Config; import java.util.List; @@ -15,7 +17,7 @@ import java.util.List; * Redis 解析器通用接口 * * @author hxinyu - * @since 2.11.0 + * @since 2.11.0 */ public interface RedisParserHelper { @@ -39,10 +41,34 @@ public interface RedisParserHelper { void listenRedis(); + /** + * 获取Redisson客户端的Config配置通用方法 + * @param redisParserVO redisParserVO + * @param dataBase redisson连接的数据库号 + * @return redisson config + */ + default Config getRedissonConfig(RedisParserVO redisParserVO, Integer dataBase) { + Config config = new Config(); + String redisAddress = StrFormatter.format(REDIS_URL_PATTERN, redisParserVO.getHost(), redisParserVO.getPort()); + //如果配置了密码 + if (StrUtil.isNotBlank(redisParserVO.getPassword())) { + config.useSingleServer().setAddress(redisAddress) + .setPassword(redisParserVO.getPassword()) + .setDatabase(dataBase); + } + //没有配置密码 + else { + config.useSingleServer().setAddress(redisAddress) + .setDatabase(dataBase); + } + return config; + } + /** * script节点的修改/添加 + * * @param scriptFieldValue 新的script名 - * @param newValue 新的script值 + * @param newValue 新的script值 */ static void changeScriptNode(String scriptFieldValue, String newValue) { NodeSimpleVO nodeSimpleVO = convert(scriptFieldValue); diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java index fb127531..95b9c1b9 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java @@ -5,8 +5,8 @@ import cn.hutool.crypto.digest.DigestUtil; import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.log.LFLog; +import com.yomahub.liteflow.parser.redis.mode.RClient; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; -import redis.clients.jedis.Jedis; import java.util.*; @@ -20,7 +20,7 @@ public class ChainPollingTask { private RedisParserVO redisParserVO; - private Jedis chainJedis; + private RClient chainClient; private Integer chainNum; @@ -28,9 +28,9 @@ public class ChainPollingTask { LFLog LOG; - public ChainPollingTask(RedisParserVO redisParserVO, Jedis chainJedis, Integer chainNum, Map chainSHAMap, LFLog LOG) { + public ChainPollingTask(RedisParserVO redisParserVO, RClient chainClient, Integer chainNum, Map chainSHAMap, LFLog LOG) { this.redisParserVO = redisParserVO; - this.chainJedis = chainJedis; + this.chainClient = chainClient; this.chainNum = chainNum; this.chainSHAMap = chainSHAMap; this.LOG = LOG; @@ -46,7 +46,7 @@ public class ChainPollingTask { Runnable r = () -> { String chainKey = redisParserVO.getChainKey(); //Lua获取chainKey中最新的chain数量 - String keyNum = chainJedis.evalsha(keyLua, 1, chainKey).toString(); + String keyNum = chainClient.evalSha(keyLua, chainKey); //修改chainNum为最新chain数量 chainNum = Integer.parseInt(keyNum); @@ -56,7 +56,7 @@ public class ChainPollingTask { String chainId = entry.getKey(); String oldSHA = entry.getValue(); //在redis服务端通过Lua脚本计算SHA值 - String newSHA = chainJedis.evalsha(valueLua, 2, chainKey, chainId).toString(); + String newSHA = chainClient.evalSha(valueLua, chainKey, chainId); if (StrUtil.equals(newSHA, "nil")) { //新SHA值为nil, 即未获取到该chain,表示该chain已被删除 FlowBus.removeChain(chainId); @@ -68,7 +68,7 @@ public class ChainPollingTask { } else if (!StrUtil.equals(newSHA, oldSHA)) { //SHA值发生变化,表示该chain的值已被修改,重新拉取变化的chain - String chainData = chainJedis.hget(chainKey, chainId); + String chainData = chainClient.hget(chainKey, chainId); LiteFlowChainELBuilder.createChain().setChainId(chainId).setEL(chainData).build(); LOG.info("starting reload flow config... update key={} new value={},", chainId, chainData); @@ -90,11 +90,11 @@ public class ChainPollingTask { // 2、修改了chainId:因为遍历到旧的id时会取到nil,SHAMap会把原来的chainId删掉,但没有机会添加新的chainId // 3、上述两者结合 //在此处重新拉取所有chainId集合,补充添加新chain - Set newChainSet = chainJedis.hkeys(chainKey); + Set newChainSet = chainClient.hkeys(chainKey); for (String chainId : newChainSet) { if (!chainSHAMap.containsKey(chainId)) { //将新chainId添加到LiteFlowChainELBuilder和SHAMap - String chainData = chainJedis.hget(chainKey, chainId); + String chainData = chainClient.hget(chainKey, chainId); LiteFlowChainELBuilder.createChain().setChainId(chainId).setEL(chainData).build(); LOG.info("starting reload flow config... create key={} new value={},", chainId, chainData); chainSHAMap.put(chainId, DigestUtil.sha1Hex(chainData)); diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java index 8b796b22..318994a8 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java @@ -6,10 +6,12 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.digest.DigestUtil; import com.yomahub.liteflow.parser.redis.exception.RedisException; +import com.yomahub.liteflow.parser.redis.mode.RClient; import com.yomahub.liteflow.parser.redis.mode.RedisParserHelper; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import com.yomahub.liteflow.spi.holder.ContextAwareHolder; -import redis.clients.jedis.Jedis; +import org.redisson.Redisson; +import org.redisson.config.Config; import java.util.*; import java.util.concurrent.*; @@ -25,9 +27,9 @@ public class RedisParserPollingMode implements RedisParserHelper { private final RedisParserVO redisParserVO; - private Jedis chainJedis; + private RClient chainClient; - private Jedis scriptJedis; + private RClient scriptClient; //chainKey中chain总数 private Integer chainNum = 0; @@ -63,25 +65,18 @@ public class RedisParserPollingMode implements RedisParserHelper { try{ try{ - this.chainJedis = ContextAwareHolder.loadContextAware().getBean("chainJedis"); - this.scriptJedis = ContextAwareHolder.loadContextAware().getBean("scriptJedis"); + this.chainClient = ContextAwareHolder.loadContextAware().getBean("chainClient"); + this.scriptClient = ContextAwareHolder.loadContextAware().getBean("scriptClient"); } catch (Exception ignored) { } - if (ObjectUtil.isNull(chainJedis)) { - chainJedis = new Jedis(redisParserVO.getHost(), redisParserVO.getPort()); - //如果配置了密码 - if (StrUtil.isNotBlank(redisParserVO.getPassword())) { - chainJedis.auth(redisParserVO.getPassword()); - } - chainJedis.select(redisParserVO.getChainDataBase()); + if (ObjectUtil.isNull(chainClient)) { + Config config = getRedissonConfig(redisParserVO, redisParserVO.getChainDataBase()); + this.chainClient = new RClient(Redisson.create(config)); //如果有脚本数据 if (ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { - scriptJedis = new Jedis(redisParserVO.getHost(), redisParserVO.getPort()); - if (StrUtil.isNotBlank(redisParserVO.getPassword())) { - scriptJedis.auth(redisParserVO.getPassword()); - } - scriptJedis.select(redisParserVO.getScriptDataBase()); + config = getRedissonConfig(redisParserVO, redisParserVO.getScriptDataBase()); + this.scriptClient = new RClient(Redisson.create(config)); } } } @@ -95,7 +90,7 @@ public class RedisParserPollingMode implements RedisParserHelper { try { // 检查chainKey下有没有子节点 String chainKey = redisParserVO.getChainKey(); - Set chainNameSet = chainJedis.hkeys(chainKey); + Set chainNameSet = chainClient.hkeys(chainKey); if (CollectionUtil.isEmpty(chainNameSet)) { throw new RedisException(StrUtil.format("There are no chains in key [{}]", chainKey)); } @@ -103,7 +98,7 @@ public class RedisParserPollingMode implements RedisParserHelper { // 获取chainKey下的所有子节点内容List List chainItemContentList = new ArrayList<>(); for (String chainName : chainNameSet) { - String chainData = chainJedis.hget(chainKey, chainName); + String chainData = chainClient.hget(chainKey, chainName); if (StrUtil.isNotBlank(chainData)) { chainItemContentList.add(StrUtil.format(CHAIN_XML_PATTERN, chainName, chainData)); } @@ -119,7 +114,7 @@ public class RedisParserPollingMode implements RedisParserHelper { String scriptAllContent = StrUtil.EMPTY; if (hasScript()) { String scriptKey = redisParserVO.getScriptKey(); - Set scriptFieldSet = scriptJedis.hkeys(scriptKey); + Set scriptFieldSet = scriptClient.hkeys(scriptKey); scriptNum = scriptFieldSet.size(); List scriptItemContentList = new ArrayList<>(); @@ -130,7 +125,7 @@ public class RedisParserPollingMode implements RedisParserHelper { StrUtil.format("The name of the redis field [{}] in scriptKey [{}] is invalid", scriptFieldValue, scriptKey)); } - String scriptData = scriptJedis.hget(scriptKey, scriptFieldValue); + String scriptData = scriptClient.hget(scriptKey, scriptFieldValue); // 有语言类型 if (StrUtil.isNotBlank(nodeSimpleVO.getLanguage())) { @@ -161,7 +156,7 @@ public class RedisParserPollingMode implements RedisParserHelper { } public boolean hasScript() { - if (ObjectUtil.isNull(scriptJedis) || ObjectUtil.isNull(redisParserVO.getScriptDataBase())) { + if (ObjectUtil.isNull(scriptClient) || ObjectUtil.isNull(redisParserVO.getScriptDataBase())) { return false; } try{ @@ -169,7 +164,7 @@ public class RedisParserPollingMode implements RedisParserHelper { if (StrUtil.isBlank(scriptKey)) { return false; } - Set scriptKeySet = scriptJedis.hkeys(scriptKey); + Set scriptKeySet = scriptClient.hkeys(scriptKey); return !CollUtil.isEmpty(scriptKeySet); } catch (Exception e) { @@ -183,8 +178,8 @@ public class RedisParserPollingMode implements RedisParserHelper { @Override public void listenRedis() { //将lua脚本添加到chainJedis脚本缓存 - String keyLuaOfChain = chainJedis.scriptLoad(luaOfKey); - String valueLuaOfChain = chainJedis.scriptLoad(luaOfValue); + String keyLuaOfChain = chainClient.scriptLoad(luaOfKey); + String valueLuaOfChain = chainClient.scriptLoad(luaOfValue); //定时任务线程池 ScheduledThreadPoolExecutor pollExecutor = new ScheduledThreadPoolExecutor( @@ -192,19 +187,19 @@ public class RedisParserPollingMode implements RedisParserHelper { new ThreadPoolExecutor.DiscardOldestPolicy()); //添加轮询chain的定时任务 - ChainPollingTask chainTask = new ChainPollingTask(redisParserVO, chainJedis, chainNum, chainSHAMap, LOG); + ChainPollingTask chainTask = new ChainPollingTask(redisParserVO, chainClient, chainNum, chainSHAMap, LOG); pollExecutor.scheduleAtFixedRate(chainTask.pollChainTask(keyLuaOfChain, valueLuaOfChain), 60, redisParserVO.getPollingInterval().longValue(), TimeUnit.SECONDS); //如果有脚本 - if (ObjectUtil.isNotNull(scriptJedis) && ObjectUtil.isNotNull(redisParserVO.getScriptDataBase()) + if (ObjectUtil.isNotNull(scriptClient) && ObjectUtil.isNotNull(redisParserVO.getScriptDataBase()) && StrUtil.isNotBlank(redisParserVO.getScriptKey())) { //将lua脚本添加到scriptJedis脚本缓存 - String keyLuaOfScript = scriptJedis.scriptLoad(luaOfKey); - String valueLuaOfScript = scriptJedis.scriptLoad(luaOfValue); + String keyLuaOfScript = scriptClient.scriptLoad(luaOfKey); + String valueLuaOfScript = scriptClient.scriptLoad(luaOfValue); //添加轮询script的定时任务 - ScriptPollingTask scriptTask = new ScriptPollingTask(redisParserVO, scriptJedis, scriptNum, scriptSHAMap, LOG); + ScriptPollingTask scriptTask = new ScriptPollingTask(redisParserVO, scriptClient, scriptNum, scriptSHAMap, LOG); pollExecutor.scheduleAtFixedRate(scriptTask.pollScriptTask(keyLuaOfScript, valueLuaOfScript), 60, redisParserVO.getPollingInterval().longValue(), TimeUnit.SECONDS); } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java index e00af848..f53a62b0 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java @@ -4,9 +4,9 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.digest.DigestUtil; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.log.LFLog; +import com.yomahub.liteflow.parser.redis.mode.RClient; import com.yomahub.liteflow.parser.redis.mode.RedisParserHelper; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; -import redis.clients.jedis.Jedis; import java.util.ArrayList; import java.util.List; @@ -23,7 +23,7 @@ public class ScriptPollingTask { private RedisParserVO redisParserVO; - private Jedis scriptJedis; + private RClient scriptClient; private Integer scriptNum; @@ -31,9 +31,9 @@ public class ScriptPollingTask { LFLog LOG; - public ScriptPollingTask(RedisParserVO redisParserVO, Jedis scriptJedis, Integer scriptNum, Map scriptSHAMap, LFLog LOG) { + public ScriptPollingTask(RedisParserVO redisParserVO, RClient scriptClient, Integer scriptNum, Map scriptSHAMap, LFLog LOG) { this.redisParserVO = redisParserVO; - this.scriptJedis = scriptJedis; + this.scriptClient = scriptClient; this.scriptNum = scriptNum; this.scriptSHAMap = scriptSHAMap; this.LOG = LOG; @@ -49,7 +49,7 @@ public class ScriptPollingTask { Runnable r = () -> { String scriptKey = redisParserVO.getScriptKey(); //Lua获取scriptKey中最新的script数量 - String keyNum = scriptJedis.evalsha(keyLua, 1, scriptKey).toString(); + String keyNum = scriptClient.evalSha(keyLua, scriptKey); //修改scriptNum为最新script数量 scriptNum = Integer.parseInt(keyNum); @@ -59,7 +59,7 @@ public class ScriptPollingTask { String scriptFieldValue = entry.getKey(); String oldSHA = entry.getValue(); //在redis服务端通过Lua脚本计算SHA值 - String newSHA = scriptJedis.evalsha(valueLua, 2, scriptKey, scriptFieldValue).toString(); + String newSHA = scriptClient.evalSha(valueLua, scriptKey, scriptFieldValue); if (StrUtil.equals(newSHA, "nil")) { //新SHA值为nil, 即未获取到该script,表示该script已被删除 RedisParserHelper.NodeSimpleVO nodeSimpleVO = RedisParserHelper.convert(scriptFieldValue); @@ -72,7 +72,7 @@ public class ScriptPollingTask { } else if (!StrUtil.equals(newSHA, oldSHA)) { //SHA值发生变化,表示该script的值已被修改,重新拉取变化的script - String scriptData = scriptJedis.hget(scriptKey, scriptFieldValue); + String scriptData = scriptClient.hget(scriptKey, scriptFieldValue); RedisParserHelper.changeScriptNode(scriptFieldValue, scriptData); LOG.info("starting reload flow config... update key={} new value={},", scriptFieldValue, scriptData); @@ -94,11 +94,11 @@ public class ScriptPollingTask { // 2、修改了script名:因为遍历到旧的id时会取到nil,SHAMap会把原来的script删掉,但没有机会添加新的script // 3、上述两者结合 //在此处重新拉取所有script名集合,补充添加新script - Set newScriptSet = scriptJedis.hkeys(scriptKey); + Set newScriptSet = scriptClient.hkeys(scriptKey); for (String scriptFieldValue : newScriptSet) { if (!scriptSHAMap.containsKey(scriptFieldValue)) { //将新script添加到LiteFlowChainELBuilder和SHAMap - String scriptData = scriptJedis.hget(scriptKey, scriptFieldValue); + String scriptData = scriptClient.hget(scriptKey, scriptFieldValue); RedisParserHelper.changeScriptNode(scriptFieldValue, scriptData); LOG.info("starting reload flow config... create key={} new value={},", scriptFieldValue, scriptData); scriptSHAMap.put(scriptFieldValue, DigestUtil.sha1Hex(scriptData)); diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java index eb8acd7a..67c9697f 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java @@ -2,7 +2,6 @@ package com.yomahub.liteflow.parser.redis.mode.subscribe; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; -import cn.hutool.core.text.StrFormatter; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; @@ -64,23 +63,6 @@ public class RedisParserSubscribeMode implements RedisParserHelper { } - private Config getRedissonConfig(RedisParserVO redisParserVO, Integer dataBase) { - Config config = new Config(); - String redisAddress = StrFormatter.format(REDIS_URL_PATTERN, redisParserVO.getHost(), redisParserVO.getPort()); - //如果配置了密码 - if (StrUtil.isNotBlank(redisParserVO.getPassword())) { - config.useSingleServer().setAddress(redisAddress) - .setPassword(redisParserVO.getPassword()) - .setDatabase(dataBase); - } - //没有配置密码 - else { - config.useSingleServer().setAddress(redisAddress) - .setDatabase(dataBase); - } - return config; - } - @Override public String getContent() { try { diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java index 62e40f8a..5119b726 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java @@ -4,6 +4,7 @@ import cn.hutool.crypto.digest.DigestUtil; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.parser.redis.mode.RClient; import com.yomahub.liteflow.slot.DefaultContext; import com.yomahub.liteflow.test.BaseTest; import org.junit.jupiter.api.*; @@ -37,11 +38,11 @@ import static org.mockito.Mockito.when; @ComponentScan({"com.yomahub.liteflow.test.redis.cmp"}) public class RedisWithXmlELPollSpringbootTest extends BaseTest { - @MockBean(name = "chainJedis") - private static Jedis chainJedis; + @MockBean(name = "chainClient") + private static RClient chainClient; - @MockBean(name = "scriptJedis") - private static Jedis scriptJedis; + @MockBean(name = "scriptClient") + private static RClient scriptClient; @Resource private FlowExecutor flowExecutor; @@ -65,14 +66,14 @@ public class RedisWithXmlELPollSpringbootTest extends BaseTest { chainNameSet.add("chain11"); String chainValue = "THEN(a, b, c);"; //SHA值用于测试修改chain的轮询刷新功能 - Object chainSHA = DigestUtil.sha1Hex(chainValue); + String chainSHA = DigestUtil.sha1Hex(chainValue); //修改chain并更新SHA值 String changeChainValue = "THEN(a, c);"; - Object changeChainSHA = DigestUtil.sha1Hex(changeChainValue); - when(chainJedis.hkeys("pollChainKey")).thenReturn(chainNameSet); - when(chainJedis.hget("pollChainKey", "chain11")).thenReturn(chainValue).thenReturn(changeChainValue); - when(chainJedis.evalsha(anyString(), anyInt(), anyString())).thenReturn(chainSHA).thenReturn(changeChainSHA); + String changeChainSHA = DigestUtil.sha1Hex(changeChainValue); + when(chainClient.hkeys("pollChainKey")).thenReturn(chainNameSet); + when(chainClient.hget("pollChainKey", "chain11")).thenReturn(chainValue).thenReturn(changeChainValue); + when(chainClient.evalSha(anyString(), anyString())).thenReturn(chainSHA).thenReturn(changeChainSHA); //测试修改前的chain LiteflowResponse response = flowExecutor.execute2Resp("chain11", "arg"); @@ -95,8 +96,8 @@ public class RedisWithXmlELPollSpringbootTest extends BaseTest { Set chainNameSet = new HashSet<>(); chainNameSet.add("chain22"); String chainValue = "THEN(a, b, c, s11, s22, s33);"; - when(chainJedis.hkeys("pollChainKey")).thenReturn(chainNameSet); - when(chainJedis.hget("pollChainKey", "chain22")).thenReturn(chainValue); + when(chainClient.hkeys("pollChainKey")).thenReturn(chainNameSet); + when(chainClient.hget("pollChainKey", "chain22")).thenReturn(chainValue); Set scriptFieldSet = new HashSet<>(); scriptFieldSet.add("s11:script:脚本s11:groovy"); @@ -106,21 +107,21 @@ public class RedisWithXmlELPollSpringbootTest extends BaseTest { String s22 = "defaultContext.setData(\"test22\",\"hello s22\");"; String s33 = "defaultContext.setData(\"test33\",\"hello s33\");"; //SHA值用于测试修改script的轮询刷新功能 - Object s11SHA = DigestUtil.sha1Hex(s11); - Object s22SHA = DigestUtil.sha1Hex(s22); - Object s33SHA = DigestUtil.sha1Hex(s33); + String s11SHA = DigestUtil.sha1Hex(s11); + String s22SHA = DigestUtil.sha1Hex(s22); + String s33SHA = DigestUtil.sha1Hex(s33); //修改script值并更新SHA值 String changeS11 = "defaultContext.setData(\"test11\",\"hello world\");"; - Object changeS11SHA = DigestUtil.sha1Hex(changeS11); + String changeS11SHA = DigestUtil.sha1Hex(changeS11); - when(scriptJedis.hkeys("pollScriptKey")).thenReturn(scriptFieldSet); - when(scriptJedis.hget("pollScriptKey", "s11:script:脚本s11:groovy")).thenReturn(s11).thenReturn(changeS11); - when(scriptJedis.hget("pollScriptKey", "s22:script:脚本s22:js")).thenReturn(s22); - when(scriptJedis.hget("pollScriptKey", "s33:script:脚本s33")).thenReturn(s33); + when(scriptClient.hkeys("pollScriptKey")).thenReturn(scriptFieldSet); + when(scriptClient.hget("pollScriptKey", "s11:script:脚本s11:groovy")).thenReturn(s11).thenReturn(changeS11); + when(scriptClient.hget("pollScriptKey", "s22:script:脚本s22:js")).thenReturn(s22); + when(scriptClient.hget("pollScriptKey", "s33:script:脚本s33")).thenReturn(s33); //分别模拟三个script的evalsha指纹值计算的返回值, 其中s11脚本修改 指纹值变化 - when(scriptJedis.evalsha(anyString(), eq(2), eq("pollScriptKey"), eq("s11:script:脚本s11:groovy"))).thenReturn(s11SHA).thenReturn(changeS11SHA); - when(scriptJedis.evalsha(anyString(), eq(2), eq("pollScriptKey"), eq("s22:script:脚本s22:js"))).thenReturn(s22SHA); - when(scriptJedis.evalsha(anyString(), eq(2), eq("pollScriptKey"), eq("s33:script:脚本s33"))).thenReturn(s33SHA); + when(scriptClient.evalSha(anyString(), eq("pollScriptKey"), eq("s11:script:脚本s11:groovy"))).thenReturn(s11SHA).thenReturn(changeS11SHA); + when(scriptClient.evalSha(anyString(), eq("pollScriptKey"), eq("s22:script:脚本s22:js"))).thenReturn(s22SHA); + when(scriptClient.evalSha(anyString(), eq("pollScriptKey"), eq("s33:script:脚本s33"))).thenReturn(s33SHA); //测试修改前的script LiteflowResponse response = flowExecutor.execute2Resp("chain22", "arg"); diff --git a/pom.xml b/pom.xml index 526c33bd..2b0a5e20 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,6 @@ 2.11.0 1.3.5 3.21.0 - 4.3.1 5.8.18 From b5452dec69219e602be645a61ed0d443e4b5888d Mon Sep 17 00:00:00 2001 From: houxinyu Date: Tue, 15 Aug 2023 17:02:49 +0800 Subject: [PATCH 35/41] fix test --- .../com/yomahub/liteflow/parser/redis/mode/RClient.java | 2 +- .../test/redis/RedisWithXmlELPollSpringbootTest.java | 7 ------- .../test/redis/RedisWithXmlELSubscribeSpringbootTest.java | 6 ------ 3 files changed, 1 insertion(+), 14 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RClient.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RClient.java index 6d9afbce..cfa4a1bf 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RClient.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RClient.java @@ -97,7 +97,7 @@ public class RClient { /** * Executes Lua script stored in Redis scripts cache by SHA-1 digest - * @param shaDigest script cache by sha-1 + * @param shaDigest script cache by SHA-1 * @param args script args * @return string */ diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java index 5119b726..7ce8d5c7 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java @@ -16,8 +16,6 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.ComponentScan; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; -import redis.clients.jedis.Jedis; - import javax.annotation.Resource; import java.util.HashSet; import java.util.Set; @@ -47,11 +45,6 @@ public class RedisWithXmlELPollSpringbootTest extends BaseTest { @Resource private FlowExecutor flowExecutor; - @BeforeEach - public void setUp() { - MockitoAnnotations.initMocks(this); - } - @AfterEach public void after() { FlowBus.cleanCache(); diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java index efc161a6..a7fb0198 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java @@ -24,7 +24,6 @@ import javax.annotation.Resource; import java.util.HashMap; import java.util.Map; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; /** @@ -49,11 +48,6 @@ public class RedisWithXmlELSubscribeSpringbootTest extends BaseTest { @Resource private FlowExecutor flowExecutor; - @BeforeEach - public void setUp() { - MockitoAnnotations.initMocks(this); - } - @AfterEach public void after() { FlowBus.cleanCache(); From 132729141df4650e1f77edb58d4ebd4d5bfa683d Mon Sep 17 00:00:00 2001 From: houxinyu Date: Wed, 16 Aug 2023 18:12:58 +0800 Subject: [PATCH 36/41] fix from cr --- .../redis/mode/polling/ChainPollingTask.java | 29 ++++++++++++------- .../mode/polling/RedisParserPollingMode.java | 14 ++++----- .../redis/mode/polling/ScriptPollingTask.java | 27 ++++++++++------- .../parser/redis/vo/RedisParserVO.java | 13 ++++++++- .../pom.xml | 1 + .../RedisWithXmlELPollSpringbootTest.java | 1 - .../redis/application-poll-xml.properties | 1 + 7 files changed, 56 insertions(+), 30 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java index 95b9c1b9..6b66d030 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ChainPollingTask.java @@ -5,6 +5,7 @@ import cn.hutool.crypto.digest.DigestUtil; import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.log.LFLog; +import com.yomahub.liteflow.log.LFLoggerManager; import com.yomahub.liteflow.parser.redis.mode.RClient; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; @@ -16,7 +17,7 @@ import java.util.*; * @author hxinyu * @since 2.11.0 */ -public class ChainPollingTask { +public class ChainPollingTask implements Runnable { private RedisParserVO redisParserVO; @@ -26,24 +27,29 @@ public class ChainPollingTask { private Map chainSHAMap; - LFLog LOG; + private String keyLua; - public ChainPollingTask(RedisParserVO redisParserVO, RClient chainClient, Integer chainNum, Map chainSHAMap, LFLog LOG) { + private String valueLua; + + LFLog LOG = LFLoggerManager.getLogger(ChainPollingTask.class); + + public ChainPollingTask(RedisParserVO redisParserVO, RClient chainClient, Integer chainNum, Map chainSHAMap, String keyLua, String valueLua) { this.redisParserVO = redisParserVO; this.chainClient = chainClient; this.chainNum = chainNum; this.chainSHAMap = chainSHAMap; - this.LOG = LOG; + this.keyLua = keyLua; + this.valueLua = valueLua; } - /** - * 用于返回chain轮询任务的Runnable实例 + * 用于返回chain轮询任务 * 先根据hash中value的SHA值修改变化的和被删除的chain * 再根据hash中field数量的变化拉取新增的chain */ - public Runnable pollChainTask(String keyLua, String valueLua) { - Runnable r = () -> { + @Override + public void run() { + try { String chainKey = redisParserVO.getChainKey(); //Lua获取chainKey中最新的chain数量 String keyNum = chainClient.evalSha(keyLua, chainKey); @@ -52,7 +58,7 @@ public class ChainPollingTask { List needDelete = new ArrayList<>(); //遍历Map,判断各个chain的value有无变化:修改变化了值的chain和被删除的chain - for(Map.Entry entry: chainSHAMap.entrySet()) { + for (Map.Entry entry : chainSHAMap.entrySet()) { String chainId = entry.getKey(); String oldSHA = entry.getValue(); //在redis服务端通过Lua脚本计算SHA值 @@ -101,7 +107,8 @@ public class ChainPollingTask { } } } - }; - return r; + } catch (Exception e) { + LOG.error("[Exception during chain polling] " + e.getMessage(), e); + } } } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java index 318994a8..c5d93368 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java @@ -44,7 +44,7 @@ public class RedisParserPollingMode implements RedisParserHelper { private Map scriptSHAMap = new HashMap<>(); //定时任务线程池核心线程数 - private static final int CORE_POOL_SIZE = 1; + private static final int CORE_POOL_SIZE = 2; //计算hash中field数量的lua脚本 private final String luaOfKey = "local keys = redis.call(\"hkeys\", KEYS[1]);\n" + @@ -187,9 +187,9 @@ public class RedisParserPollingMode implements RedisParserHelper { new ThreadPoolExecutor.DiscardOldestPolicy()); //添加轮询chain的定时任务 - ChainPollingTask chainTask = new ChainPollingTask(redisParserVO, chainClient, chainNum, chainSHAMap, LOG); - pollExecutor.scheduleAtFixedRate(chainTask.pollChainTask(keyLuaOfChain, valueLuaOfChain), - 60, redisParserVO.getPollingInterval().longValue(), TimeUnit.SECONDS); + ChainPollingTask chainTask = new ChainPollingTask(redisParserVO, chainClient, chainNum, chainSHAMap, keyLuaOfChain, valueLuaOfChain); + pollExecutor.scheduleAtFixedRate(chainTask, redisParserVO.getPollingStartTime().longValue(), + redisParserVO.getPollingInterval().longValue(), TimeUnit.SECONDS); //如果有脚本 if (ObjectUtil.isNotNull(scriptClient) && ObjectUtil.isNotNull(redisParserVO.getScriptDataBase()) @@ -199,9 +199,9 @@ public class RedisParserPollingMode implements RedisParserHelper { String valueLuaOfScript = scriptClient.scriptLoad(luaOfValue); //添加轮询script的定时任务 - ScriptPollingTask scriptTask = new ScriptPollingTask(redisParserVO, scriptClient, scriptNum, scriptSHAMap, LOG); - pollExecutor.scheduleAtFixedRate(scriptTask.pollScriptTask(keyLuaOfScript, valueLuaOfScript), - 60, redisParserVO.getPollingInterval().longValue(), TimeUnit.SECONDS); + ScriptPollingTask scriptTask = new ScriptPollingTask(redisParserVO, scriptClient, scriptNum, scriptSHAMap, keyLuaOfScript, valueLuaOfScript); + pollExecutor.scheduleAtFixedRate(scriptTask, redisParserVO.getPollingStartTime().longValue(), + redisParserVO.getPollingInterval().longValue(), TimeUnit.SECONDS); } } } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java index f53a62b0..a23965c3 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java @@ -4,6 +4,7 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.digest.DigestUtil; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.log.LFLog; +import com.yomahub.liteflow.log.LFLoggerManager; import com.yomahub.liteflow.parser.redis.mode.RClient; import com.yomahub.liteflow.parser.redis.mode.RedisParserHelper; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; @@ -19,7 +20,7 @@ import java.util.Set; * @author hxinyu * @since 2.11.0 */ -public class ScriptPollingTask { +public class ScriptPollingTask implements Runnable { private RedisParserVO redisParserVO; @@ -29,24 +30,29 @@ public class ScriptPollingTask { private Map scriptSHAMap; - LFLog LOG; + private String keyLua; - public ScriptPollingTask(RedisParserVO redisParserVO, RClient scriptClient, Integer scriptNum, Map scriptSHAMap, LFLog LOG) { + private String valueLua; + + LFLog LOG = LFLoggerManager.getLogger(ScriptPollingTask.class); + + public ScriptPollingTask(RedisParserVO redisParserVO, RClient scriptClient, Integer scriptNum, Map scriptSHAMap, String keyLua, String valueLua) { this.redisParserVO = redisParserVO; this.scriptClient = scriptClient; this.scriptNum = scriptNum; this.scriptSHAMap = scriptSHAMap; - this.LOG = LOG; + this.keyLua = keyLua; + this.valueLua = valueLua; } - /** - * 用于返回script轮询任务的Runnable实例 + * 用于返回script轮询任务 * 首先根据hash中field数量的变化拉取新增的script * 再根据hash中value的SHA值修改变化的和被删除的script */ - public Runnable pollScriptTask(String keyLua, String valueLua) { - Runnable r = () -> { + @Override + public void run() { + try { String scriptKey = redisParserVO.getScriptKey(); //Lua获取scriptKey中最新的script数量 String keyNum = scriptClient.evalSha(keyLua, scriptKey); @@ -105,7 +111,8 @@ public class ScriptPollingTask { } } } - }; - return r; + } catch (Exception e) { + LOG.error("[Exception during script polling] " + e.getMessage(), e); + } } } \ No newline at end of file diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java index beeee195..9ec2026f 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java @@ -23,9 +23,12 @@ public class RedisParserVO { /*监听机制 轮询为poll 订阅为subscribe 默认为poll*/ private RedisParserMode mode = RedisParserMode.POLL; - /*轮询时间间隔(s) 默认1分钟 若选择订阅机制可不配置*/ + /*轮询时间间隔(s) 默认60s 若选择订阅机制可不配置*/ private Integer pollingInterval = 60; + /*规则配置后首次轮询的起始时间 默认为60s 若选择订阅机制可不配置*/ + private Integer pollingStartTime = 60; + /*chain表配置的数据库号*/ private Integer chainDataBase; @@ -77,6 +80,14 @@ public class RedisParserVO { } } + public Integer getPollingStartTime() { + return pollingStartTime; + } + + public void setPollingStartTime(Integer pollingStartTime) { + this.pollingStartTime = pollingStartTime; + } + public Integer getPollingInterval() { return pollingInterval; } diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/pom.xml b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/pom.xml index 90fe5ef9..4b493d8a 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/pom.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/pom.xml @@ -43,6 +43,7 @@ ${revision} test + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java index 7ce8d5c7..45103a0f 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java @@ -9,7 +9,6 @@ import com.yomahub.liteflow.slot.DefaultContext; import com.yomahub.liteflow.test.BaseTest; import org.junit.jupiter.api.*; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.MockitoAnnotations; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-poll-xml.properties b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-poll-xml.properties index c89b0866..567bff7b 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-poll-xml.properties +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-poll-xml.properties @@ -2,6 +2,7 @@ liteflow.rule-source-ext-data={\ "host":"localhost",\ "port":6379,\ "pollingInterval":1,\ + "pollingStartTime":1,\ "chainDataBase":1,\ "chainKey":"pollChainKey",\ "scriptDataBase":1,\ From bf2e7c3ba0ddd4048ef6ed52673aee0d9b1ac61f Mon Sep 17 00:00:00 2001 From: houxinyu Date: Thu, 17 Aug 2023 16:56:36 +0800 Subject: [PATCH 37/41] fix poll test & fix from cr --- .../mode/polling/RedisParserPollingMode.java | 17 +++++-- .../RedisWithXmlELPollSpringbootTest.java | 47 +++++++++++++++---- ...RedisWithXmlELSubscribeSpringbootTest.java | 2 - 3 files changed, 50 insertions(+), 16 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java index c5d93368..ae4d2ee3 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java @@ -2,6 +2,7 @@ package com.yomahub.liteflow.parser.redis.mode.polling; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.thread.NamedThreadFactory; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.digest.DigestUtil; @@ -46,6 +47,9 @@ public class RedisParserPollingMode implements RedisParserHelper { //定时任务线程池核心线程数 private static final int CORE_POOL_SIZE = 2; + //定时任务线程池 + private ScheduledThreadPoolExecutor pollExecutor; + //计算hash中field数量的lua脚本 private final String luaOfKey = "local keys = redis.call(\"hkeys\", KEYS[1]);\n" + "return #keys;\n"; @@ -79,6 +83,14 @@ public class RedisParserPollingMode implements RedisParserHelper { this.scriptClient = new RClient(Redisson.create(config)); } } + //创建定时任务线程池 + if (ObjectUtil.isNull(pollExecutor)) { + ThreadFactory namedThreadFactory = new NamedThreadFactory("RedisParser-Polling-Thread-", false); + pollExecutor = new ScheduledThreadPoolExecutor( + CORE_POOL_SIZE, + namedThreadFactory, + new ThreadPoolExecutor.DiscardOldestPolicy()); + } } catch (Exception e) { throw new RedisException(e.getMessage()); @@ -181,11 +193,6 @@ public class RedisParserPollingMode implements RedisParserHelper { String keyLuaOfChain = chainClient.scriptLoad(luaOfKey); String valueLuaOfChain = chainClient.scriptLoad(luaOfValue); - //定时任务线程池 - ScheduledThreadPoolExecutor pollExecutor = new ScheduledThreadPoolExecutor( - CORE_POOL_SIZE, - new ThreadPoolExecutor.DiscardOldestPolicy()); - //添加轮询chain的定时任务 ChainPollingTask chainTask = new ChainPollingTask(redisParserVO, chainClient, chainNum, chainSHAMap, keyLuaOfChain, valueLuaOfChain); pollExecutor.scheduleAtFixedRate(chainTask, redisParserVO.getPollingStartTime().longValue(), diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java index 45103a0f..18786d42 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java @@ -44,6 +44,20 @@ public class RedisWithXmlELPollSpringbootTest extends BaseTest { @Resource private FlowExecutor flowExecutor; + //计算hash中field数量的lua脚本 + private final String luaOfKey = "local keys = redis.call(\"hkeys\", KEYS[1]);\n" + + "return #keys;\n"; + + //计算hash中value的SHA值的lua脚本 + private final String luaOfValue = "local key = KEYS[1];\n" + + "local field = KEYS[2];\n" + + "local value, err = redis.call(\"hget\", key, field);\n" + + "if value == false or value == nil then\n" + + " return \"nil\";\n" + + "end\n" + + "local sha1 = redis.sha1hex(value);\n" + + "return sha1;"; + @AfterEach public void after() { FlowBus.cleanCache(); @@ -53,7 +67,7 @@ public class RedisWithXmlELPollSpringbootTest extends BaseTest { * 测试chain */ @Test - public void testPollWithXml() { + public void testPollWithXml() throws InterruptedException { Set chainNameSet = new HashSet<>(); chainNameSet.add("chain11"); String chainValue = "THEN(a, b, c);"; @@ -65,14 +79,22 @@ public class RedisWithXmlELPollSpringbootTest extends BaseTest { String changeChainSHA = DigestUtil.sha1Hex(changeChainValue); when(chainClient.hkeys("pollChainKey")).thenReturn(chainNameSet); when(chainClient.hget("pollChainKey", "chain11")).thenReturn(chainValue).thenReturn(changeChainValue); - when(chainClient.evalSha(anyString(), anyString())).thenReturn(chainSHA).thenReturn(changeChainSHA); + when(chainClient.scriptLoad(luaOfKey)).thenReturn("keysha"); + when(chainClient.scriptLoad(luaOfValue)).thenReturn("valuesha"); + when(chainClient.evalSha(eq("keysha"), anyString())).thenReturn("1"); + when(chainClient.evalSha(eq("valuesha"), anyString(), anyString())).thenReturn(chainSHA).thenReturn(changeChainSHA); + //这里其实并没有script数据 预设数据只是为了不产生NumberFormatException + when(scriptClient.scriptLoad(luaOfKey)).thenReturn("keysha"); + when(scriptClient.scriptLoad(luaOfValue)).thenReturn("valuesha"); + when(scriptClient.evalSha(eq("keysha"), anyString())).thenReturn("0"); + when(scriptClient.evalSha(eq("valuesha"), anyString(), anyString())).thenReturn(""); //测试修改前的chain LiteflowResponse response = flowExecutor.execute2Resp("chain11", "arg"); Assertions.assertTrue(response.isSuccess()); Assertions.assertEquals("a==>b==>c", response.getExecuteStepStr()); - flowExecutor.reloadRule(); + Thread.sleep(2000); //测试修改后的chain response = flowExecutor.execute2Resp("chain11", "arg"); @@ -84,12 +106,16 @@ public class RedisWithXmlELPollSpringbootTest extends BaseTest { * 测试script */ @Test - public void testPollWithScriptXml() { + public void testPollWithScriptXml() throws InterruptedException { Set chainNameSet = new HashSet<>(); chainNameSet.add("chain22"); String chainValue = "THEN(a, b, c, s11, s22, s33);"; when(chainClient.hkeys("pollChainKey")).thenReturn(chainNameSet); when(chainClient.hget("pollChainKey", "chain22")).thenReturn(chainValue); + when(chainClient.scriptLoad(luaOfKey)).thenReturn("keysha"); + when(chainClient.scriptLoad(luaOfValue)).thenReturn("valuesha"); + when(chainClient.evalSha(eq("keysha"), anyString())).thenReturn("1"); + when(chainClient.evalSha(eq("valuesha"), anyString(), anyString())).thenReturn(""); Set scriptFieldSet = new HashSet<>(); scriptFieldSet.add("s11:script:脚本s11:groovy"); @@ -111,9 +137,12 @@ public class RedisWithXmlELPollSpringbootTest extends BaseTest { when(scriptClient.hget("pollScriptKey", "s22:script:脚本s22:js")).thenReturn(s22); when(scriptClient.hget("pollScriptKey", "s33:script:脚本s33")).thenReturn(s33); //分别模拟三个script的evalsha指纹值计算的返回值, 其中s11脚本修改 指纹值变化 - when(scriptClient.evalSha(anyString(), eq("pollScriptKey"), eq("s11:script:脚本s11:groovy"))).thenReturn(s11SHA).thenReturn(changeS11SHA); - when(scriptClient.evalSha(anyString(), eq("pollScriptKey"), eq("s22:script:脚本s22:js"))).thenReturn(s22SHA); - when(scriptClient.evalSha(anyString(), eq("pollScriptKey"), eq("s33:script:脚本s33"))).thenReturn(s33SHA); + when(scriptClient.scriptLoad(luaOfKey)).thenReturn("keysha"); + when(scriptClient.scriptLoad(luaOfValue)).thenReturn("valuesha"); + when(scriptClient.evalSha(eq("keysha"), anyString())).thenReturn("3"); + when(scriptClient.evalSha("valuesha", "pollScriptKey", "s11:script:脚本s11:groovy")).thenReturn(s11SHA).thenReturn(changeS11SHA); + when(scriptClient.evalSha("valuesha", "pollScriptKey", "s22:script:脚本s22:js")).thenReturn(s22SHA); + when(scriptClient.evalSha("valuesha", "pollScriptKey", "s33:script:脚本s33")).thenReturn(s33SHA); //测试修改前的script LiteflowResponse response = flowExecutor.execute2Resp("chain22", "arg"); @@ -123,11 +152,11 @@ public class RedisWithXmlELPollSpringbootTest extends BaseTest { Assertions.assertEquals("hello s22", context.getData("test22")); Assertions.assertEquals("a==>b==>c==>s11[脚本s11]==>s22[脚本s22]==>s33[脚本s33]", response.getExecuteStepStrWithoutTime()); - flowExecutor.reloadRule(); + Thread.sleep(2000); //测试修改后的script response = flowExecutor.execute2Resp("chain22", "arg"); - context = response.getFirstContextBean(); + context = response.getFirstContextBean(); Assertions.assertTrue(response.isSuccess()); Assertions.assertEquals("hello world", context.getData("test11")); } diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java index a7fb0198..f926789e 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java @@ -8,10 +8,8 @@ import com.yomahub.liteflow.slot.DefaultContext; import com.yomahub.liteflow.test.BaseTest; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.MockitoAnnotations; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; From d3db18390325a6b1e764de7aa7005c91434be8bd Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sat, 19 Aug 2023 19:33:11 +0800 Subject: [PATCH 38/41] =?UTF-8?q?=E4=BC=98=E5=8C=96redis=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pom.xml | 1 + .../redis/RedisSubscribeTestCondition.java | 31 +++ ...RedisWithXmlELSubscribeSpringbootTest.java | 205 ++++++++++++------ 3 files changed, 173 insertions(+), 64 deletions(-) create mode 100644 liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisSubscribeTestCondition.java diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/pom.xml b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/pom.xml index 4b493d8a..d64a3121 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/pom.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/pom.xml @@ -35,6 +35,7 @@ com.yomahub liteflow-script-groovy ${revision} + test diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisSubscribeTestCondition.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisSubscribeTestCondition.java new file mode 100644 index 00000000..724e8df7 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisSubscribeTestCondition.java @@ -0,0 +1,31 @@ +package com.yomahub.liteflow.test.redis; + +import cn.hutool.core.util.StrUtil; +import org.redisson.Redisson; +import org.redisson.api.RedissonClient; +import org.redisson.api.redisnode.RedisNodes; +import org.redisson.api.redisnode.RedisSingle; +import org.redisson.config.Config; + +import java.util.concurrent.TimeUnit; + +/** + * 判断本地6379端口是否启动了Redis + */ +public class RedisSubscribeTestCondition { + + /** + * @return true为本地未启动Redis + */ + public static boolean notStartRedis() { + try{ + Config config = new Config(); + config.useSingleServer().setAddress("redis://127.0.0.1:6379"); + RedissonClient redissonClient = Redisson.create(config); + RedisSingle redisNode = redissonClient.getRedisNodes(RedisNodes.SINGLE); + return !redisNode.pingAll(15000, TimeUnit.MICROSECONDS); + } catch (Exception e) { + return true; + } + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java index f926789e..0d815d23 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java @@ -1,118 +1,195 @@ package com.yomahub.liteflow.test.redis; +import cn.hutool.core.util.ObjectUtil; import com.yomahub.liteflow.core.FlowExecutor; -import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.flow.LiteflowResponse; -import com.yomahub.liteflow.parser.redis.mode.RClient; +import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.property.LiteflowConfigGetter; import com.yomahub.liteflow.slot.DefaultContext; import com.yomahub.liteflow.test.BaseTest; -import org.junit.jupiter.api.AfterEach; +import com.yomahub.liteflow.util.JsonUtil; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.redisson.Redisson; +import org.redisson.api.RMapCache; +import org.redisson.api.RedissonClient; +import org.redisson.config.Config; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.ComponentScan; import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.DisabledIf; +import org.springframework.test.context.junit.jupiter.DisabledIfCondition; import org.springframework.test.context.junit.jupiter.SpringExtension; import javax.annotation.Resource; -import java.util.HashMap; -import java.util.Map; - -import static org.mockito.Mockito.when; - /** * springboot环境下的redis配置源订阅模式功能测试 * + * 由于redisson中RMapCache监听器功能无法mock测试 + * 故Sub模式测试用例需本地启动Redis服务 连接地址: 127.0.0.1:6379 + * 若本地该端口号未启动Redis服务 则自动忽略本类中测试用例 + * * @author hxinyu * @since 2.11.0 */ -@ExtendWith(SpringExtension.class) +@ExtendWith({SpringExtension.class, DisabledIfCondition.class}) @TestPropertySource(value = "classpath:/redis/application-sub-xml.properties") @SpringBootTest(classes = RedisWithXmlELSubscribeSpringbootTest.class) @EnableAutoConfiguration @ComponentScan({"com.yomahub.liteflow.test.redis.cmp"}) +@DisabledIf("#{T(com.yomahub.liteflow.test.redis.RedisSubscribeTestCondition).notStartRedis()}") public class RedisWithXmlELSubscribeSpringbootTest extends BaseTest { - @MockBean(name = "chainClient") - private static RClient chainClient; - - @MockBean(name = "scriptClient") - private static RClient scriptClient; + private static RedissonClient redissonClient; @Resource private FlowExecutor flowExecutor; - @AfterEach - public void after() { - FlowBus.cleanCache(); + @BeforeAll + public static void setUpBeforeClass() { + Config config = new Config(); + config.useSingleServer().setAddress("redis://127.0.0.1:6379").setDatabase(1); + redissonClient = Redisson.create(config); + RMapCache chainKey = redissonClient.getMapCache("chainKey"); + RMapCache scriptKey = redissonClient.getMapCache("scriptKey"); + scriptKey.put("s1:script:脚本s1:groovy", "defaultContext.setData(\"test1\",\"hello s1\");"); + scriptKey.put("s2:script:脚本s2:js", "defaultContext.setData(\"test2\",\"hello s2\");"); + scriptKey.put("s3:script:脚本s3", "defaultContext.setData(\"test3\",\"hello s3\");"); + chainKey.put("chain1", "THEN(a, b, c);"); + chainKey.put("chain2", "THEN(a, b, c, s3);"); + chainKey.put("chain3", "THEN(a, b, c, s1, s2);"); + } + + @AfterAll + public static void after(){ + System.out.println("after"); + testCleanData(); } /** - * 测试 chain + * 测试chain */ @Test - public void testSubWithXml() { - Map chainMap = new HashMap<>(); - chainMap.put("chain1", "THEN(a, b, c);"); - //修改chain值 - Map changeChainMap = new HashMap<>(); - changeChainMap.put("chain1", "THEN(a, c);"); - when(chainClient.getMap("chainKey")).thenReturn(chainMap).thenReturn(changeChainMap); - - //测试修改前的chain + public void testSubWithXml() throws InterruptedException { LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); Assertions.assertTrue(response.isSuccess()); Assertions.assertEquals("a==>b==>c", response.getExecuteStepStr()); - flowExecutor.reloadRule(); + //修改redis中规则 + changeXMLData(); + //重新加载规则 + Thread.sleep(50); + Assertions.assertEquals("a==>c==>b", flowExecutor.execute2Resp("chain1", "arg").getExecuteStepStr()); - //测试修改后的chain + //删除redis中规则 + deleteXMLData(); + //重新加载规则 + Thread.sleep(50); response = flowExecutor.execute2Resp("chain1", "arg"); - Assertions.assertTrue(response.isSuccess()); - Assertions.assertEquals("a==>c", response.getExecuteStepStr()); + Assertions.assertTrue(!response.isSuccess()); + + //添加redis中规则 + addXMLData(); + //重新加载规则 + Thread.sleep(50); + Assertions.assertEquals("b==>c", flowExecutor.execute2Resp("chain4", "arg").getExecuteStepStr()); } + /** + * 测试script + */ @Test - public void testSubWithScriptXml() { - Map chainMap = new HashMap<>(); - chainMap.put("chain2", "THEN(a, b, c, s1, s2, s3);"); - - Map scriptMap = new HashMap<>(); - scriptMap.put("s1:script:脚本s1:groovy", "defaultContext.setData(\"test1\",\"hello s1\");"); - scriptMap.put("s2:script:脚本s2:js", "defaultContext.setData(\"test2\",\"hello s2\");"); - scriptMap.put("s3:script:脚本s3", "defaultContext.setData(\"test3\",\"hello s3\");"); - //修改chain值和script值 - Map changeChainMap = new HashMap<>(); - changeChainMap.put("chain2", "THEN(a, c, s1, s3);"); - Map changeScriptMap = new HashMap<>(); - changeScriptMap.put("s1:script:脚本s1:groovy", "defaultContext.setData(\"test1\",\"hello world\");"); - changeScriptMap.put("s2:script:脚本s2:js", "defaultContext.setData(\"test2\",\"hello s2\");"); - changeScriptMap.put("s3:script:脚本s3", "defaultContext.setData(\"test3\",\"hello s3\");"); - - when(chainClient.getMap("chainKey")).thenReturn(chainMap).thenReturn(changeChainMap); - //这里是因为脚本的getMap方法在一次流程里会执行到两次 - when(scriptClient.getMap("scriptKey")).thenReturn(scriptMap).thenReturn(scriptMap) - .thenReturn(changeScriptMap).thenReturn(changeScriptMap); - - //测试修改前的chain和script - LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg"); + public void testSubWithScriptXml() throws InterruptedException { + LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg"); DefaultContext context = response.getFirstContextBean(); Assertions.assertTrue(response.isSuccess()); Assertions.assertEquals("hello s1", context.getData("test1")); - Assertions.assertEquals("hello s2", context.getData("test2")); - Assertions.assertEquals("a==>b==>c==>s1[脚本s1]==>s2[脚本s2]==>s3[脚本s3]", response.getExecuteStepStrWithoutTime()); + Assertions.assertEquals("a==>b==>c==>s1[脚本s1]==>s2[脚本s2]", response.getExecuteStepStrWithoutTime()); - flowExecutor.reloadRule(); + //添加和删除脚本 + addAndDeleteScriptData(); + //修改redis脚本 + changeScriptData(); + Thread.sleep(50); + context = flowExecutor.execute2Resp("chain3", "arg").getFirstContextBean(); + Assertions.assertEquals("hello s1 version2", context.getData("test1")); + context = flowExecutor.execute2Resp("chain2", "arg").getFirstContextBean(); + Assertions.assertEquals("hello s3 version2", context.getData("test2")); + } - //测试修改后的chain和script - response = flowExecutor.execute2Resp("chain2", "arg"); - context = response.getFirstContextBean(); - Assertions.assertTrue(response.isSuccess()); - Assertions.assertEquals("hello world", context.getData("test1")); - Assertions.assertEquals("a==>c==>s1[脚本s1]==>s3[脚本s3]", response.getExecuteStepStrWithoutTime()); + /** + * 修改redisson中的chain + */ + public void changeXMLData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + RMapCache chainKey = redissonClient.getMapCache(redisParserVO.getChainKey()); + chainKey.put("chain1", "THEN(a, c, b);"); + } + + /** + * 删除redisson中的chain + */ + public void deleteXMLData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + RMapCache chainKey = redissonClient.getMapCache(redisParserVO.getChainKey()); + chainKey.remove("chain1"); + chainKey.remove("chain4"); + } + + /** + * 新增redisson中的chain + */ + public void addXMLData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + RMapCache chainKey = redissonClient.getMapCache(redisParserVO.getChainKey()); + chainKey.put("chain4","THEN(b, c);"); + } + + /** + * 修改redisson中的脚本 + */ + public void changeScriptData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + RMapCache scriptKey = redissonClient.getMapCache(redisParserVO.getScriptKey()); + scriptKey.put("s1:script:脚本s1:groovy", "defaultContext.setData(\"test1\",\"hello s1 version2\");"); + scriptKey.put("s3:script:脚本s3", "defaultContext.setData(\"test2\",\"hello s3 version2\");"); + } + + /** + * 新增和删除redisson中的chain + */ + public void addAndDeleteScriptData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + RedisParserVO redisParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), RedisParserVO.class); + RMapCache scriptKey = redissonClient.getMapCache(redisParserVO.getScriptKey()); + scriptKey.remove("s3:script:脚本s3"); + scriptKey.put("s5:script:脚本s5:groovy", "defaultContext.setData(\"test1\",\"hello s5\");"); + } + + //redis内规则数据数据清空 + public static void testCleanData(){ + if(ObjectUtil.isNotNull(redissonClient)){ + RMapCache scriptKey = redissonClient.getMapCache("chainKey"); + RMapCache chainKey = redissonClient.getMapCache("scriptKey"); + for (String key : chainKey.keySet()) { + chainKey.remove(key); + } + for (String key : scriptKey.keySet()) { + scriptKey.remove(key); + } + chainKey.keySet().forEach(System.out::println); + System.out.println(""); + scriptKey.keySet().forEach(System.out::println); + } } } From 325cec7113b536792446eee364b56c278af09325 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sun, 20 Aug 2023 02:11:28 +0800 Subject: [PATCH 39/41] add sentinel mode --- .../liteflow/parser/redis/mode/RedisMode.java | 27 +++++++ .../parser/redis/mode/RedisParserHelper.java | 53 ++++++++++-- .../parser/redis/mode/RedisParserMode.java | 3 +- .../mode/polling/RedisParserPollingMode.java | 29 +++++-- .../subscribe/RedisParserSubscribeMode.java | 29 +++++-- .../parser/redis/vo/RedisParserVO.java | 80 ++++++++++++++++++- .../redis/RedisSubscribeTestCondition.java | 31 ------- 7 files changed, 199 insertions(+), 53 deletions(-) create mode 100644 liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisMode.java delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisSubscribeTestCondition.java diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisMode.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisMode.java new file mode 100644 index 00000000..ce561042 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisMode.java @@ -0,0 +1,27 @@ +package com.yomahub.liteflow.parser.redis.mode; + +/** + * 用于定义Redis模式的枚举类 + * + * single单点模式, sentinel哨兵模式 + * 不支持集群模式配置 + * + * @author hxinyu + * @since 2.11.0 + */ +public enum RedisMode { + + SINGLE("single"), + + SENTINEL("sentinel"); + + private String mode; + + RedisMode(String mode) { + this.mode = mode; + } + + public String getMode() { + return mode; + } +} diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java index 356e86a5..eb60d2cd 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java @@ -10,6 +10,7 @@ import com.yomahub.liteflow.log.LFLog; import com.yomahub.liteflow.log.LFLoggerManager; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import org.redisson.config.Config; +import org.redisson.config.SentinelServersConfig; import java.util.List; @@ -24,7 +25,9 @@ public interface RedisParserHelper { LFLog LOG = LFLoggerManager.getLogger(RedisParserHelper.class); - String REDIS_URL_PATTERN = "redis://{}:{}"; + String SINGLE_REDIS_URL_PATTERN = "redis://{}:{}"; + + String SENTINEL_REDIS_URL_PATTERN = "redis://{}"; String CHAIN_XML_PATTERN = "{}"; @@ -42,16 +45,23 @@ public interface RedisParserHelper { /** - * 获取Redisson客户端的Config配置通用方法 + * 获取Redisson客户端的Config配置通用方法(单点模式) * @param redisParserVO redisParserVO - * @param dataBase redisson连接的数据库号 + * @param dataBase redis连接的数据库号 * @return redisson config */ - default Config getRedissonConfig(RedisParserVO redisParserVO, Integer dataBase) { + default Config getSingleRedissonConfig(RedisParserVO redisParserVO, Integer dataBase) { Config config = new Config(); - String redisAddress = StrFormatter.format(REDIS_URL_PATTERN, redisParserVO.getHost(), redisParserVO.getPort()); + String redisAddress = StrFormatter.format(SINGLE_REDIS_URL_PATTERN, redisParserVO.getHost(), redisParserVO.getPort()); + //如果配置了用户名和密码 + if (StrUtil.isNotBlank(redisParserVO.getUsername()) && StrUtil.isNotBlank(redisParserVO.getPassword())) { + config.useSingleServer().setAddress(redisAddress) + .setUsername(redisParserVO.getUsername()) + .setPassword(redisParserVO.getPassword()) + .setDatabase(dataBase); + } //如果配置了密码 - if (StrUtil.isNotBlank(redisParserVO.getPassword())) { + else if (StrUtil.isNotBlank(redisParserVO.getPassword())) { config.useSingleServer().setAddress(redisAddress) .setPassword(redisParserVO.getPassword()) .setDatabase(dataBase); @@ -64,6 +74,37 @@ public interface RedisParserHelper { return config; } + /** + * 获取Redisson客户端的Config配置通用方法(哨兵模式) + * @param redisParserVO redisParserVO + * @param dataBase redis连接的数据库号 + * @return redisson Config + */ + default Config getSentinelRedissonConfig(RedisParserVO redisParserVO, Integer dataBase) { + Config config = new Config(); + SentinelServersConfig sentinelConfig = config.useSentinelServers() + .setMasterName(redisParserVO.getMasterName()); + redisParserVO.getSentinelAddress().forEach(address -> { + sentinelConfig.addSentinelAddress(StrFormatter.format(SENTINEL_REDIS_URL_PATTERN, address)); + }); + //如果配置了用户名和密码 + if(StrUtil.isNotBlank(redisParserVO.getUsername()) && StrUtil.isNotBlank(redisParserVO.getPassword())) { + sentinelConfig.setUsername(redisParserVO.getUsername()) + .setPassword(redisParserVO.getPassword()) + .setDatabase(dataBase); + } + //如果配置了密码 + else if(StrUtil.isNotBlank(redisParserVO.getPassword())) { + sentinelConfig.setPassword(redisParserVO.getPassword()) + .setDatabase(dataBase); + } + //没有配置密码 + else { + sentinelConfig.setDatabase(dataBase); + } + return config; + } + /** * script节点的修改/添加 * diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserMode.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserMode.java index 13c4b875..258229c6 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserMode.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserMode.java @@ -1,8 +1,9 @@ package com.yomahub.liteflow.parser.redis.mode; /** - * 用于定义redis规则存储和监听方式的枚举类 + * 用于定义Redis规则存储和监听方式的枚举类 * + * poll轮询拉取模式, sub监听模式 * @author hxinyu * @since 2.11.0 */ diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java index ae4d2ee3..b9c3b2ea 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java @@ -8,6 +8,7 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.digest.DigestUtil; import com.yomahub.liteflow.parser.redis.exception.RedisException; import com.yomahub.liteflow.parser.redis.mode.RClient; +import com.yomahub.liteflow.parser.redis.mode.RedisMode; import com.yomahub.liteflow.parser.redis.mode.RedisParserHelper; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import com.yomahub.liteflow.spi.holder.ContextAwareHolder; @@ -75,12 +76,28 @@ public class RedisParserPollingMode implements RedisParserHelper { catch (Exception ignored) { } if (ObjectUtil.isNull(chainClient)) { - Config config = getRedissonConfig(redisParserVO, redisParserVO.getChainDataBase()); - this.chainClient = new RClient(Redisson.create(config)); - //如果有脚本数据 - if (ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { - config = getRedissonConfig(redisParserVO, redisParserVO.getScriptDataBase()); - this.scriptClient = new RClient(Redisson.create(config)); + RedisMode redisMode = redisParserVO.getRedisMode(); + Config config; + //Redis单点模式 + if (redisMode.equals(RedisMode.SINGLE)){ + config = getSingleRedissonConfig(redisParserVO, redisParserVO.getChainDataBase()); + this.chainClient = new RClient(Redisson.create(config)); + //如果有脚本数据 + if (ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { + config = getSingleRedissonConfig(redisParserVO, redisParserVO.getScriptDataBase()); + this.scriptClient = new RClient(Redisson.create(config)); + } + } + + //Redis哨兵模式 + else if (redisMode.equals(RedisMode.SENTINEL)) { + config = getSentinelRedissonConfig(redisParserVO, redisParserVO.getChainDataBase()); + this.chainClient = new RClient(Redisson.create(config)); + //如果有脚本数据 + if (ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { + config = getSentinelRedissonConfig(redisParserVO, redisParserVO.getScriptDataBase()); + this.scriptClient = new RClient(Redisson.create(config)); + } } } //创建定时任务线程池 diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java index 67c9697f..b115baec 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java @@ -8,6 +8,7 @@ import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.parser.redis.exception.RedisException; import com.yomahub.liteflow.parser.redis.mode.RClient; +import com.yomahub.liteflow.parser.redis.mode.RedisMode; import com.yomahub.liteflow.parser.redis.mode.RedisParserHelper; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import com.yomahub.liteflow.spi.holder.ContextAwareHolder; @@ -48,12 +49,28 @@ public class RedisParserSubscribeMode implements RedisParserHelper { catch (Exception ignored) { } if (ObjectUtil.isNull(chainClient)) { - Config config = getRedissonConfig(redisParserVO, redisParserVO.getChainDataBase()); - this.chainClient = new RClient(Redisson.create(config)); - //如果有脚本数据 - if (ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { - config = getRedissonConfig(redisParserVO, redisParserVO.getScriptDataBase()); - this.scriptClient = new RClient(Redisson.create(config)); + RedisMode redisMode = redisParserVO.getRedisMode(); + Config config; + //Redis单点模式 + if (redisMode.equals(RedisMode.SINGLE)){ + config = getSingleRedissonConfig(redisParserVO, redisParserVO.getChainDataBase()); + this.chainClient = new RClient(Redisson.create(config)); + //如果有脚本数据 + if (ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { + config = getSingleRedissonConfig(redisParserVO, redisParserVO.getScriptDataBase()); + this.scriptClient = new RClient(Redisson.create(config)); + } + } + + //Redis哨兵模式 + else if (redisMode.equals(RedisMode.SENTINEL)) { + config = getSentinelRedissonConfig(redisParserVO, redisParserVO.getChainDataBase()); + this.chainClient = new RClient(Redisson.create(config)); + //如果有脚本数据 + if (ObjectUtil.isNotNull(redisParserVO.getScriptDataBase())) { + config = getSentinelRedissonConfig(redisParserVO, redisParserVO.getScriptDataBase()); + this.scriptClient = new RClient(Redisson.create(config)); + } } } } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java index 9ec2026f..7aeaecd7 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/vo/RedisParserVO.java @@ -1,9 +1,12 @@ package com.yomahub.liteflow.parser.redis.vo; +import com.yomahub.liteflow.parser.redis.mode.RedisMode; import com.yomahub.liteflow.parser.redis.mode.RedisParserMode; +import java.util.List; + /** - * 用于解析RuleSourceExtData的vo类,用于Redis模式中 + * 用于解析RuleSourceExtData的vo类, 用于Redis模式中 * * @author hxinyu * @since 2.11.0 @@ -11,12 +14,24 @@ import com.yomahub.liteflow.parser.redis.mode.RedisParserMode; public class RedisParserVO { - /*连接地址*/ + /*Redis配置模式 单点/哨兵, 默认为单点模式*/ + private RedisMode redisMode = RedisMode.SINGLE; + + /*单点模式 连接地址*/ private String host; - /*端口号*/ + /*单点模式 端口号*/ private Integer port; + /*哨兵模式 主节点名*/ + private String masterName; + + /*哨兵模式 哨兵节点连接地址 ip:port, 可配置多个*/ + private List sentinelAddress; + + /*用户名 需要Redis 6.0及以上*/ + private String username; + /*密码*/ private String password; @@ -41,6 +56,21 @@ public class RedisParserVO { /*脚本配置的键名 若没有脚本数据可不配置*/ private String scriptKey; + public void setRedisMode(String redisMode) { + redisMode = redisMode.toUpperCase(); + try{ + RedisMode m = RedisMode.valueOf(redisMode); + this.redisMode = m; + } + catch (Exception ignored) { + //转换出错默认为单点模式 + } + } + + public RedisMode getRedisMode() { + return redisMode; + } + public String getHost() { return host; } @@ -57,6 +87,30 @@ public class RedisParserVO { this.port = port; } + public String getMasterName() { + return masterName; + } + + public void setMasterName(String masterName) { + this.masterName = masterName; + } + + public List getSentinelAddress() { + return sentinelAddress; + } + + public void setSentinelAddress(List sentinelAddress) { + this.sentinelAddress = sentinelAddress; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + public String getPassword() { return password; } @@ -127,4 +181,24 @@ public class RedisParserVO { public void setScriptKey(String scriptKey) { this.scriptKey = scriptKey; } + + @Override + public String toString() { + return "RedisParserVO{" + + "redisMode=" + redisMode + + ", host='" + host + '\'' + + ", port=" + port + + ", masterName=" + masterName + + ", sentinelAddress=" + sentinelAddress + + ", username='" + username + '\'' + + ", password='" + password + '\'' + + ", mode=" + mode + + ", pollingInterval=" + pollingInterval + + ", pollingStartTime=" + pollingStartTime + + ", chainDataBase=" + chainDataBase + + ", chainKey='" + chainKey + '\'' + + ", scriptDataBase=" + scriptDataBase + + ", scriptKey='" + scriptKey + '\'' + + '}'; + } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisSubscribeTestCondition.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisSubscribeTestCondition.java deleted file mode 100644 index 724e8df7..00000000 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisSubscribeTestCondition.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.yomahub.liteflow.test.redis; - -import cn.hutool.core.util.StrUtil; -import org.redisson.Redisson; -import org.redisson.api.RedissonClient; -import org.redisson.api.redisnode.RedisNodes; -import org.redisson.api.redisnode.RedisSingle; -import org.redisson.config.Config; - -import java.util.concurrent.TimeUnit; - -/** - * 判断本地6379端口是否启动了Redis - */ -public class RedisSubscribeTestCondition { - - /** - * @return true为本地未启动Redis - */ - public static boolean notStartRedis() { - try{ - Config config = new Config(); - config.useSingleServer().setAddress("redis://127.0.0.1:6379"); - RedissonClient redissonClient = Redisson.create(config); - RedisSingle redisNode = redissonClient.getRedisNodes(RedisNodes.SINGLE); - return !redisNode.pingAll(15000, TimeUnit.MICROSECONDS); - } catch (Exception e) { - return true; - } - } -} From 3c5d22c62ce3fd6490ac3d0530988febdbc7fcbc Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sun, 20 Aug 2023 15:28:43 +0800 Subject: [PATCH 40/41] fix test --- .../mode/polling/RedisParserPollingMode.java | 2 +- .../redis/RedisSubscribeTestCondition.java | 29 +++++++++++++++++++ .../RedisWithXmlELPollSpringbootTest.java | 19 ++++++++---- ...RedisWithXmlELSubscribeSpringbootTest.java | 21 +++++++------- .../redis/application-poll-xml.properties | 4 +-- .../redis/application-sub-xml.properties | 4 +-- 6 files changed, 59 insertions(+), 20 deletions(-) create mode 100644 liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisSubscribeTestCondition.java diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java index b9c3b2ea..231b9907 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java @@ -102,7 +102,7 @@ public class RedisParserPollingMode implements RedisParserHelper { } //创建定时任务线程池 if (ObjectUtil.isNull(pollExecutor)) { - ThreadFactory namedThreadFactory = new NamedThreadFactory("RedisParser-Polling-Thread-", false); + ThreadFactory namedThreadFactory = new NamedThreadFactory("Redis-Polling-", false); pollExecutor = new ScheduledThreadPoolExecutor( CORE_POOL_SIZE, namedThreadFactory, diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisSubscribeTestCondition.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisSubscribeTestCondition.java new file mode 100644 index 00000000..82a307ef --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisSubscribeTestCondition.java @@ -0,0 +1,29 @@ +package com.yomahub.liteflow.test.redis; + +import org.redisson.Redisson; +import org.redisson.api.RedissonClient; +import org.redisson.api.redisnode.RedisNodes; +import org.redisson.api.redisnode.RedisSingle; +import org.redisson.config.Config; + +/** + * 判断本地是否启动Redis + * + * @author hxinyu + * @since 2.11.0 + */ +public class RedisSubscribeTestCondition { + + /* 若6379端口未启动Redis则返回true */ + public static boolean notStartRedis() { + try{ + Config config = new Config(); + config.useSingleServer().setAddress("redis://127.0.0.1:6379"); + RedissonClient redissonClient = Redisson.create(config); + RedisSingle redisNode = redissonClient.getRedisNodes(RedisNodes.SINGLE); + return !redisNode.pingAll(); + } catch (Exception e) { + return true; + } + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java index 18786d42..05749ee9 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELPollSpringbootTest.java @@ -2,11 +2,16 @@ package com.yomahub.liteflow.test.redis; import cn.hutool.crypto.digest.DigestUtil; import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.core.FlowInitHook; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.flow.LiteflowResponse; import com.yomahub.liteflow.parser.redis.mode.RClient; +import com.yomahub.liteflow.property.LiteflowConfigGetter; import com.yomahub.liteflow.slot.DefaultContext; +import com.yomahub.liteflow.spi.holder.SpiFactoryCleaner; +import com.yomahub.liteflow.spring.ComponentScanner; import com.yomahub.liteflow.test.BaseTest; +import com.yomahub.liteflow.thread.ExecutorHelper; import org.junit.jupiter.api.*; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; @@ -58,9 +63,13 @@ public class RedisWithXmlELPollSpringbootTest extends BaseTest { "local sha1 = redis.sha1hex(value);\n" + "return sha1;"; + @AfterEach public void after() { FlowBus.cleanCache(); + FlowInitHook.cleanHook(); + ExecutorHelper.loadInstance().clearExecutorServiceMap(); + SpiFactoryCleaner.clean(); } /** @@ -94,7 +103,7 @@ public class RedisWithXmlELPollSpringbootTest extends BaseTest { Assertions.assertTrue(response.isSuccess()); Assertions.assertEquals("a==>b==>c", response.getExecuteStepStr()); - Thread.sleep(2000); + Thread.sleep(4000); //测试修改后的chain response = flowExecutor.execute2Resp("chain11", "arg"); @@ -106,10 +115,10 @@ public class RedisWithXmlELPollSpringbootTest extends BaseTest { * 测试script */ @Test - public void testPollWithScriptXml() throws InterruptedException { + public void testPollWithScript() throws InterruptedException { Set chainNameSet = new HashSet<>(); chainNameSet.add("chain22"); - String chainValue = "THEN(a, b, c, s11, s22, s33);"; + String chainValue = "THEN(s11, s22, s33, a, b);"; when(chainClient.hkeys("pollChainKey")).thenReturn(chainNameSet); when(chainClient.hget("pollChainKey", "chain22")).thenReturn(chainValue); when(chainClient.scriptLoad(luaOfKey)).thenReturn("keysha"); @@ -150,9 +159,9 @@ public class RedisWithXmlELPollSpringbootTest extends BaseTest { Assertions.assertTrue(response.isSuccess()); Assertions.assertEquals("hello s11", context.getData("test11")); Assertions.assertEquals("hello s22", context.getData("test22")); - Assertions.assertEquals("a==>b==>c==>s11[脚本s11]==>s22[脚本s22]==>s33[脚本s33]", response.getExecuteStepStrWithoutTime()); + Assertions.assertEquals("s11[脚本s11]==>s22[脚本s22]==>s33[脚本s33]==>a==>b", response.getExecuteStepStrWithoutTime()); - Thread.sleep(2000); + Thread.sleep(4000); //测试修改后的script response = flowExecutor.execute2Resp("chain22", "arg"); diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java index 0d815d23..3b82456f 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java @@ -31,9 +31,12 @@ import javax.annotation.Resource; /** * springboot环境下的redis配置源订阅模式功能测试 * - * 由于redisson中RMapCache监听器功能无法mock测试 + * 由于Redisson中RMapCache的监听器功能无法mock测试 * 故Sub模式测试用例需本地启动Redis服务 连接地址: 127.0.0.1:6379 - * 若本地该端口号未启动Redis服务 则自动忽略本类中测试用例 + * 若本地该端口号未启动Redis 则自动忽略本类中测试用例 + * + * 测试用例会在1号database中添加测试数据 chainKey:testChainKey; scriptKey:testScriptKey + * 测试完成后清除测试数据 * * @author hxinyu * @since 2.11.0 @@ -56,8 +59,8 @@ public class RedisWithXmlELSubscribeSpringbootTest extends BaseTest { Config config = new Config(); config.useSingleServer().setAddress("redis://127.0.0.1:6379").setDatabase(1); redissonClient = Redisson.create(config); - RMapCache chainKey = redissonClient.getMapCache("chainKey"); - RMapCache scriptKey = redissonClient.getMapCache("scriptKey"); + RMapCache chainKey = redissonClient.getMapCache("testChainKey"); + RMapCache scriptKey = redissonClient.getMapCache("testScriptKey"); scriptKey.put("s1:script:脚本s1:groovy", "defaultContext.setData(\"test1\",\"hello s1\");"); scriptKey.put("s2:script:脚本s2:js", "defaultContext.setData(\"test2\",\"hello s2\");"); scriptKey.put("s3:script:脚本s3", "defaultContext.setData(\"test3\",\"hello s3\");"); @@ -68,7 +71,6 @@ public class RedisWithXmlELSubscribeSpringbootTest extends BaseTest { @AfterAll public static void after(){ - System.out.println("after"); testCleanData(); } @@ -179,17 +181,16 @@ public class RedisWithXmlELSubscribeSpringbootTest extends BaseTest { //redis内规则数据数据清空 public static void testCleanData(){ if(ObjectUtil.isNotNull(redissonClient)){ - RMapCache scriptKey = redissonClient.getMapCache("chainKey"); - RMapCache chainKey = redissonClient.getMapCache("scriptKey"); + RMapCache chainKey = redissonClient.getMapCache("testChainKey"); + RMapCache scriptKey = redissonClient.getMapCache("testScriptKey"); for (String key : chainKey.keySet()) { chainKey.remove(key); } for (String key : scriptKey.keySet()) { scriptKey.remove(key); } - chainKey.keySet().forEach(System.out::println); - System.out.println(""); - scriptKey.keySet().forEach(System.out::println); + chainKey.delete(); + scriptKey.delete(); } } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-poll-xml.properties b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-poll-xml.properties index 567bff7b..aea34f3c 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-poll-xml.properties +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-poll-xml.properties @@ -1,8 +1,8 @@ liteflow.rule-source-ext-data={\ "host":"localhost",\ "port":6379,\ - "pollingInterval":1,\ - "pollingStartTime":1,\ + "pollingInterval":2,\ + "pollingStartTime":2,\ "chainDataBase":1,\ "chainKey":"pollChainKey",\ "scriptDataBase":1,\ diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-sub-xml.properties b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-sub-xml.properties index 22a58eed..6d841fea 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-sub-xml.properties +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/resources/redis/application-sub-xml.properties @@ -3,8 +3,8 @@ liteflow.rule-source-ext-data={\ "port":6379,\ "mode":"sub",\ "chainDataBase":1,\ - "chainKey":"chainKey",\ + "chainKey":"testChainKey",\ "scriptDataBase":1,\ - "scriptKey":"scriptKey"\ + "scriptKey":"testScriptKey"\ } liteflow.parse-on-start=false \ No newline at end of file From 7f6f7829a32379c28f94ae90075390bdb1aed55c Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sun, 20 Aug 2023 18:17:39 +0800 Subject: [PATCH 41/41] fix test --- .../test/redis/RedisWithXmlELSubscribeSpringbootTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java index 3b82456f..02575d0e 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-redis-springboot/src/test/java/com/yomahub/liteflow/test/redis/RedisWithXmlELSubscribeSpringbootTest.java @@ -86,20 +86,20 @@ public class RedisWithXmlELSubscribeSpringbootTest extends BaseTest { //修改redis中规则 changeXMLData(); //重新加载规则 - Thread.sleep(50); + Thread.sleep(100); Assertions.assertEquals("a==>c==>b", flowExecutor.execute2Resp("chain1", "arg").getExecuteStepStr()); //删除redis中规则 deleteXMLData(); //重新加载规则 - Thread.sleep(50); + Thread.sleep(100); response = flowExecutor.execute2Resp("chain1", "arg"); Assertions.assertTrue(!response.isSuccess()); //添加redis中规则 addXMLData(); //重新加载规则 - Thread.sleep(50); + Thread.sleep(100); Assertions.assertEquals("b==>c", flowExecutor.execute2Resp("chain4", "arg").getExecuteStepStr()); } @@ -118,7 +118,7 @@ public class RedisWithXmlELSubscribeSpringbootTest extends BaseTest { addAndDeleteScriptData(); //修改redis脚本 changeScriptData(); - Thread.sleep(50); + Thread.sleep(100); context = flowExecutor.execute2Resp("chain3", "arg").getFirstContextBean(); Assertions.assertEquals("hello s1 version2", context.getData("test1")); context = flowExecutor.execute2Resp("chain2", "arg").getFirstContextBean();