Skip to content

Commit f7d6bee

Browse files
authored
Merge pull request #541 from splitio/rbs-evaluator
Updated Evaluator
2 parents d248562 + b607793 commit f7d6bee

File tree

10 files changed

+326
-76
lines changed

10 files changed

+326
-76
lines changed

client/src/main/java/io/split/client/SplitFactoryImpl.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,12 @@
6666
import io.split.storages.SplitCache;
6767
import io.split.storages.SplitCacheConsumer;
6868
import io.split.storages.SplitCacheProducer;
69+
import io.split.storages.RuleBasedSegmentCacheConsumer;
70+
import io.split.storages.RuleBasedSegmentCache;
6971
import io.split.storages.enums.OperationMode;
7072
import io.split.storages.memory.InMemoryCacheImp;
7173
import io.split.storages.memory.SegmentCacheInMemoryImpl;
74+
import io.split.storages.memory.RuleBasedSegmentCacheInMemoryImp;
7275
import io.split.storages.pluggable.adapters.UserCustomEventAdapterProducer;
7376
import io.split.storages.pluggable.adapters.UserCustomImpressionAdapterConsumer;
7477
import io.split.storages.pluggable.adapters.UserCustomImpressionAdapterProducer;
@@ -202,6 +205,7 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn
202205

203206
// Cache Initialisations
204207
SegmentCache segmentCache = new SegmentCacheInMemoryImpl();
208+
RuleBasedSegmentCache ruleBasedSegmentCache = new RuleBasedSegmentCacheInMemoryImp();
205209
FlagSetsFilter flagSetsFilter = new FlagSetsFilterImpl(config.getSetsFilter());
206210
SplitCache splitCache = new InMemoryCacheImp(flagSetsFilter);
207211
ImpressionsStorage impressionsStorage = new InMemoryImpressionsStorage(config.impressionsQueueSize());
@@ -244,7 +248,7 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn
244248
config.getThreadFactory());
245249

246250
// Evaluator
247-
_evaluator = new EvaluatorImp(splitCache, segmentCache);
251+
_evaluator = new EvaluatorImp(splitCache, segmentCache, ruleBasedSegmentCache);
248252

249253
// SplitClient
250254
_client = new SplitClientImpl(this,
@@ -333,7 +337,9 @@ protected SplitFactoryImpl(String apiToken, SplitClientConfig config, CustomStor
333337
_gates = new SDKReadinessGates();
334338

335339
_telemetrySynchronizer = new TelemetryConsumerSubmitter(customStorageWrapper, _sdkMetadata);
336-
_evaluator = new EvaluatorImp(userCustomSplitAdapterConsumer, userCustomSegmentAdapterConsumer);
340+
// TODO Update the instance to UserCustomRuleBasedSegmentAdapterConsumer
341+
RuleBasedSegmentCacheConsumer userCustomRuleBasedSegmentAdapterConsumer = new RuleBasedSegmentCacheInMemoryImp();
342+
_evaluator = new EvaluatorImp(userCustomSplitAdapterConsumer, userCustomSegmentAdapterConsumer, userCustomRuleBasedSegmentAdapterConsumer);
337343
_impressionsSender = PluggableImpressionSender.create(customStorageWrapper);
338344
_uniqueKeysTracker = createUniqueKeysTracker(config);
339345
_impressionsManager = buildImpressionsManager(config, userCustomImpressionAdapterConsumer,
@@ -392,6 +398,7 @@ protected SplitFactoryImpl(SplitClientConfig config) {
392398
SegmentCache segmentCache = new SegmentCacheInMemoryImpl();
393399
FlagSetsFilter flagSetsFilter = new FlagSetsFilterImpl(config.getSetsFilter());
394400
SplitCache splitCache = new InMemoryCacheImp(flagSetsFilter);
401+
RuleBasedSegmentCache _ruleBasedSegmentCache = new RuleBasedSegmentCacheInMemoryImp();
395402
_splitCache = splitCache;
396403
_gates = new SDKReadinessGates();
397404
_segmentCache = segmentCache;
@@ -428,7 +435,7 @@ protected SplitFactoryImpl(SplitClientConfig config) {
428435
_impressionsManager, null, null, null);
429436

430437
// Evaluator
431-
_evaluator = new EvaluatorImp(splitCache, segmentCache);
438+
_evaluator = new EvaluatorImp(splitCache, segmentCache, _ruleBasedSegmentCache);
432439

433440
EventsStorage eventsStorage = new NoopEventsStorageImp();
434441

client/src/main/java/io/split/engine/evaluator/EvaluationContext.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
package io.split.engine.evaluator;
22

3+
import io.split.storages.RuleBasedSegmentCacheConsumer;
34
import io.split.storages.SegmentCacheConsumer;
45

56
import static com.google.common.base.Preconditions.checkNotNull;
67

78
public class EvaluationContext {
89
private final Evaluator _evaluator;
910
private final SegmentCacheConsumer _segmentCacheConsumer;
11+
private final RuleBasedSegmentCacheConsumer _ruleBasedSegmentCacheConsumer;
1012

11-
public EvaluationContext(Evaluator evaluator, SegmentCacheConsumer segmentCacheConsumer) {
13+
public EvaluationContext(Evaluator evaluator, SegmentCacheConsumer segmentCacheConsumer,
14+
RuleBasedSegmentCacheConsumer ruleBasedSegmentCacheConsumer) {
1215
_evaluator = checkNotNull(evaluator);
1316
_segmentCacheConsumer = checkNotNull(segmentCacheConsumer);
17+
_ruleBasedSegmentCacheConsumer = checkNotNull(ruleBasedSegmentCacheConsumer);
1418
}
1519

1620
public Evaluator getEvaluator() {
@@ -20,4 +24,8 @@ public Evaluator getEvaluator() {
2024
public SegmentCacheConsumer getSegmentCache() {
2125
return _segmentCacheConsumer;
2226
}
27+
28+
public RuleBasedSegmentCacheConsumer getRuleBasedSegmentCache() {
29+
return _ruleBasedSegmentCacheConsumer;
30+
}
2331
}

client/src/main/java/io/split/engine/evaluator/EvaluatorImp.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import io.split.engine.experiments.ParsedSplit;
77
import io.split.engine.splitter.Splitter;
88
import io.split.grammar.Treatments;
9+
import io.split.storages.RuleBasedSegmentCacheConsumer;
910
import io.split.storages.SegmentCacheConsumer;
1011
import io.split.storages.SplitCacheConsumer;
1112
import org.slf4j.Logger;
@@ -23,13 +24,16 @@ public class EvaluatorImp implements Evaluator {
2324
private static final Logger _log = LoggerFactory.getLogger(EvaluatorImp.class);
2425

2526
private final SegmentCacheConsumer _segmentCacheConsumer;
27+
private final RuleBasedSegmentCacheConsumer _ruleBasedSegmentCacheConsumer;
2628
private final EvaluationContext _evaluationContext;
2729
private final SplitCacheConsumer _splitCacheConsumer;
2830

29-
public EvaluatorImp(SplitCacheConsumer splitCacheConsumer, SegmentCacheConsumer segmentCache) {
31+
public EvaluatorImp(SplitCacheConsumer splitCacheConsumer, SegmentCacheConsumer segmentCache,
32+
RuleBasedSegmentCacheConsumer ruleBasedSegmentCacheConsumer) {
3033
_splitCacheConsumer = checkNotNull(splitCacheConsumer);
3134
_segmentCacheConsumer = checkNotNull(segmentCache);
32-
_evaluationContext = new EvaluationContext(this, _segmentCacheConsumer);
35+
_ruleBasedSegmentCacheConsumer = checkNotNull(ruleBasedSegmentCacheConsumer);
36+
_evaluationContext = new EvaluationContext(this, _segmentCacheConsumer, ruleBasedSegmentCacheConsumer);
3337
}
3438

3539
@Override
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package io.split.engine.matchers;
2+
3+
import io.split.engine.evaluator.EvaluationContext;
4+
import io.split.engine.experiments.ParsedCondition;
5+
import io.split.engine.experiments.ParsedRuleBasedSegment;
6+
7+
import java.util.List;
8+
import java.util.Map;
9+
10+
import static com.google.common.base.Preconditions.checkNotNull;
11+
12+
/**
13+
* A matcher that checks if the key is part of a user defined segment. This class
14+
* assumes that the logic for refreshing what keys are part of a segment is delegated
15+
* to SegmentFetcher.
16+
*
17+
* @author adil
18+
*/
19+
public class RuleBasedSegmentMatcher implements Matcher {
20+
private final String _segmentName;
21+
22+
public RuleBasedSegmentMatcher(String segmentName) {
23+
_segmentName = checkNotNull(segmentName);
24+
}
25+
26+
@Override
27+
public boolean match(Object matchValue, String bucketingKey, Map<String, Object> attributes, EvaluationContext evaluationContext) {
28+
if (!(matchValue instanceof String)) {
29+
return false;
30+
}
31+
ParsedRuleBasedSegment parsedRuleBasedSegment = evaluationContext.getRuleBasedSegmentCache().get(_segmentName);
32+
if (parsedRuleBasedSegment == null) {
33+
return false;
34+
}
35+
36+
if (parsedRuleBasedSegment.excludedKeys().contains(matchValue)) {
37+
return false;
38+
}
39+
40+
for (String segmentName: parsedRuleBasedSegment.excludedSegments()) {
41+
if (evaluationContext.getSegmentCache().isInSegment(segmentName, (String) matchValue)) {
42+
return false;
43+
}
44+
}
45+
List<ParsedCondition> conditions = parsedRuleBasedSegment.parsedConditions();
46+
for (ParsedCondition parsedCondition : conditions) {
47+
if (parsedCondition.matcher().match((String) matchValue, bucketingKey, attributes, evaluationContext)) {
48+
return true;
49+
}
50+
}
51+
return false;
52+
}
53+
54+
@Override
55+
public int hashCode() {
56+
int result = 17;
57+
result = 31 * result + _segmentName.hashCode();
58+
return result;
59+
}
60+
61+
@Override
62+
public boolean equals(Object obj) {
63+
if (obj == null) return false;
64+
if (this == obj) return true;
65+
if (!(obj instanceof RuleBasedSegmentMatcher)) return false;
66+
67+
RuleBasedSegmentMatcher other = (RuleBasedSegmentMatcher) obj;
68+
69+
return _segmentName.equals(other._segmentName);
70+
}
71+
72+
@Override
73+
public String toString() {
74+
StringBuilder bldr = new StringBuilder();
75+
bldr.append("in segment ");
76+
bldr.append(_segmentName);
77+
return bldr.toString();
78+
}
79+
80+
public String getSegmentName() {
81+
return _segmentName;
82+
}
83+
}

0 commit comments

Comments
 (0)