From 04df6669264227e3c3c6165ea0d876e5d8aa8766 Mon Sep 17 00:00:00 2001 From: Liran M <77168114+liran2000@users.noreply.github.com> Date: Mon, 26 Feb 2024 22:28:48 +0200 Subject: [PATCH] feat: Statsig provider evaluate boolean updates (#691) Signed-off-by: liran2000 --- providers/statsig/README.md | 8 ++++++- .../providers/statsig/StatsigProvider.java | 23 +++++++++++++++++-- .../statsig/StatsigProviderTest.java | 12 ++++++++++ 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/providers/statsig/README.md b/providers/statsig/README.md index e71356414..1c565b35c 100644 --- a/providers/statsig/README.md +++ b/providers/statsig/README.md @@ -18,10 +18,11 @@ ## Concepts -* Boolean evaluation gets [gate](https://docs.statsig.com/server/javaSdk#checking-a-gate) status. * String/Integer/Double evaluations evaluation gets [Dynamic config](https://docs.statsig.com/server/javaSdk#reading-a-dynamic-config) or [Layer](https://docs.statsig.com/server/javaSdk#getting-an-layerexperiment) evaluation. As the key represents an inner attribute, feature config is required as a parameter with data needed for evaluation. For an example of dynamic config of product alias, need to differentiate between dynamic config or layer, and the dynamic config name. +* Boolean evaluation gets [gate](https://docs.statsig.com/server/javaSdk#checking-a-gate) status when feature config is not passed. + When feature config exists, it evaluates to the config/layer attribute, similar to String/Integer/Float evaluations. * Object evaluation gets a structure representing the dynamic config or layer. * [Private Attributes](https://docs.statsig.com/server/javaSdk#private-attributes) are supported as 'privateAttributes' context key. @@ -71,3 +72,8 @@ Unit test based on Statsig [Local Overrides](https://docs.statsig.com/server/jav As it is limited, evaluation context based tests are limited. See [statsigProviderTest](./src/test/java/dev/openfeature/contrib/providers/statsig/StatsigProviderTest.java) for more information. + +## Known issues +- Gate BooleanEvaluation with default value true cannot fallback to true. + https://github.com/statsig-io/java-server-sdk/issues/22 + diff --git a/providers/statsig/src/main/java/dev/openfeature/contrib/providers/statsig/StatsigProvider.java b/providers/statsig/src/main/java/dev/openfeature/contrib/providers/statsig/StatsigProvider.java index bff88088e..f70097678 100644 --- a/providers/statsig/src/main/java/dev/openfeature/contrib/providers/statsig/StatsigProvider.java +++ b/providers/statsig/src/main/java/dev/openfeature/contrib/providers/statsig/StatsigProvider.java @@ -85,8 +85,27 @@ public Metadata getMetadata() { public ProviderEvaluation getBooleanEvaluation(String key, Boolean defaultValue, EvaluationContext ctx) { verifyEvaluation(); StatsigUser user = ContextTransformer.transform(ctx); - Future featureOn = Statsig.checkGateAsync(user, key); - Boolean evaluatedValue = featureOn.get(); + Boolean evaluatedValue = defaultValue; + try { + FeatureConfig featureConfig = parseFeatureConfig(ctx); + switch (featureConfig.getType()) { + case CONFIG: + DynamicConfig dynamicConfig = fetchDynamicConfig(user, featureConfig); + evaluatedValue = dynamicConfig.getBoolean(key, defaultValue); + break; + case LAYER: + Layer layer = fetchLayer(user, featureConfig); + evaluatedValue = layer.getBoolean(key, defaultValue); + break; + default: + break; + } + } catch (Exception e) { + log.debug("could not fetch feature config. checking gate {}.", key); + Future featureOn = Statsig.checkGateAsync(user, key); + evaluatedValue = featureOn.get(); + } + return ProviderEvaluation.builder() .value(evaluatedValue) .build(); diff --git a/providers/statsig/src/test/java/dev/openfeature/contrib/providers/statsig/StatsigProviderTest.java b/providers/statsig/src/test/java/dev/openfeature/contrib/providers/statsig/StatsigProviderTest.java index 6fa5a3a17..b36c3a747 100644 --- a/providers/statsig/src/test/java/dev/openfeature/contrib/providers/statsig/StatsigProviderTest.java +++ b/providers/statsig/src/test/java/dev/openfeature/contrib/providers/statsig/StatsigProviderTest.java @@ -75,6 +75,7 @@ static void setUp() { private static void buildFlags() { Statsig.overrideGate(FLAG_NAME, true); Map configMap = new HashMap<>(); + configMap.put("boolean", true); configMap.put("alias", "test"); configMap.put("revision", INT_FLAG_VALUE); configMap.put("price", DOUBLE_FLAG_VALUE); @@ -118,6 +119,17 @@ void getBooleanEvaluation() { assertEquals(true, client.getBooleanValue(FLAG_NAME, false)); assertEquals(false, statsigProvider.getBooleanEvaluation("non-existing", false, new ImmutableContext()).getValue()); assertEquals(false, client.getBooleanValue("non-existing", false)); + + // expected to succeed when https://github.com/statsig-io/java-server-sdk/issues/22 is resolved and adopted +// assertEquals(true, client.getBooleanValue("non-existing", true)); + + MutableContext evaluationContext = new MutableContext(); + MutableContext featureConfig = new MutableContext(); + featureConfig.add("type", "CONFIG"); + featureConfig.add("name", "product"); + evaluationContext.add("feature_config", featureConfig); + assertEquals(true, statsigProvider.getBooleanEvaluation("boolean", false, + evaluationContext).getValue()); } @Test