Skip to content

Commit 4af6f4f

Browse files
committed
Update client class
1 parent be872d2 commit 4af6f4f

File tree

6 files changed

+548
-90
lines changed

6 files changed

+548
-90
lines changed

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

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
import com.google.gson.GsonBuilder;
44
import io.split.client.api.Key;
55
import io.split.client.api.SplitResult;
6-
import io.split.client.dtos.DecoratedImpression;
7-
import io.split.client.dtos.EvaluationOptions;
8-
import io.split.client.dtos.Event;
6+
import io.split.client.dtos.*;
97
import io.split.client.events.EventsStorageProducer;
108
import io.split.client.impressions.Impression;
119
import io.split.client.impressions.ImpressionsManager;
@@ -14,7 +12,6 @@
1412
import io.split.engine.evaluator.Evaluator;
1513
import io.split.engine.evaluator.EvaluatorImp;
1614
import io.split.engine.evaluator.Labels;
17-
import io.split.grammar.Treatments;
1815
import io.split.inputValidation.EventsValidator;
1916
import io.split.inputValidation.KeyValidator;
2017
import io.split.inputValidation.SplitNameValidator;
@@ -49,7 +46,7 @@
4946
* @author adil
5047
*/
5148
public final class SplitClientImpl implements SplitClient {
52-
public static final SplitResult SPLIT_RESULT_CONTROL = new SplitResult(Treatments.CONTROL, null);
49+
// public static final SplitResult SPLIT_RESULT_CONTROL = new SplitResult(Treatments.CONTROL, null);
5350
private static final String CLIENT_DESTROY = "Client has already been destroyed - no calls possible";
5451
private static final String CATCHALL_EXCEPTION = "CatchAll Exception";
5552
private static final String MATCHING_KEY = "matchingKey";
@@ -66,6 +63,7 @@ public final class SplitClientImpl implements SplitClient {
6663
private final TelemetryEvaluationProducer _telemetryEvaluationProducer;
6764
private final TelemetryConfigProducer _telemetryConfigProducer;
6865
private final FlagSetsFilter _flagSetsFilter;
66+
private final FallbackTreatmentCalculator _fallbackTreatmentCalculator;
6967

7068
public SplitClientImpl(SplitFactory container,
7169
SplitCacheConsumer splitCacheConsumer,
@@ -76,7 +74,8 @@ public SplitClientImpl(SplitFactory container,
7674
Evaluator evaluator,
7775
TelemetryEvaluationProducer telemetryEvaluationProducer,
7876
TelemetryConfigProducer telemetryConfigProducer,
79-
FlagSetsFilter flagSetsFilter) {
77+
FlagSetsFilter flagSetsFilter,
78+
FallbackTreatmentCalculator fallbackTreatmentCalculator) {
8079
_container = container;
8180
_splitCacheConsumer = checkNotNull(splitCacheConsumer);
8281
_impressionManager = checkNotNull(impressionManager);
@@ -87,6 +86,7 @@ public SplitClientImpl(SplitFactory container,
8786
_telemetryEvaluationProducer = checkNotNull(telemetryEvaluationProducer);
8887
_telemetryConfigProducer = checkNotNull(telemetryConfigProducer);
8988
_flagSetsFilter = flagSetsFilter;
89+
_fallbackTreatmentCalculator = fallbackTreatmentCalculator;
9090
}
9191

9292
@Override
@@ -492,31 +492,31 @@ private SplitResult getTreatmentWithConfigInternal(String matchingKey, String bu
492492

493493
if (_container.isDestroyed()) {
494494
_log.error(CLIENT_DESTROY);
495-
return SPLIT_RESULT_CONTROL;
495+
return checkFallbackTreatment(featureFlag);
496496
}
497497

498498
if (!KeyValidator.isValid(matchingKey, MATCHING_KEY, _config.maxStringLength(), methodEnum.getMethod())) {
499-
return SPLIT_RESULT_CONTROL;
499+
return checkFallbackTreatment(featureFlag);
500500
}
501501

502502
if (!KeyValidator.bucketingKeyIsValid(bucketingKey, _config.maxStringLength(), methodEnum.getMethod())) {
503-
return SPLIT_RESULT_CONTROL;
503+
return checkFallbackTreatment(featureFlag);
504504
}
505505

506506
Optional<String> splitNameResult = SplitNameValidator.isValid(featureFlag, methodEnum.getMethod());
507507
if (!splitNameResult.isPresent()) {
508-
return SPLIT_RESULT_CONTROL;
508+
return checkFallbackTreatment(featureFlag);
509509
}
510510
featureFlag = splitNameResult.get();
511511
long start = System.currentTimeMillis();
512512

513513
EvaluatorImp.TreatmentLabelAndChangeNumber result = _evaluator.evaluateFeature(matchingKey, bucketingKey, featureFlag, attributes);
514514

515-
if (result.treatment.equals(Treatments.CONTROL) && result.label.equals(Labels.DEFINITION_NOT_FOUND) && _gates.isSDKReady()) {
515+
if (result.label != null && result.label.contains(Labels.DEFINITION_NOT_FOUND) && _gates.isSDKReady()) {
516516
_log.warn(String.format(
517517
"%s: you passed \"%s\" that does not exist in this environment, " +
518518
"please double check what feature flags exist in the Split user interface.", methodEnum.getMethod(), featureFlag));
519-
return SPLIT_RESULT_CONTROL;
519+
return checkFallbackTreatment(featureFlag);
520520
}
521521

522522
recordStats(
@@ -541,10 +541,19 @@ private SplitResult getTreatmentWithConfigInternal(String matchingKey, String bu
541541
} catch (Exception e1) {
542542
// ignore
543543
}
544-
return SPLIT_RESULT_CONTROL;
544+
return checkFallbackTreatment(featureFlag);
545545
}
546546
}
547547

548+
private SplitResult checkFallbackTreatment(String featureName) {
549+
FallbackTreatment fallbackTreatment = _fallbackTreatmentCalculator.resolve(featureName, "");
550+
String config = null;
551+
if (fallbackTreatment.getConfig() != null) {
552+
config = fallbackTreatment.getConfig().toString();
553+
}
554+
return new SplitResult(fallbackTreatment.getTreatment(), config);
555+
}
556+
548557
private String validateProperties(Map<String, Object> properties) {
549558
if (properties == null){
550559
return null;
@@ -563,6 +572,7 @@ private Map<String, SplitResult> getTreatmentsWithConfigInternal(String matching
563572
_log.error(String.format("%s: featureFlagNames must be a non-empty array", methodEnum.getMethod()));
564573
return new HashMap<>();
565574
}
575+
566576
try {
567577
checkSDKReady(methodEnum, featureFlagNames);
568578
Map<String, SplitResult> result = validateBeforeEvaluate(featureFlagNames, matchingKey, methodEnum, bucketingKey);
@@ -623,17 +633,17 @@ private Map<String, SplitResult> getTreatmentsBySetsWithConfigInternal(String ma
623633
return createMapControl(featureFlagNames);
624634
}
625635
}
636+
626637
private Map<String, SplitResult> processEvaluatorResult(Map<String, EvaluatorImp.TreatmentLabelAndChangeNumber> evaluatorResult,
627638
MethodEnum methodEnum, String matchingKey, String bucketingKey, Map<String,
628639
Object> attributes, long initTime, String properties){
629640
List<DecoratedImpression> decoratedImpressions = new ArrayList<>();
630641
Map<String, SplitResult> result = new HashMap<>();
631642
evaluatorResult.keySet().forEach(t -> {
632-
if (evaluatorResult.get(t).treatment.equals(Treatments.CONTROL) && evaluatorResult.get(t).label.
633-
equals(Labels.DEFINITION_NOT_FOUND) && _gates.isSDKReady()) {
643+
if (evaluatorResult.get(t).label != null && evaluatorResult.get(t).label.contains(Labels.DEFINITION_NOT_FOUND) && _gates.isSDKReady()) {
634644
_log.warn(String.format("%s: you passed \"%s\" that does not exist in this environment please double check " +
635645
"what feature flags exist in the Split user interface.", methodEnum.getMethod(), t));
636-
result.put(t, SPLIT_RESULT_CONTROL);
646+
result.put(t, checkFallbackTreatment(t));
637647
} else {
638648
result.put(t, new SplitResult(evaluatorResult.get(t).treatment, evaluatorResult.get(t).configurations));
639649
decoratedImpressions.add(
@@ -735,7 +745,7 @@ private void checkSDKReady(MethodEnum methodEnum) {
735745

736746
private Map<String, SplitResult> createMapControl(List<String> featureFlags) {
737747
Map<String, SplitResult> result = new HashMap<>();
738-
featureFlags.forEach(s -> result.put(s, SPLIT_RESULT_CONTROL));
748+
featureFlags.forEach(s -> result.put(s, checkFallbackTreatment(s)));
739749
return result;
740750
}
741751
}

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

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.google.common.io.Files;
44
import io.split.client.dtos.BearerCredentialsProvider;
5+
import io.split.client.dtos.FallbackTreatmentCalculatorImp;
56
import io.split.client.dtos.Metadata;
67
import io.split.client.events.EventsSender;
78
import io.split.client.events.EventsStorage;
@@ -256,8 +257,9 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn
256257
_telemetrySyncTask = new TelemetrySyncTask(config.getTelemetryRefreshRate(), _telemetrySynchronizer,
257258
config.getThreadFactory());
258259

260+
FallbackTreatmentCalculatorImp fallbackTreatmentCalculatorImp = new FallbackTreatmentCalculatorImp(null);
259261
// Evaluator
260-
_evaluator = new EvaluatorImp(splitCache, segmentCache, ruleBasedSegmentCache, null);
262+
_evaluator = new EvaluatorImp(splitCache, segmentCache, ruleBasedSegmentCache, fallbackTreatmentCalculatorImp);
261263

262264
// SplitClient
263265
_client = new SplitClientImpl(this,
@@ -269,7 +271,9 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn
269271
_evaluator,
270272
_telemetryStorageProducer, // TelemetryEvaluation instance
271273
_telemetryStorageProducer, // TelemetryConfiguration instance
272-
flagSetsFilter);
274+
flagSetsFilter,
275+
fallbackTreatmentCalculatorImp
276+
);
273277

274278
// SplitManager
275279
_manager = new SplitManagerImpl(splitCache, config, _gates, _telemetryStorageProducer);
@@ -348,8 +352,9 @@ protected SplitFactoryImpl(String apiToken, SplitClientConfig config, CustomStor
348352
_telemetrySynchronizer = new TelemetryConsumerSubmitter(customStorageWrapper, _sdkMetadata);
349353
UserCustomRuleBasedSegmentAdapterConsumer userCustomRuleBasedSegmentAdapterConsumer =
350354
new UserCustomRuleBasedSegmentAdapterConsumer(customStorageWrapper);
355+
FallbackTreatmentCalculatorImp fallbackTreatmentCalculatorImp = new FallbackTreatmentCalculatorImp(null);
351356
_evaluator = new EvaluatorImp(userCustomSplitAdapterConsumer, userCustomSegmentAdapterConsumer,
352-
userCustomRuleBasedSegmentAdapterConsumer, null);
357+
userCustomRuleBasedSegmentAdapterConsumer, fallbackTreatmentCalculatorImp);
353358
_impressionsSender = PluggableImpressionSender.create(customStorageWrapper);
354359
_uniqueKeysTracker = createUniqueKeysTracker(config);
355360
_impressionsManager = buildImpressionsManager(config, userCustomImpressionAdapterConsumer,
@@ -378,7 +383,9 @@ protected SplitFactoryImpl(String apiToken, SplitClientConfig config, CustomStor
378383
_evaluator,
379384
_telemetryStorageProducer, // TelemetryEvaluation instance
380385
_telemetryStorageProducer, // TelemetryConfiguration instance
381-
flagSetsFilter);
386+
flagSetsFilter,
387+
fallbackTreatmentCalculatorImp
388+
);
382389

383390
// SyncManager
384391
_syncManager = new ConsumerSyncManager(synchronizer);
@@ -446,8 +453,9 @@ protected SplitFactoryImpl(SplitClientConfig config) {
446453
SplitTasks splitTasks = SplitTasks.build(_splitSynchronizationTask, _segmentSynchronizationTaskImp,
447454
_impressionsManager, null, null, null);
448455

456+
FallbackTreatmentCalculatorImp fallbackTreatmentCalculatorImp = new FallbackTreatmentCalculatorImp(null);
449457
// Evaluator
450-
_evaluator = new EvaluatorImp(splitCache, segmentCache, ruleBasedSegmentCache, null);
458+
_evaluator = new EvaluatorImp(splitCache, segmentCache, ruleBasedSegmentCache, fallbackTreatmentCalculatorImp);
451459

452460
EventsStorage eventsStorage = new NoopEventsStorageImp();
453461

@@ -461,7 +469,9 @@ protected SplitFactoryImpl(SplitClientConfig config) {
461469
_evaluator,
462470
_telemetryStorageProducer, // TelemetryEvaluation instance
463471
_telemetryStorageProducer, // TelemetryConfiguration instance
464-
flagSetsFilter);
472+
flagSetsFilter,
473+
fallbackTreatmentCalculatorImp
474+
);
465475

466476
// Synchronizer
467477
Synchronizer synchronizer = new LocalhostSynchronizer(splitTasks, _splitFetcher,

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

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,10 @@
33
import io.split.client.dtos.ConditionType;
44
import io.split.client.dtos.FallbackTreatment;
55
import io.split.client.dtos.FallbackTreatmentCalculator;
6-
import io.split.client.dtos.FallbackTreatmentsConfiguration;
76
import io.split.client.exceptions.ChangeNumberExceptionWrapper;
87
import io.split.engine.experiments.ParsedCondition;
98
import io.split.engine.experiments.ParsedSplit;
109
import io.split.engine.splitter.Splitter;
11-
import io.split.grammar.Treatments;
1210
import io.split.storages.RuleBasedSegmentCacheConsumer;
1311
import io.split.storages.SegmentCacheConsumer;
1412
import io.split.storages.SplitCacheConsumer;
@@ -63,7 +61,27 @@ public Map<String, TreatmentLabelAndChangeNumber> evaluateFeatures(String matchi
6361
public Map<String, EvaluatorImp.TreatmentLabelAndChangeNumber> evaluateFeaturesByFlagSets(String key, String bucketingKey,
6462
List<String> flagSets, Map<String, Object> attributes) {
6563
List<String> flagSetsWithNames = getFeatureFlagNamesByFlagSets(flagSets);
66-
return evaluateFeatures(key, bucketingKey, flagSetsWithNames, attributes);
64+
try {
65+
return evaluateFeatures(key, bucketingKey, flagSetsWithNames, attributes);
66+
} catch (Exception e) {
67+
_log.error("Evaluator Exception", e);
68+
return createMapControl(flagSetsWithNames, "exception");
69+
}
70+
}
71+
72+
private Map<String, EvaluatorImp.TreatmentLabelAndChangeNumber> createMapControl(List<String> featureFlags, String label) {
73+
Map<String, TreatmentLabelAndChangeNumber> result = new HashMap<>();
74+
featureFlags.forEach(s -> result.put(s, checkFallbackTreatment(s, label)));
75+
return result;
76+
}
77+
78+
private EvaluatorImp.TreatmentLabelAndChangeNumber checkFallbackTreatment(String featureName, String label) {
79+
FallbackTreatment fallbackTreatment = _fallbackTreatmentCalculator.resolve(featureName, label);
80+
return new EvaluatorImp.TreatmentLabelAndChangeNumber(fallbackTreatment.getTreatment(),
81+
fallbackTreatment.getLabel(),
82+
null,
83+
getFallbackConfig(fallbackTreatment),
84+
false);
6785
}
6886

6987
private List<String> getFeatureFlagNamesByFlagSets(List<String> flagSets) {
@@ -177,13 +195,25 @@ private String getConfig(ParsedSplit parsedSplit, String returnedTreatment) {
177195
return parsedSplit.configurations() != null ? parsedSplit.configurations().get(returnedTreatment) : null;
178196
}
179197

198+
private String getFallbackConfig(FallbackTreatment fallbackTreatment) {
199+
if (fallbackTreatment.getConfig() != null) {
200+
return fallbackTreatment.getConfig().toString();
201+
}
202+
203+
return null;
204+
}
205+
180206
private TreatmentLabelAndChangeNumber evaluateParsedSplit(String matchingKey, String bucketingKey, Map<String, Object> attributes,
181207
ParsedSplit parsedSplit, String featureName) {
182208
try {
183209

184210
if (parsedSplit == null) {
185211
FallbackTreatment fallbackTreatment = _fallbackTreatmentCalculator.resolve(featureName, Labels.DEFINITION_NOT_FOUND);
186-
return new TreatmentLabelAndChangeNumber(fallbackTreatment.getTreatment(), fallbackTreatment.getLabel());
212+
return new TreatmentLabelAndChangeNumber(fallbackTreatment.getTreatment(),
213+
fallbackTreatment.getLabel(),
214+
null,
215+
getFallbackConfig(fallbackTreatment),
216+
true);
187217
}
188218
return getTreatment(matchingKey, bucketingKey, parsedSplit, attributes);
189219
} catch (ChangeNumberExceptionWrapper e) {

0 commit comments

Comments
 (0)