diff --git a/client/src/main/java/io/split/client/dtos/Excluded.java b/client/src/main/java/io/split/client/dtos/Excluded.java index bc544d97..e23afa4b 100644 --- a/client/src/main/java/io/split/client/dtos/Excluded.java +++ b/client/src/main/java/io/split/client/dtos/Excluded.java @@ -4,5 +4,5 @@ public class Excluded { public List keys; - public List segments; + public List segments; } diff --git a/client/src/main/java/io/split/client/dtos/ExcludedSegments.java b/client/src/main/java/io/split/client/dtos/ExcludedSegments.java new file mode 100644 index 00000000..84dc3cf0 --- /dev/null +++ b/client/src/main/java/io/split/client/dtos/ExcludedSegments.java @@ -0,0 +1,12 @@ +package io.split.client.dtos; + +public class ExcludedSegments { + public ExcludedSegments() {} + public ExcludedSegments(String type, String name) { + this.type = type; + this.name = name; + } + + public String type; + public String name; +} diff --git a/client/src/main/java/io/split/engine/experiments/ParsedRuleBasedSegment.java b/client/src/main/java/io/split/engine/experiments/ParsedRuleBasedSegment.java index ae8c8f48..6cd7a4ba 100644 --- a/client/src/main/java/io/split/engine/experiments/ParsedRuleBasedSegment.java +++ b/client/src/main/java/io/split/engine/experiments/ParsedRuleBasedSegment.java @@ -1,6 +1,7 @@ package io.split.engine.experiments; import com.google.common.collect.ImmutableList; +import io.split.client.dtos.ExcludedSegments; import io.split.engine.matchers.AttributeMatcher; import io.split.engine.matchers.UserDefinedSegmentMatcher; @@ -15,7 +16,7 @@ public class ParsedRuleBasedSegment { private final String _trafficTypeName; private final long _changeNumber; private final List _excludedKeys; - private final List _excludedSegments; + private final List _excludedSegments; public static ParsedRuleBasedSegment createParsedRuleBasedSegmentForTests( String ruleBasedSegment, @@ -23,7 +24,7 @@ public static ParsedRuleBasedSegment createParsedRuleBasedSegmentForTests( String trafficTypeName, long changeNumber, List excludedKeys, - List excludedSegments + List excludedSegments ) { return new ParsedRuleBasedSegment( ruleBasedSegment, @@ -41,7 +42,7 @@ public ParsedRuleBasedSegment( String trafficTypeName, long changeNumber, List excludedKeys, - List excludedSegments + List excludedSegments ) { _ruleBasedSegment = ruleBasedSegment; _parsedCondition = ImmutableList.copyOf(matcherAndSplits); @@ -64,7 +65,7 @@ public List parsedConditions() { public long changeNumber() {return _changeNumber;} public List excludedKeys() {return _excludedKeys;} - public List excludedSegments() {return _excludedSegments;} + public List excludedSegments() {return _excludedSegments;} @Override public int hashCode() { diff --git a/client/src/main/java/io/split/engine/matchers/RuleBasedSegmentMatcher.java b/client/src/main/java/io/split/engine/matchers/RuleBasedSegmentMatcher.java index ba5b8f41..f92b999a 100644 --- a/client/src/main/java/io/split/engine/matchers/RuleBasedSegmentMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/RuleBasedSegmentMatcher.java @@ -1,5 +1,6 @@ package io.split.engine.matchers; +import io.split.client.dtos.ExcludedSegments; import io.split.engine.evaluator.EvaluationContext; import io.split.engine.experiments.ParsedCondition; import io.split.engine.experiments.ParsedRuleBasedSegment; @@ -17,6 +18,8 @@ * @author adil */ public class RuleBasedSegmentMatcher implements Matcher { + private final String standardType = "standard"; + private final String _segmentName; public RuleBasedSegmentMatcher(String segmentName) { @@ -37,8 +40,8 @@ public boolean match(Object matchValue, String bucketingKey, Map return false; } - for (String segmentName: parsedRuleBasedSegment.excludedSegments()) { - if (evaluationContext.getSegmentCache().isInSegment(segmentName, (String) matchValue)) { + for (ExcludedSegments segment: parsedRuleBasedSegment.excludedSegments()) { + if (segment.type.equals(standardType) && evaluationContext.getSegmentCache().isInSegment(segment.name, (String) matchValue)) { return false; } } diff --git a/client/src/test/java/io/split/engine/experiments/ParsedRuleBasedSegmentTest.java b/client/src/test/java/io/split/engine/experiments/ParsedRuleBasedSegmentTest.java index d1411c81..9915207b 100644 --- a/client/src/test/java/io/split/engine/experiments/ParsedRuleBasedSegmentTest.java +++ b/client/src/test/java/io/split/engine/experiments/ParsedRuleBasedSegmentTest.java @@ -3,6 +3,7 @@ import com.google.common.collect.Lists; import com.google.common.collect.Sets; import io.split.client.dtos.ConditionType; +import io.split.client.dtos.ExcludedSegments; import io.split.client.dtos.MatcherCombiner; import io.split.client.dtos.SplitChange; import io.split.client.utils.Json; @@ -15,6 +16,7 @@ import org.junit.Test; import java.util.ArrayList; +import java.util.List; import static io.split.client.utils.RuleBasedSegmentProcessor.processRuleBasedSegmentChanges; @@ -22,11 +24,15 @@ public class ParsedRuleBasedSegmentTest { @Test public void works() { + List excludedSegments = new ArrayList<>(); + excludedSegments.add(new ExcludedSegments("standard","segment1")); + excludedSegments.add(new ExcludedSegments("standard","segment2")); + AttributeMatcher segmentMatcher = AttributeMatcher.vanilla(new UserDefinedSegmentMatcher("employees")); CombiningMatcher segmentCombiningMatcher = new CombiningMatcher(MatcherCombiner.AND, Lists.newArrayList(segmentMatcher)); ParsedRuleBasedSegment parsedRuleBasedSegment = new ParsedRuleBasedSegment("another_rule_based_segment", - Lists.newArrayList(new ParsedCondition(ConditionType.WHITELIST, segmentCombiningMatcher, null, "label")),"user", - 123, Lists.newArrayList("mauro@test.io","gaston@test.io"), Lists.newArrayList("segment1", "segment2")); + Lists.newArrayList(new ParsedCondition(ConditionType.WHITELIST, segmentCombiningMatcher, null, "label")), "user", + 123, Lists.newArrayList("mauro@test.io", "gaston@test.io"), excludedSegments); Assert.assertEquals(Sets.newHashSet("employees"), parsedRuleBasedSegment.getSegmentsNames()); Assert.assertEquals("another_rule_based_segment", parsedRuleBasedSegment.ruleBasedSegment()); @@ -48,7 +54,7 @@ public void worksWithoutExcluded() { Assert.assertTrue(toUpdate.getToAdd().get(0).excludedSegments().isEmpty()); load = "{\"ff\":{\"s\":-1,\"t\":-1,\"d\":[]},\"rbs\":{\"s\":-1,\"t\":1457726098069,\"d\":[{ \"changeNumber\": 123, \"trafficTypeName\": \"user\", \"name\": \"some_name\"," - + "\"status\": \"ACTIVE\",\"excluded\":{\"segments\":[\"segment1\"]},\"conditions\": [{\"contitionType\": \"ROLLOUT\"," + + "\"status\": \"ACTIVE\",\"excluded\":{\"segments\":[{\"type\": \"standard\",\"name\":\"segment1\"}]},\"conditions\": [{\"contitionType\": \"ROLLOUT\"," + "\"label\": \"some_label\", \"matcherGroup\": { \"matchers\": [{ \"matcherType\": \"ALL_KEYS\", \"negate\": false}]," + "\"combiner\": \"AND\"}}]}]}}"; change = Json.fromJson(load, SplitChange.class); @@ -56,7 +62,7 @@ public void worksWithoutExcluded() { Assert.assertTrue(toUpdate.getToAdd().get(0).excludedKeys().isEmpty()); load = "{\"ff\":{\"s\":-1,\"t\":-1,\"d\":[]},\"rbs\":{\"s\":-1,\"t\":1457726098069,\"d\":[{ \"changeNumber\": 123, \"trafficTypeName\": \"user\", \"name\": \"some_name\"," - + "\"status\": \"ACTIVE\",\"excluded\":{\"segments\":[\"segment1\"], \"keys\":null},\"conditions\": [{\"contitionType\": \"ROLLOUT\"," + + "\"status\": \"ACTIVE\",\"excluded\":{\"segments\":[{\"type\": \"standard\",\"name\":\"segment1\"}], \"keys\":null},\"conditions\": [{\"contitionType\": \"ROLLOUT\"," + "\"label\": \"some_label\", \"matcherGroup\": { \"matchers\": [{ \"matcherType\": \"ALL_KEYS\", \"negate\": false}]," + "\"combiner\": \"AND\"}}]}]}}"; change = Json.fromJson(load, SplitChange.class); diff --git a/client/src/test/java/io/split/storages/memory/RuleBasedSegmentCacheInMemoryImplTest.java b/client/src/test/java/io/split/storages/memory/RuleBasedSegmentCacheInMemoryImplTest.java index c24f8012..1b59b7c7 100644 --- a/client/src/test/java/io/split/storages/memory/RuleBasedSegmentCacheInMemoryImplTest.java +++ b/client/src/test/java/io/split/storages/memory/RuleBasedSegmentCacheInMemoryImplTest.java @@ -1,6 +1,7 @@ package io.split.storages.memory; import com.google.common.collect.Sets; +import io.split.client.dtos.ExcludedSegments; import io.split.client.dtos.MatcherCombiner; import io.split.engine.experiments.ParsedRuleBasedSegment; import io.split.engine.experiments.ParsedCondition; @@ -14,6 +15,9 @@ import org.junit.Test; import com.google.common.collect.Lists; +import java.util.ArrayList; +import java.util.List; + public class RuleBasedSegmentCacheInMemoryImplTest extends TestCase { @Test @@ -35,18 +39,25 @@ public void testAddAndDeleteSegment(){ @Test public void testMultipleSegment(){ + List excludedSegments = new ArrayList<>(); + excludedSegments.add(new ExcludedSegments("standard","segment1")); + excludedSegments.add(new ExcludedSegments("standard","segment3")); + RuleBasedSegmentCacheInMemoryImp ruleBasedSegmentCache = new RuleBasedSegmentCacheInMemoryImp(); AttributeMatcher whiteListMatcher = AttributeMatcher.vanilla(new WhitelistMatcher(Lists.newArrayList("test_1", "admin"))); CombiningMatcher whitelistCombiningMatcher = new CombiningMatcher(MatcherCombiner.AND, Lists.newArrayList(whiteListMatcher)); ParsedRuleBasedSegment parsedRuleBasedSegment1 = new ParsedRuleBasedSegment("sample_rule_based_segment", Lists.newArrayList(new ParsedCondition(ConditionType.WHITELIST, whitelistCombiningMatcher, null, "label")),"user", - 123, Lists.newArrayList("mauro@test.io","gaston@test.io"), Lists.newArrayList(Lists.newArrayList("segment1", "segment3"))); + 123, Lists.newArrayList("mauro@test.io","gaston@test.io"), excludedSegments); + excludedSegments.clear(); + excludedSegments.add(new ExcludedSegments("standard","segment1")); + excludedSegments.add(new ExcludedSegments("standard","segment2")); AttributeMatcher segmentMatcher = AttributeMatcher.vanilla(new UserDefinedSegmentMatcher("employees")); CombiningMatcher segmentCombiningMatcher = new CombiningMatcher(MatcherCombiner.AND, Lists.newArrayList(segmentMatcher)); ParsedRuleBasedSegment parsedRuleBasedSegment2 = new ParsedRuleBasedSegment("another_rule_based_segment", Lists.newArrayList(new ParsedCondition(ConditionType.WHITELIST, segmentCombiningMatcher, null, "label")),"user", - 123, Lists.newArrayList("mauro@test.io","gaston@test.io"), Lists.newArrayList("segment1", "segment2")); + 123, Lists.newArrayList("mauro@test.io","gaston@test.io"), excludedSegments); ruleBasedSegmentCache.update(Lists.newArrayList(parsedRuleBasedSegment1, parsedRuleBasedSegment2), null, 123); assertEquals(Lists.newArrayList("another_rule_based_segment", "sample_rule_based_segment"), ruleBasedSegmentCache.ruleBasedSegmentNames());