This is an automated email from the ASF dual-hosted git repository.
Aias00 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new 5901356c92 fix(plugin): evict cached fault-tolerance handles when
explicitly cleared (#7914) (#7925)
5901356c92 is described below
commit 5901356c92f2c81fdf3bba03a6b945547e829cb2
Author: konlue <[email protected]>
AuthorDate: Thu Oct 22 10:05:17 2026 +0800
fix(plugin): evict cached fault-tolerance handles when explicitly cleared
(#7914) (#7925)
* fix(plugin): evict cached fault-tolerance handles when explicitly cleared
(#7914)
* fix(plugin): treat null handles as cleared and evict unconditionally
(#7914)
---
.../handler/RateLimiterPluginDataHandler.java | 16 +++--
.../handler/RateLimiterPluginDataHandlerTest.java | 76 ++++++++++++++++++++++
.../resilience4j/handler/Resilience4JHandler.java | 18 +++--
.../handler/Resilience4JHandlerTest.java | 72 ++++++++++++++++++++
.../sentinel/handler/SentinelRuleHandle.java | 7 ++
.../sentinel/handler/SentinelRuleHandleTest.java | 49 ++++++++++++++
6 files changed, 226 insertions(+), 12 deletions(-)
diff --git
a/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-ratelimiter/src/main/java/org/apache/shenyu/plugin/ratelimiter/handler/RateLimiterPluginDataHandler.java
b/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-ratelimiter/src/main/java/org/apache/shenyu/plugin/ratelimiter/handler/RateLimiterPluginDataHandler.java
index 246ce6dcee..badaea4767 100644
---
a/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-ratelimiter/src/main/java/org/apache/shenyu/plugin/ratelimiter/handler/RateLimiterPluginDataHandler.java
+++
b/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-ratelimiter/src/main/java/org/apache/shenyu/plugin/ratelimiter/handler/RateLimiterPluginDataHandler.java
@@ -17,6 +17,7 @@
package org.apache.shenyu.plugin.ratelimiter.handler;
+import org.apache.commons.lang3.StringUtils;
import org.apache.shenyu.common.constant.Constants;
import org.apache.shenyu.common.dto.PluginData;
import org.apache.shenyu.common.dto.RuleData;
@@ -36,7 +37,6 @@ import org.apache.shenyu.plugin.base.utils.CacheKeyUtils;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import java.util.Objects;
-import java.util.Optional;
import java.util.function.Supplier;
/**
@@ -84,15 +84,19 @@ public class RateLimiterPluginDataHandler implements
PluginDataHandler {
@Override
public void handlerRule(final RuleData ruleData) {
- Optional.ofNullable(ruleData.getHandle()).ifPresent(s -> {
- final RateLimiterHandle rateLimiterHandle =
GsonUtils.getInstance().fromJson(s, RateLimiterHandle.class);
-
CACHED_HANDLE.get().cachedHandle(CacheKeyUtils.INST.getKey(ruleData),
rateLimiterHandle);
- });
+ if (StringUtils.isBlank(ruleData.getHandle())) {
+ // a cleared (null or blank) handle must evict the previous rule,
+ // not leave it cached and enforcing (#7914)
+ removeRule(ruleData);
+ return;
+ }
+ final RateLimiterHandle rateLimiterHandle =
GsonUtils.getInstance().fromJson(ruleData.getHandle(), RateLimiterHandle.class);
+ CACHED_HANDLE.get().cachedHandle(CacheKeyUtils.INST.getKey(ruleData),
rateLimiterHandle);
}
@Override
public void removeRule(final RuleData ruleData) {
- Optional.ofNullable(ruleData.getHandle()).ifPresent(s ->
CACHED_HANDLE.get().removeHandle(CacheKeyUtils.INST.getKey(ruleData)));
+ CACHED_HANDLE.get().removeHandle(CacheKeyUtils.INST.getKey(ruleData));
}
@Override
diff --git
a/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-ratelimiter/src/test/java/org/apache/shenyu/plugin/ratelimiter/handler/RateLimiterPluginDataHandlerTest.java
b/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-ratelimiter/src/test/java/org/apache/shenyu/plugin/ratelimiter/handler/RateLimiterPluginDataHandlerTest.java
index 0e46e1a1c7..14768200e2 100644
---
a/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-ratelimiter/src/test/java/org/apache/shenyu/plugin/ratelimiter/handler/RateLimiterPluginDataHandlerTest.java
+++
b/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-ratelimiter/src/test/java/org/apache/shenyu/plugin/ratelimiter/handler/RateLimiterPluginDataHandlerTest.java
@@ -20,11 +20,14 @@ package org.apache.shenyu.plugin.ratelimiter.handler;
import com.google.common.collect.Sets;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.apache.shenyu.common.dto.PluginData;
+import org.apache.shenyu.common.dto.RuleData;
+import org.apache.shenyu.common.dto.convert.rule.RateLimiterHandle;
import org.apache.shenyu.common.enums.PluginEnum;
import org.apache.shenyu.common.utils.GsonUtils;
import org.apache.shenyu.common.utils.Singleton;
import org.apache.shenyu.infra.redis.RedisConfigProperties;
import org.apache.shenyu.infra.redis.RedisConnectionFactory;
+import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -46,6 +49,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNotSame;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -76,6 +80,13 @@ public final class RateLimiterPluginDataHandlerTest {
private RedisConnectionFactory redisConnectionFactory;
+ @AfterEach
+ public void clearTestKeys() {
+
RateLimiterPluginDataHandler.CACHED_HANDLE.get().removeHandle("1_clear-test");
+
RateLimiterPluginDataHandler.CACHED_HANDLE.get().removeHandle("1_null-clear-test");
+
RateLimiterPluginDataHandler.CACHED_HANDLE.get().removeHandle("1_remove-null-test");
+ }
+
@BeforeEach
public void setUp() {
this.redisConnectionFactory = new
RedisConnectionFactory(generateRedisConfig(generateDefaultUrl()));
@@ -193,6 +204,71 @@ public final class RateLimiterPluginDataHandlerTest {
assertEquals(PluginEnum.RATE_LIMITER.getName(), new
RateLimiterPluginDataHandler().pluginNamed());
}
+ /**
+ * an explicitly cleared handle must evict the previously cached rule
(#7914).
+ */
+ @Test
+ public void handlerRuleExplicitClearEvictsPreviousRule() {
+ final RateLimiterPluginDataHandler handler = new
RateLimiterPluginDataHandler();
+ final RuleData ruleData = new RuleData();
+ ruleData.setSelectorId("1");
+ ruleData.setId("clear-test");
+
ruleData.setHandle(GsonUtils.getGson().toJson(RateLimiterHandle.newDefaultInstance()));
+ handler.handlerRule(ruleData);
+
assertNotNull(RateLimiterPluginDataHandler.CACHED_HANDLE.get().obtainHandle("1_clear-test"));
+
+ ruleData.setHandle("");
+ handler.handlerRule(ruleData);
+
assertNull(RateLimiterPluginDataHandler.CACHED_HANDLE.get().obtainHandle("1_clear-test"),
+ "an empty handle must evict the previously cached rule");
+
+ ruleData.setHandle(" ");
+ handler.handlerRule(ruleData);
+
assertNull(RateLimiterPluginDataHandler.CACHED_HANDLE.get().obtainHandle("1_clear-test"));
+
+
ruleData.setHandle(GsonUtils.getGson().toJson(RateLimiterHandle.newDefaultInstance()));
+ handler.handlerRule(ruleData);
+
assertNotNull(RateLimiterPluginDataHandler.CACHED_HANDLE.get().obtainHandle("1_clear-test"),
+ "a subsequent valid update must re-cache the rule");
+ }
+
+ /**
+ * A handle that disappeared entirely (null) is a clear too (#7914).
+ */
+ @Test
+ public void handlerRuleNullHandleEvictsPreviousRule() {
+ final RateLimiterPluginDataHandler handler = new
RateLimiterPluginDataHandler();
+ final RuleData ruleData = new RuleData();
+ ruleData.setSelectorId("1");
+ ruleData.setId("null-clear-test");
+
ruleData.setHandle(GsonUtils.getGson().toJson(RateLimiterHandle.newDefaultInstance()));
+ handler.handlerRule(ruleData);
+
assertNotNull(RateLimiterPluginDataHandler.CACHED_HANDLE.get().obtainHandle("1_null-clear-test"));
+
+ ruleData.setHandle(null);
+ handler.handlerRule(ruleData);
+
assertNull(RateLimiterPluginDataHandler.CACHED_HANDLE.get().obtainHandle("1_null-clear-test"),
+ "a null handle must evict the previously cached rule");
+ }
+
+ /**
+ * Deleting a rule whose handle is already null must still evict the
cached entry (#7914).
+ */
+ @Test
+ public void removeRuleWithoutHandleStillEvicts() {
+ final RateLimiterPluginDataHandler handler = new
RateLimiterPluginDataHandler();
+ final RuleData ruleData = new RuleData();
+ ruleData.setSelectorId("1");
+ ruleData.setId("remove-null-test");
+ ruleData.setHandle(null);
+
RateLimiterPluginDataHandler.CACHED_HANDLE.get().cachedHandle("1_remove-null-test",
+ RateLimiterHandle.newDefaultInstance());
+
+ handler.removeRule(ruleData);
+
+
assertNull(RateLimiterPluginDataHandler.CACHED_HANDLE.get().obtainHandle("1_remove-null-test"));
+ }
+
/**
* url generate by host and port.
*/
diff --git
a/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-resilience4j/src/main/java/org/apache/shenyu/plugin/resilience4j/handler/Resilience4JHandler.java
b/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-resilience4j/src/main/java/org/apache/shenyu/plugin/resilience4j/handler/Resilience4JHandler.java
index d0f54e018b..41f3f3a3a3 100644
---
a/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-resilience4j/src/main/java/org/apache/shenyu/plugin/resilience4j/handler/Resilience4JHandler.java
+++
b/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-resilience4j/src/main/java/org/apache/shenyu/plugin/resilience4j/handler/Resilience4JHandler.java
@@ -17,6 +17,7 @@
package org.apache.shenyu.plugin.resilience4j.handler;
+import org.apache.commons.lang3.StringUtils;
import org.apache.shenyu.common.constant.Constants;
import org.apache.shenyu.common.dto.RuleData;
import org.apache.shenyu.common.dto.SelectorData;
@@ -29,7 +30,6 @@ import org.apache.shenyu.plugin.base.utils.BeanHolder;
import org.apache.shenyu.plugin.base.utils.CacheKeyUtils;
import
org.apache.shenyu.plugin.resilience4j.factory.Resilience4JRegistryFactory;
-import java.util.Optional;
import java.util.function.Supplier;
/**
@@ -54,18 +54,24 @@ public class Resilience4JHandler implements
PluginDataHandler {
@Override
public void handlerRule(final RuleData ruleData) {
String key = CacheKeyUtils.INST.getKey(ruleData);
+ // resetting the registry on every update is intentional: a rule
change must
+ // not keep breaker/bulkhead/limiter state built from the previous
handle (#7914)
Resilience4JRegistryFactory.remove(key);
- Optional.ofNullable(ruleData.getHandle()).ifPresent(s -> {
- final Resilience4JHandle resilience4JHandle =
GsonUtils.getInstance().fromJson(s, Resilience4JHandle.class);
- CACHED_HANDLE.get().cachedHandle(key, resilience4JHandle);
- });
+ if (StringUtils.isBlank(ruleData.getHandle())) {
+ // a cleared (null or blank) handle must evict the previous rule,
+ // not leave it cached and enforcing (#7914)
+ removeRule(ruleData);
+ return;
+ }
+ final Resilience4JHandle resilience4JHandle =
GsonUtils.getInstance().fromJson(ruleData.getHandle(),
Resilience4JHandle.class);
+ CACHED_HANDLE.get().cachedHandle(key, resilience4JHandle);
}
@Override
public void removeRule(final RuleData ruleData) {
String key = CacheKeyUtils.INST.getKey(ruleData);
Resilience4JRegistryFactory.remove(key);
- Optional.ofNullable(ruleData.getHandle()).ifPresent(s ->
CACHED_HANDLE.get().removeHandle(key));
+ CACHED_HANDLE.get().removeHandle(key);
}
@Override
diff --git
a/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-resilience4j/src/test/java/org/apache/shenyu/plugin/resilience4j/handler/Resilience4JHandlerTest.java
b/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-resilience4j/src/test/java/org/apache/shenyu/plugin/resilience4j/handler/Resilience4JHandlerTest.java
index c5c0da0869..c96c3b1861 100644
---
a/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-resilience4j/src/test/java/org/apache/shenyu/plugin/resilience4j/handler/Resilience4JHandlerTest.java
+++
b/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-resilience4j/src/test/java/org/apache/shenyu/plugin/resilience4j/handler/Resilience4JHandlerTest.java
@@ -21,6 +21,7 @@ import org.apache.shenyu.common.dto.RuleData;
import org.apache.shenyu.common.dto.convert.rule.Resilience4JHandle;
import org.apache.shenyu.plugin.base.cache.CommonHandleCache;
import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import java.util.function.Supplier;
@@ -56,6 +57,77 @@ public final class Resilience4JHandlerTest {
Assertions.assertNull(cache.get().obtainHandle("1_test"));
}
+ /**
+ * An explicitly cleared handle must evict the previous rule, whitespace
+ * counts as a clear, and a subsequent valid update re-caches (#7914).
+ */
+ @Test
+ public void testHandlerRuleExplicitClearEvictsPreviousRule() {
+ ruleData.setSelectorId("1");
+ ruleData.setId("clear-test");
+ ruleData.setHandle("{\"urlPath\":\"test\"}");
+ resilience4JHandler.handlerRule(ruleData);
+ final Supplier<CommonHandleCache<String, Resilience4JHandle>> cache =
Resilience4JHandler.CACHED_HANDLE;
+ Assertions.assertNotNull(cache.get().obtainHandle("1_clear-test"));
+
+ ruleData.setHandle("");
+ resilience4JHandler.handlerRule(ruleData);
+ Assertions.assertNull(cache.get().obtainHandle("1_clear-test"),
+ "an empty handle must evict the previously cached rule");
+
+ ruleData.setHandle(" ");
+ resilience4JHandler.handlerRule(ruleData);
+ Assertions.assertNull(cache.get().obtainHandle("1_clear-test"));
+
+ ruleData.setHandle("{\"urlPath\":\"test\"}");
+ resilience4JHandler.handlerRule(ruleData);
+ Assertions.assertNotNull(cache.get().obtainHandle("1_clear-test"),
+ "a subsequent valid update must re-cache the rule");
+ }
+
+ /**
+ * A handle that disappeared entirely (null, e.g. the column is NULL
instead
+ * of an empty string) is a clear too: the previous rule must stop
enforcing (#7914).
+ */
+ @Test
+ public void testHandlerRuleNullHandleEvictsPreviousRule() {
+ ruleData.setSelectorId("1");
+ ruleData.setId("null-clear-test");
+ ruleData.setHandle("{\"urlPath\":\"test\"}");
+ resilience4JHandler.handlerRule(ruleData);
+ final Supplier<CommonHandleCache<String, Resilience4JHandle>> cache =
Resilience4JHandler.CACHED_HANDLE;
+
Assertions.assertNotNull(cache.get().obtainHandle("1_null-clear-test"));
+
+ ruleData.setHandle(null);
+ resilience4JHandler.handlerRule(ruleData);
+ Assertions.assertNull(cache.get().obtainHandle("1_null-clear-test"),
+ "a null handle must evict the previously cached rule");
+ }
+
+ /**
+ * Deleting a rule whose handle is already null must still evict the cached
+ * entry, so the paths cannot disagree about what a removal means (#7914).
+ */
+ @Test
+ public void testRemoveRuleWithoutHandleStillEvicts() {
+ ruleData.setSelectorId("1");
+ ruleData.setId("remove-null-test");
+ ruleData.setHandle(null);
+ final Supplier<CommonHandleCache<String, Resilience4JHandle>> cache =
Resilience4JHandler.CACHED_HANDLE;
+ cache.get().cachedHandle("1_remove-null-test", new
Resilience4JHandle());
+
+ resilience4JHandler.removeRule(ruleData);
+
+ Assertions.assertNull(cache.get().obtainHandle("1_remove-null-test"));
+ }
+
+ @AfterEach
+ public void tearDown() {
+ Resilience4JHandler.CACHED_HANDLE.get().removeHandle("1_clear-test");
+
Resilience4JHandler.CACHED_HANDLE.get().removeHandle("1_null-clear-test");
+
Resilience4JHandler.CACHED_HANDLE.get().removeHandle("1_remove-null-test");
+ }
+
@Test
public void testPluginNamed() {
Assertions.assertEquals(resilience4JHandler.pluginNamed(),
"resilience4j");
diff --git
a/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-sentinel/src/main/java/org/apache/shenyu/plugin/sentinel/handler/SentinelRuleHandle.java
b/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-sentinel/src/main/java/org/apache/shenyu/plugin/sentinel/handler/SentinelRuleHandle.java
index cf2bdb0f9d..3f756e4547 100644
---
a/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-sentinel/src/main/java/org/apache/shenyu/plugin/sentinel/handler/SentinelRuleHandle.java
+++
b/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-sentinel/src/main/java/org/apache/shenyu/plugin/sentinel/handler/SentinelRuleHandle.java
@@ -21,6 +21,7 @@ import
com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
+import org.apache.commons.lang3.StringUtils;
import org.apache.shenyu.common.constant.Constants;
import org.apache.shenyu.common.dto.RuleData;
import org.apache.shenyu.common.dto.SelectorData;
@@ -59,6 +60,12 @@ public class SentinelRuleHandle implements PluginDataHandler
{
@Override
public void handlerRule(final RuleData ruleData) {
+ if (StringUtils.isBlank(ruleData.getHandle())) {
+ // a cleared (null or blank) handle must evict the cached rule and
+ // its flow/degrade enforcement, not crash or go stale (#7914)
+ removeRule(ruleData);
+ return;
+ }
SentinelHandle sentinelHandle =
GsonUtils.getInstance().fromJson(ruleData.getHandle(), SentinelHandle.class);
sentinelHandle.checkData();
String key = CacheKeyUtils.INST.getKey(ruleData);
diff --git
a/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-sentinel/src/test/java/org/apache/shenyu/plugin/sentinel/handler/SentinelRuleHandleTest.java
b/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-sentinel/src/test/java/org/apache/shenyu/plugin/sentinel/handler/SentinelRuleHandleTest.java
index ca152fc009..3579efc3c6 100644
---
a/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-sentinel/src/test/java/org/apache/shenyu/plugin/sentinel/handler/SentinelRuleHandleTest.java
+++
b/shenyu-plugin/shenyu-plugin-fault-tolerance/shenyu-plugin-sentinel/src/test/java/org/apache/shenyu/plugin/sentinel/handler/SentinelRuleHandleTest.java
@@ -42,6 +42,7 @@ import java.util.concurrent.TimeUnit;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ExtendWith(MockitoExtension.class)
@@ -106,6 +107,54 @@ public final class SentinelRuleHandleTest {
}
}
+ @Test
+ public void handlerRuleExplicitClearEvictsCacheAndEnforcement() {
+ final RuleData data = createRuleData("clear-test");
+ sentinelRuleHandle.handlerRule(data);
+ assertEquals(1, FlowRuleManager.getRules().size());
+ assertEquals(1, DegradeRuleManager.getRules().size());
+
+ // an explicitly cleared handle must evict cache and enforcement, not
NPE (#7914)
+ data.setHandle("");
+ sentinelRuleHandle.handlerRule(data);
+ assertTrue(FlowRuleManager.getRules().isEmpty());
+ assertTrue(DegradeRuleManager.getRules().isEmpty());
+
assertNull(SentinelRuleHandle.CACHED_HANDLE.get().obtainHandle("sentinel_clear-test"));
+
+ // a subsequent valid update re-establishes enforcement
+ data.setHandle(GsonUtils.getGson().toJson(sentinelHandle()));
+ sentinelRuleHandle.handlerRule(data);
+ assertEquals(1, FlowRuleManager.getRules().size());
+ }
+
+ @Test
+ public void handlerRuleNullHandleEvictsCacheAndEnforcement() {
+ final RuleData data = createRuleData("null-clear-test");
+ sentinelRuleHandle.handlerRule(data);
+ assertEquals(1, FlowRuleManager.getRules().size());
+
+ // a handle that disappeared entirely (null) is a clear too (#7914)
+ data.setHandle(null);
+ sentinelRuleHandle.handlerRule(data);
+ assertTrue(FlowRuleManager.getRules().isEmpty());
+ assertTrue(DegradeRuleManager.getRules().isEmpty());
+
assertNull(SentinelRuleHandle.CACHED_HANDLE.get().obtainHandle("sentinel_null-clear-test"));
+ }
+
+ private SentinelHandle sentinelHandle() {
+ SentinelHandle handle = new SentinelHandle();
+ handle.setFlowRuleCount(10);
+ handle.setFlowRuleGrade(0);
+ handle.setFlowRuleControlBehavior(0);
+ handle.setDegradeRuleCount(1d);
+ handle.setDegradeRuleGrade(0);
+ handle.setDegradeRuleTimeWindow(5);
+ handle.setDegradeRuleMinRequestAmount(5);
+ handle.setDegradeRuleStatIntervals(10);
+ handle.setDegradeRuleSlowRatioThreshold(0.5d);
+ return handle;
+ }
+
private RuleData createRuleData(final String ruleId) {
RuleData data = new RuleData();
data.setSelectorId("sentinel");