Skip to content

Commit

Permalink
[SDKS-7540] Create method EvaluateFeaturesByFlagSets in the Evaluator
Browse files Browse the repository at this point in the history
  • Loading branch information
nmayorsplit committed Sep 26, 2023
1 parent f9e7b53 commit 08faef6
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ EvaluatorImp.TreatmentLabelAndChangeNumber evaluateFeature(String matchingKey, S
Map<String, Object> attributes);
Map<String, EvaluatorImp.TreatmentLabelAndChangeNumber> evaluateFeatures(String matchingKey, String bucketingKey,
List<String> featureFlags, Map<String, Object> attributes);
}
EvaluatorImp.ByFlagSetsResult evaluateFeaturesByFlagSets(String key, String bucketingKey, List<String> flagSets);
}
41 changes: 39 additions & 2 deletions client/src/main/java/io/split/engine/evaluator/EvaluatorImp.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.split.engine.evaluator;

import com.google.common.base.Stopwatch;
import io.split.client.dtos.ConditionType;
import io.split.client.exceptions.ChangeNumberExceptionWrapper;
import io.split.engine.experiments.ParsedCondition;
Expand All @@ -11,15 +12,16 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

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

public class EvaluatorImp implements Evaluator {


private static final Logger _log = LoggerFactory.getLogger(EvaluatorImp.class);

private final SegmentCacheConsumer _segmentCacheConsumer;
Expand Down Expand Up @@ -51,6 +53,31 @@ public Map<String, TreatmentLabelAndChangeNumber> evaluateFeatures(String matchi
return results;
}

@Override
public ByFlagSetsResult evaluateFeaturesByFlagSets(String key, String bucketingKey, List<String> flagSets) {
Stopwatch stopwatch = Stopwatch.createStarted();
List<String> flagSetsWithNames = getFeatureFlagNamesByFlagSets(flagSets);
Map<String, TreatmentLabelAndChangeNumber> evaluations = evaluateFeatures(key, bucketingKey, flagSetsWithNames, null);
stopwatch.stop();
long millis = stopwatch.elapsed(TimeUnit.MILLISECONDS);
return new ByFlagSetsResult(evaluations, millis);
}

private List<String> getFeatureFlagNamesByFlagSets(List<String> flagSets) {
HashSet<String> ffNamesToReturn = new HashSet<>();
Map<String, HashSet<String>> namesByFlagSets = _splitCacheConsumer.getNamesByFlagSets(flagSets);
for (String set: flagSets) {
HashSet<String> flags = namesByFlagSets.get(set);
if (flags == null) {
_log.warn(String.format("You passed %s Flag Set that does not contain cached feature flag names, please double check " +
"what Flag Sets are in use in the Split user interface.", set));
continue;
}
ffNamesToReturn.addAll(flags);
}
return new ArrayList<>(ffNamesToReturn);
}

/**
* @param matchingKey MUST NOT be null
* @param bucketingKey
Expand Down Expand Up @@ -128,6 +155,16 @@ private TreatmentLabelAndChangeNumber evaluateParsedSplit(String matchingKey, St
}
}

public static class ByFlagSetsResult {
public final Map<String, TreatmentLabelAndChangeNumber> evaluations;
public final long elapsedMilliseconds;

public ByFlagSetsResult(Map<String, TreatmentLabelAndChangeNumber> evaluations, long elapsed) {
this.evaluations = evaluations;
this.elapsedMilliseconds = elapsed;
}
}

public static final class TreatmentLabelAndChangeNumber {
public final String treatment;
public final String label;
Expand Down
35 changes: 35 additions & 0 deletions client/src/test/java/io/split/engine/evaluator/EvaluatorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
import io.split.engine.matchers.CombiningMatcher;
import io.split.storages.SegmentCacheConsumer;
import io.split.storages.SplitCacheConsumer;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
Expand Down Expand Up @@ -147,4 +149,37 @@ public void evaluateWithWhitelistConditionReturnTreatment() {
assertEquals("test whitelist label", result.label);
assertEquals(CHANGE_NUMBER, result.changeNumber);
}

@Test
public void evaluateWithSets() {
ParsedSplit split = ParsedSplit.createParsedSplitForTests(SPLIT_NAME, 0, false, DEFAULT_TREATMENT_VALUE, _conditions, TRAFFIC_TYPE_VALUE, CHANGE_NUMBER, 2, new HashSet<>(Arrays.asList("set1", "set2")));
List<String> sets = new ArrayList<>(Arrays.asList("set1"));
Map<String, HashSet<String>> flagSets = new HashMap<>();
flagSets.put("set1", new HashSet<>(Arrays.asList(SPLIT_NAME)));
Mockito.when(_splitCacheConsumer.getNamesByFlagSets(sets)).thenReturn(flagSets);
Map<String, ParsedSplit> parsedSplits = new HashMap<>();
parsedSplits.put(SPLIT_NAME, split);
Mockito.when(_splitCacheConsumer.fetchMany(Arrays.asList(SPLIT_NAME))).thenReturn(parsedSplits);

EvaluatorImp.ByFlagSetsResult result = _evaluator.evaluateFeaturesByFlagSets(MATCHING_KEY, BUCKETING_KEY, sets);

EvaluatorImp.TreatmentLabelAndChangeNumber treatmentLabelAndChangeNumber = result.evaluations.get(SPLIT_NAME);

assertEquals(DEFAULT_TREATMENT_VALUE, treatmentLabelAndChangeNumber.treatment);
assertEquals("default rule", treatmentLabelAndChangeNumber.label);
assertEquals(CHANGE_NUMBER, treatmentLabelAndChangeNumber.changeNumber);
}

@Test
public void evaluateWithSetsNotHaveFlags() {
ParsedSplit split = ParsedSplit.createParsedSplitForTests(SPLIT_NAME, 0, false, DEFAULT_TREATMENT_VALUE, _conditions, TRAFFIC_TYPE_VALUE, CHANGE_NUMBER, 2, new HashSet<>(Arrays.asList("set1", "set2")));
List<String> sets = new ArrayList<>(Arrays.asList("set2"));
Map<String, HashSet<String>> flagSets = new HashMap<>();
Mockito.when(_splitCacheConsumer.getNamesByFlagSets(sets)).thenReturn(flagSets);
Map<String, ParsedSplit> parsedSplits = new HashMap<>();
Mockito.when(_splitCacheConsumer.fetchMany(Arrays.asList(SPLIT_NAME))).thenReturn(parsedSplits);

EvaluatorImp.ByFlagSetsResult result = _evaluator.evaluateFeaturesByFlagSets(MATCHING_KEY, BUCKETING_KEY, sets);
Assert.assertTrue(result.evaluations.isEmpty());
}
}

0 comments on commit 08faef6

Please sign in to comment.