Skip to content

Add fractional evaluation support#8

Open
liamhughes wants to merge 6 commits intomainfrom
liamhughes/devex-82-add-fractional-evaluation-support-to-java-client-library
Open

Add fractional evaluation support#8
liamhughes wants to merge 6 commits intomainfrom
liamhughes/devex-82-add-fractional-evaluation-support-to-java-client-library

Conversation

@liamhughes
Copy link
Copy Markdown
Contributor

@liamhughes liamhughes commented Apr 1, 2026

Background

We are implementing client-side percentage rollout evaluation to our three OpenFeature provider libraries.

The .NET provider had this added in OctopusDeploy/openfeature-provider-dotnet#45.

This PR adds this to the Java library.

Resolves https://linear.app/octopus/issue/DEVEX-82/add-fractional-evaluation-support-to-java-client-library

Changes

  • Added Apache Commons Codec for its Murmur3 hashing algorithm
  • Updated OctopusContext to have the same logical flow as the .NET equivalent, including implementing getNormalizeNumber to hash the evaluationKey + targetingKey for percentage rollout.
  • Extensive tests in OctopusContextTests replace existing tests and these now align with the .NET equivalents to ensure consistent evaluation.
  • Re-enabled the specification tests and updated submodule to latest.

Notes for review

  • Claude ported the tests over from .NET. I have checked them, but would be worth double checking them.
  • I have chosen Apache Commons Codec over Google's Guava for library size, given they both have good reputations. We could use lesser known targeted libraries or copy+paste an open source implementation of the algorithm directly into our repo, but this feels like a good balance to me.
  • I am not convinced of the Reason options chosen. It may be good to talk these through. Or perhaps ignore them until we do reasons properly and across our feature toggles ecosystem.

@liamhughes liamhughes changed the base branch from main to liamhughes/devex-136-use-new-evaluations-endpoint April 1, 2026 02:54
Base automatically changed from liamhughes/devex-136-use-new-evaluations-endpoint to main April 1, 2026 05:15
@liamhughes liamhughes force-pushed the liamhughes/devex-82-add-fractional-evaluation-support-to-java-client-library branch from 1cd8040 to 4f02169 Compare April 1, 2026 05:16
@liamhughes liamhughes force-pushed the liamhughes/devex-82-add-fractional-evaluation-support-to-java-client-library branch from 4f02169 to a53abd3 Compare April 2, 2026 00:29
@@ -26,10 +28,10 @@ byte[] getContentHash() {
}

ProviderEvaluation<Boolean> evaluate(String slug, Boolean defaultValue, EvaluationContext evaluationContext) {
Copy link
Copy Markdown
Contributor Author

@liamhughes liamhughes Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method mostly matches the .NET equivalent logically, though with a different shape. I propose that we align them further prior to the next piece of work in this area.

if (rolloutPercentage < 100) {
return ProviderEvaluation.<Boolean>builder()
.value(false)
.reason(Reason.TARGETING_MATCH.toString())
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@liamhughes liamhughes changed the title Liamhughes/devex 82 add fractional evaluation support to java client library Add fractional evaluation support Apr 2, 2026
return null;
}
List<FeatureToggleEvaluation> evaluations = OctopusObjectMapper.INSTANCE.readValue(httpResponse.body(), new TypeReference<>(){});
var evaluations = OctopusObjectMapper.INSTANCE.readValue(httpResponse.body(), new TypeReference<List<FeatureToggleEvaluation>>(){});
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I lied in my last PR. Well, not that I lied, but I did think we were on Java 8 rather than 11.

@liamhughes liamhughes requested a review from Copilot April 2, 2026 04:30
@liamhughes liamhughes marked this pull request as ready for review April 2, 2026 04:31
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds client-side fractional (percentage) rollout evaluation to the Java OpenFeature provider, aligning behavior with the .NET provider and re-enabling the spec fixture suite.

Changes:

  • Introduced MurmurHash3-based bucketing (evaluationKey + targetingKey) to support percentage rollouts.
  • Updated evaluation flow in OctopusContext to incorporate rollout checks before segment matching.
  • Reworked/expanded tests (including re-enabling spec fixture tests) to validate cross-SDK-consistent bucketing and evaluation behavior.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/main/java/com/octopus/openfeature/provider/OctopusContext.java Implements normalized bucketing via MurmurHash3 and integrates rollout gating into flag evaluation flow.
src/test/java/com/octopus/openfeature/provider/OctopusContextTests.java Replaces prior tests with extensive rollout + segment evaluation cases and cross-SDK bucketing vectors.
src/test/java/com/octopus/openfeature/provider/SpecificationTests.java Re-enables parameterized specification fixture tests.
src/test/java/com/octopus/openfeature/provider/FeatureToggleEvaluationDeserializationTests.java Tightens TypeReference typing for toggle list deserialization.
src/main/java/com/octopus/openfeature/provider/OctopusClient.java Tightens TypeReference typing when deserializing toggle evaluations.
pom.xml Adds Apache Commons Codec dependency for MurmurHash3.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants