From caa99aedb1332853330b2acd76b9e1f4848e0ab1 Mon Sep 17 00:00:00 2001 From: Simon Schrottner Date: Sat, 7 Sep 2024 17:46:36 +0200 Subject: [PATCH 1/2] feat(flagd-inprocess): Use program flow instead of exceptions for flag not found errors Exceptions are expensive GOTO statements, and in a performance relevant system not the best to be used for control flow . A FlagNotFound-Error can be expected, but the performance draw backs of exception in this case not. Signed-off-by: Simon Schrottner --- .../flagd/resolver/process/InProcessResolver.java | 11 +++++++++-- .../resolver/process/InProcessResolverTest.java | 12 +++++------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/process/InProcessResolver.java b/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/process/InProcessResolver.java index 120ebad5a..5657e331e 100644 --- a/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/process/InProcessResolver.java +++ b/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/process/InProcessResolver.java @@ -12,6 +12,7 @@ import dev.openfeature.contrib.providers.flagd.resolver.process.storage.connector.grpc.GrpcStreamConnector; import dev.openfeature.contrib.providers.flagd.resolver.process.targeting.Operator; import dev.openfeature.contrib.providers.flagd.resolver.process.targeting.TargetingRuleException; +import dev.openfeature.sdk.ErrorCode; import dev.openfeature.sdk.EvaluationContext; import dev.openfeature.sdk.ImmutableMetadata; import dev.openfeature.sdk.ProviderEvaluation; @@ -164,12 +165,18 @@ private ProviderEvaluation resolve(Class type, String key, EvaluationC // missing flag if (flag == null) { - throw new FlagNotFoundError("flag: " + key + " not found"); + return ProviderEvaluation.builder() + .errorMessage("flag: " + key + " not found") + .errorCode(ErrorCode.FLAG_NOT_FOUND) + .build(); } // state check if ("DISABLED".equals(flag.getState())) { - throw new FlagNotFoundError("flag: " + key + " is disabled"); + return ProviderEvaluation.builder() + .errorMessage("flag: " + key + " is disabled") + .errorCode(ErrorCode.FLAG_NOT_FOUND) + .build(); } final String resolvedVariant; 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 9953b337f..7452cba6a 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 @@ -8,6 +8,7 @@ import dev.openfeature.contrib.providers.flagd.resolver.process.storage.StorageStateChange; import dev.openfeature.contrib.providers.flagd.resolver.process.storage.connector.file.FileConnector; import dev.openfeature.contrib.providers.flagd.resolver.process.storage.connector.grpc.GrpcStreamConnector; +import dev.openfeature.sdk.ErrorCode; import dev.openfeature.sdk.ImmutableContext; import dev.openfeature.sdk.ImmutableMetadata; import dev.openfeature.sdk.MutableContext; @@ -239,10 +240,8 @@ public void missingFlag() throws Exception { }); // when/then - assertThrows(FlagNotFoundError.class, () -> { - inProcessResolver.booleanEvaluation("missingFlag", false, new ImmutableContext()); - - }); + ProviderEvaluation missingFlag = inProcessResolver.booleanEvaluation("missingFlag", false, new ImmutableContext()); + assertEquals(ErrorCode.FLAG_NOT_FOUND, missingFlag.getErrorCode()); } @Test @@ -256,9 +255,8 @@ public void disabledFlag() throws Exception { }); // when/then - assertThrows(FlagNotFoundError.class, () -> { - inProcessResolver.booleanEvaluation("disabledFlag", false, new ImmutableContext()); - }); + ProviderEvaluation disabledFlag = inProcessResolver.booleanEvaluation("disabledFlag", false, new ImmutableContext()); + assertEquals(ErrorCode.FLAG_NOT_FOUND, disabledFlag.getErrorCode()); } @Test From 4dbb4c0fd09fcc25bd9a2c021ab95f149ed2dc31 Mon Sep 17 00:00:00 2001 From: Simon Schrottner Date: Tue, 17 Sep 2024 19:41:12 +0200 Subject: [PATCH 2/2] Update providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/process/InProcessResolver.java Co-authored-by: Todd Baert Signed-off-by: Simon Schrottner --- .../providers/flagd/resolver/process/InProcessResolver.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/process/InProcessResolver.java b/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/process/InProcessResolver.java index 5657e331e..a576443af 100644 --- a/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/process/InProcessResolver.java +++ b/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/process/InProcessResolver.java @@ -19,7 +19,6 @@ import dev.openfeature.sdk.ProviderState; import dev.openfeature.sdk.Reason; import dev.openfeature.sdk.Value; -import dev.openfeature.sdk.exceptions.FlagNotFoundError; import dev.openfeature.sdk.exceptions.ParseError; import dev.openfeature.sdk.exceptions.TypeMismatchError; import lombok.extern.slf4j.Slf4j; @@ -165,7 +164,7 @@ private ProviderEvaluation resolve(Class type, String key, EvaluationC // missing flag if (flag == null) { - return ProviderEvaluation.builder() + return ProviderEvaluation.builder() .errorMessage("flag: " + key + " not found") .errorCode(ErrorCode.FLAG_NOT_FOUND) .build();