Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions client/src/main/java/io/split/engine/evaluator/Evaluator.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package io.split.engine.evaluator;

import java.util.List;
import java.util.Map;

public interface Evaluator {
EvaluatorImp.TreatmentLabelAndChangeNumber evaluateFeature(String matchingKey, String bucketingKey, String split, Map<String, Object> attributes);
Map<String, EvaluatorImp.TreatmentLabelAndChangeNumber> evaluateFeatures(String matchingKey, String bucketingKey, List<String> splits, Map<String, Object> attributes);
}
44 changes: 30 additions & 14 deletions client/src/main/java/io/split/engine/evaluator/EvaluatorImp.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.google.common.base.Preconditions.checkNotNull;
Expand All @@ -33,22 +35,19 @@ public EvaluatorImp(SplitCacheConsumer splitCacheConsumer, SegmentCacheConsumer

@Override
public TreatmentLabelAndChangeNumber evaluateFeature(String matchingKey, String bucketingKey, String split, Map<String, Object> attributes) {
try {
ParsedSplit parsedSplit = _splitCacheConsumer.get(split);

if (parsedSplit == null) {
return new TreatmentLabelAndChangeNumber(Treatments.CONTROL, Labels.DEFINITION_NOT_FOUND);
}
ParsedSplit parsedSplit = _splitCacheConsumer.get(split);
return evaluateParsedSplit(matchingKey, bucketingKey, split, attributes, parsedSplit);
}

return getTreatment(matchingKey, bucketingKey, parsedSplit, attributes);
}
catch (ChangeNumberExceptionWrapper e) {
_log.error("Evaluator Exception", e.wrappedException());
return new EvaluatorImp.TreatmentLabelAndChangeNumber(Treatments.CONTROL, Labels.EXCEPTION, e.changeNumber());
} catch (Exception e) {
_log.error("Evaluator Exception", e);
return new EvaluatorImp.TreatmentLabelAndChangeNumber(Treatments.CONTROL, Labels.EXCEPTION);
@Override
public Map<String, TreatmentLabelAndChangeNumber> evaluateFeatures(String matchingKey, String bucketingKey, List<String> splits, Map<String, Object> attributes) {
Map<String, TreatmentLabelAndChangeNumber> results = new HashMap<>();
Map<String, ParsedSplit> parsedSplits = _splitCacheConsumer.fetchMany(splits);
if(parsedSplits == null) {
return results;
}
parsedSplits.keySet().forEach(s -> results.put(s, evaluateParsedSplit(matchingKey, bucketingKey, s, attributes, parsedSplits.get(s))));
return results;
}

/**
Expand Down Expand Up @@ -108,6 +107,23 @@ private TreatmentLabelAndChangeNumber getTreatment(String matchingKey, String bu
}
}

private TreatmentLabelAndChangeNumber evaluateParsedSplit(String matchingKey, String bucketingKey, String split, Map<String, Object> attributes, ParsedSplit parsedSplit) {
try {
if (parsedSplit == null) {
return new TreatmentLabelAndChangeNumber(Treatments.CONTROL, Labels.DEFINITION_NOT_FOUND);
}

return getTreatment(matchingKey, bucketingKey, parsedSplit, attributes);
}
catch (ChangeNumberExceptionWrapper e) {
_log.error("Evaluator Exception", e.wrappedException());
return new EvaluatorImp.TreatmentLabelAndChangeNumber(Treatments.CONTROL, Labels.EXCEPTION, e.changeNumber());
} catch (Exception e) {
_log.error("Evaluator Exception", e);
return new EvaluatorImp.TreatmentLabelAndChangeNumber(Treatments.CONTROL, Labels.EXCEPTION);
}
}

public static final class TreatmentLabelAndChangeNumber {
public final String treatment;
public final String label;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

public interface SplitCacheConsumer extends SplitCacheCommons{
ParsedSplit get(String name);
Collection<ParsedSplit> getAll();
Collection<ParsedSplit> fetchMany(List<String> names);
Map<String, ParsedSplit> fetchMany(List<String> names);
boolean trafficTypeExists(String trafficTypeName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
Expand Down Expand Up @@ -57,16 +59,10 @@ public Collection<ParsedSplit> getAll() {
}

@Override
public Collection<ParsedSplit> fetchMany(List<String> names) {
List<ParsedSplit> splits = new ArrayList<>();
public Map<String,ParsedSplit> fetchMany(List<String> names) {
Map<String, ParsedSplit> splits = new HashMap<>();

for (String name : names) {
ParsedSplit split = _concurrentMap.get(name);

if (split != null) {
splits.add(split);
}
}
names.forEach(s -> splits.put(s, _concurrentMap.get(s)));

return splits;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.HashSet;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -83,12 +85,17 @@ public boolean trafficTypeExists(String trafficTypeName) {
}

@Override
public Collection<ParsedSplit> fetchMany(List<String> names) {
public Map<String, ParsedSplit> fetchMany(List<String> names) {
Map<String, ParsedSplit> result = new HashMap<>();
List<String> wrapperResponse = _safeUserStorageWrapper.getItems(PrefixAdapter.buildFetchManySplits(names));
if(wrapperResponse == null) {
return new ArrayList<>();
return result;
}
return stringsToParsedSplits(wrapperResponse);
List<ParsedSplit> parsedSplits = stringsToParsedSplits(wrapperResponse);
for(int i=0; i < parsedSplits.size(); i++) {
result.put(names.get(i), parsedSplits.get(i));
}
return result;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
import org.junit.Assert;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Expand Down Expand Up @@ -125,6 +128,27 @@ public void evaluateFeatureWhenSplitNotExistsShouldReturnControl() {
Assert.assertEquals(Labels.DEFINITION_NOT_FOUND, result.label);
}

@Test
public void evaluateMultipleFeatures() {
Evaluator evaluator = buildEvaluatorAndLoadCache(false, 100);

Map<String, EvaluatorImp.TreatmentLabelAndChangeNumber> result = evaluator.evaluateFeatures("test_1", null, new ArrayList<>(Arrays.asList("test", "split_3")), null);
Assert.assertNotNull(result);
Assert.assertEquals(2, result.keySet().size());
Assert.assertEquals(Labels.DEFINITION_NOT_FOUND, result.get("test").label);
Assert.assertEquals(ON_TREATMENT, result.get("split_3").treatment);
Long changeNumberExpected = 223366554L;
Assert.assertEquals(changeNumberExpected, result.get("split_3").changeNumber);
Assert.assertEquals(TEST_LABEL_VALUE_WHITELIST, result.get("split_3").label);
}

@Test(expected = NullPointerException.class)
public void evaluateFeaturesSplitsNull() {
Evaluator evaluator = buildEvaluatorAndLoadCache(false, 100);

Map<String, EvaluatorImp.TreatmentLabelAndChangeNumber> result = evaluator.evaluateFeatures("[email protected]", null, null, null);
}

private Evaluator buildEvaluatorAndLoadCache(boolean killed, int trafficAllocation) {
SplitCache splitCache = new InMemoryCacheImp();
SegmentCache segmentCache = new SegmentCacheInMemoryImpl();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,9 @@ public void getMany() {
names.add("split_name_2");
names.add("split_name_3");

Collection<ParsedSplit> result = _cache.fetchMany(names);
Assert.assertEquals(2, result.size());
Map<String, ParsedSplit> result = _cache.fetchMany(names);
Assert.assertEquals(2, result.keySet().size());
Assert.assertNotNull(result.get("split_name_2"));
}

@Test
Expand Down Expand Up @@ -154,8 +155,8 @@ public void testPutMany() {
_cache.putMany(Stream.of(getParsedSplit("split_name_1"),getParsedSplit("split_name_2"),getParsedSplit("split_name_3"),getParsedSplit("split_name_4")).collect(Collectors.toList()));
List<String> names = Stream.of("split_name_1","split_name_2","split_name_3","split_name_4").collect(Collectors.toList());

Collection<ParsedSplit> result = _cache.fetchMany(names);
Assert.assertEquals(4, result.size());
Map<String, ParsedSplit> result = _cache.fetchMany(names);
Assert.assertEquals(4, result.keySet().size());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand Down Expand Up @@ -158,27 +159,29 @@ public void testFetchMany(){
List<String> listResultExpected = Stream.of(Json.toJson(split), Json.toJson(split2)).collect(Collectors.toList());
Mockito.when(_safeUserStorageWrapper.getItems(PrefixAdapter.buildFetchManySplits(Stream.of(SPLIT_NAME, SPLIT_NAME+"2").collect(Collectors.toList())))).
thenReturn(listResultExpected);
List<ParsedSplit> splitsResult = (List<ParsedSplit>) _userCustomSplitAdapterConsumer.fetchMany(Stream.of(SPLIT_NAME, SPLIT_NAME+"2").collect(Collectors.toList()));
Map<String, ParsedSplit> splitsResult = _userCustomSplitAdapterConsumer.fetchMany(Stream.of(SPLIT_NAME, SPLIT_NAME+"2").collect(Collectors.toList()));
Assert.assertNotNull(splitsResult);
Assert.assertEquals(2, splitsResult.size());
Assert.assertEquals(2, splitsResult.keySet().size());
}

@Test
public void testFetchManyWithWrapperFailing(){
Mockito.when(_safeUserStorageWrapper.getItems(PrefixAdapter.buildFetchManySplits(Stream.of(SPLIT_NAME, SPLIT_NAME+"2").collect(Collectors.toList())))).
thenReturn(null);
List<ParsedSplit> splitsResult = (List<ParsedSplit>) _userCustomSplitAdapterConsumer.fetchMany(Stream.of(SPLIT_NAME, SPLIT_NAME+"2").collect(Collectors.toList()));
Map<String, ParsedSplit> splitsResult = _userCustomSplitAdapterConsumer.fetchMany(Stream.of(SPLIT_NAME, SPLIT_NAME+"2").collect(Collectors.toList()));
Assert.assertNotNull(splitsResult);
Assert.assertEquals(0, splitsResult.size());
Assert.assertNull(splitsResult.get(SPLIT_NAME));
Assert.assertNull(splitsResult.get(SPLIT_NAME+"2"));
}

@Test
public void testFetchManyNotFound(){
Mockito.when(_safeUserStorageWrapper.getItems(PrefixAdapter.buildFetchManySplits(Stream.of(SPLIT_NAME, SPLIT_NAME+"2").collect(Collectors.toList())))).
thenReturn(null);
List<ParsedSplit> splitsResult = (List<ParsedSplit>) _userCustomSplitAdapterConsumer.fetchMany(Stream.of(SPLIT_NAME, SPLIT_NAME+"2").collect(Collectors.toList()));
Map<String, ParsedSplit> splitsResult = _userCustomSplitAdapterConsumer.fetchMany(Stream.of(SPLIT_NAME, SPLIT_NAME+"2").collect(Collectors.toList()));
Assert.assertNotNull(splitsResult);
Assert.assertEquals(0, splitsResult.size());
Assert.assertNull(splitsResult.get(SPLIT_NAME));
Assert.assertNull(splitsResult.get(SPLIT_NAME+"2"));
}

@Test
Expand Down