From ee9d3d5d3c3e41ff3d73072b6e40c5356da969a9 Mon Sep 17 00:00:00 2001 From: Kavindu Dodanduwa Date: Fri, 1 Sep 2023 13:54:43 -0700 Subject: [PATCH] resolving logic cleanup Signed-off-by: Kavindu Dodanduwa --- providers/flagd/pom.xml | 2 +- .../flagd/resolver/grpc/GrpcConnector.java | 1 + .../resolver/process/InProcessResolver.java | 42 ++++++++++++++----- .../connector/GrpcStreamConnector.java | 7 +++- .../process/InProcessResolverTest.java | 30 +------------ 5 files changed, 40 insertions(+), 42 deletions(-) diff --git a/providers/flagd/pom.xml b/providers/flagd/pom.xml index 2caffc7be..9158179e4 100644 --- a/providers/flagd/pom.xml +++ b/providers/flagd/pom.xml @@ -10,7 +10,7 @@ dev.openfeature.contrib.providers flagd - 0.6.1 + 999-snapshot diff --git a/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/grpc/GrpcConnector.java b/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/grpc/GrpcConnector.java index fea2b70f5..1d2d4d379 100644 --- a/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/grpc/GrpcConnector.java +++ b/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/grpc/GrpcConnector.java @@ -69,6 +69,7 @@ public GrpcConnector(final FlagdOptions options, final Cache cache, Consumer ProviderEvaluation resolveGeneric(Class type, String key, T de EvaluationContext ctx) { final FeatureFlag flag = flagStore.getFLag(key); + // missing flag if (flag == null) { return ProviderEvaluation.builder() .value(defaultValue) @@ -84,7 +85,7 @@ private ProviderEvaluation resolveGeneric(Class type, String key, T de if ("DISABLED".equals(flag.getState())) { return ProviderEvaluation.builder() .value(defaultValue) - .reason(Reason.ERROR.toString()) + .reason(Reason.DISABLED.toString()) .errorCode(ErrorCode.GENERAL) .errorMessage(String.format("requested flag is disabled: %s", key)) .build(); @@ -94,12 +95,21 @@ private ProviderEvaluation resolveGeneric(Class type, String key, T de final Object resolvedVariant; final String reason; - if (flag.getTargeting() != "{}") { + if ("{}".equals(flag.getTargeting())) { + resolvedVariant = flag.getDefaultVariant(); + reason = Reason.STATIC.toString(); + } else { try { - resolvedVariant = jsonLogicHandler.apply(flag.getTargeting(), ctx.asObjectMap()); - reason = Reason.TARGETING_MATCH.toString(); + final Object jsonResolved = jsonLogicHandler.apply(flag.getTargeting(), ctx.asObjectMap()); + if (jsonResolved == null) { + resolvedVariant = flag.getDefaultVariant(); + reason = Reason.DEFAULT.toString(); + } else { + resolvedVariant = jsonResolved; + reason = Reason.TARGETING_MATCH.toString(); + } } catch (JsonLogicException e) { - log.log(Level.INFO, "Error evaluating targeting rule", e); + log.log(Level.FINE, "Error evaluating targeting rule", e); return ProviderEvaluation.builder() .value(defaultValue) .reason(Reason.ERROR.toString()) @@ -107,12 +117,23 @@ private ProviderEvaluation resolveGeneric(Class type, String key, T de .errorMessage(String.format("error parsing targeting rule: %s", key)) .build(); } - } else { - resolvedVariant = flag.getVariants().get(flag.getDefaultVariant()); - reason = Reason.STATIC.toString(); } - if (!resolvedVariant.getClass().isAssignableFrom(type)) { + // check variant existence + Object value = flag.getVariants().get(resolvedVariant); + if (value == null){ + log.log(Level.FINE, String.format("variant %s not found in flag with key %s", resolvedVariant, key)); + return ProviderEvaluation.builder() + .value(defaultValue) + .reason(Reason.ERROR.toString()) + .errorCode(ErrorCode.TYPE_MISMATCH) + .errorMessage(String.format("requested flag is not of the evaluation type: %s", type.getName())) + .build(); + } + + if (!value.getClass().isAssignableFrom(type) || !(resolvedVariant instanceof String)) { + log.log(Level.FINE, String.format("returning default variant for flagKey: %s, type not valid", key)); + return ProviderEvaluation.builder() .value(defaultValue) .reason(Reason.ERROR.toString()) @@ -122,7 +143,8 @@ private ProviderEvaluation resolveGeneric(Class type, String key, T de } return ProviderEvaluation.builder() - .value((T) resolvedVariant) + .value((T) value) + .variant((String) resolvedVariant) .reason(reason) .build(); } diff --git a/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/process/storage/connector/GrpcStreamConnector.java b/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/process/storage/connector/GrpcStreamConnector.java index 60c8b95f5..7e2b6431c 100644 --- a/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/process/storage/connector/GrpcStreamConnector.java +++ b/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/process/storage/connector/GrpcStreamConnector.java @@ -34,13 +34,16 @@ public GrpcStreamConnector(final FlagdOptions options) { } public void init(Consumer callback) { - new Thread(() -> { + Thread listener = new Thread(() -> { try { observeEventStream(callback, shutdown, serviceStub); } catch (InterruptedException e) { log.log(Level.WARNING, "Event stream interrupted, flag configurations are stale", e); } - }).start(); + }); + + listener.setDaemon(true); + listener.start(); } public void shutdown() { diff --git a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/resolver/process/InProcessResolverTest.java b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/resolver/process/InProcessResolverTest.java index 3926133f8..5dc484a00 100644 --- a/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/resolver/process/InProcessResolverTest.java +++ b/providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/resolver/process/InProcessResolverTest.java @@ -1,15 +1,8 @@ package dev.openfeature.contrib.providers.flagd.resolver.process; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import dev.openfeature.contrib.providers.flagd.FlagdOptions; -import io.github.jamsesso.jsonlogic.JsonLogic; -import io.github.jamsesso.jsonlogic.JsonLogicException; import org.junit.jupiter.api.Test; -import java.util.HashMap; -import java.util.Map; - class InProcessResolverTest { @Test @@ -23,32 +16,11 @@ public void testInitializer() throws Exception { resolver.init(); - // delay for init - Thread.sleep(2000); - resolver.booleanEvaluation("booleanFlag", false, null); + resolver.integerEvaluation("booleanFlag", 1, null); Thread.sleep(100_000); } - @Test - public void jsonEvaluator() throws JsonProcessingException { - String logic = "{\"if\":[{\"in\":[\"@faas.com\",{\"var\":[\"email\"]}]},\"binet\",null]}"; - - ObjectMapper mapper = new ObjectMapper(); - - Map ctx = new HashMap<>(); - ctx.put("email", "abc@faas.com"); - - JsonLogic jsonLogic = new JsonLogic(); - - try { - Object result = jsonLogic.apply(logic, ctx); - - System.out.println(result); - } catch (JsonLogicException e) { - throw new RuntimeException(e); - } - } } \ No newline at end of file