[Multi-provider] Gaps identified relative to js-sdk reference implementation
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 35/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Stale
- Tech stack
- java
- Domain
- api, backend-api-design
Research direction
Start by locating the Java MultiProvider, FirstMatchStrategy, and FirstSuccessfulStrategy implementations and compare them with the referenced js-sdk and other SDK implementations. Work through the five gaps separately, beginning with event aggregation and hook execution. Done means child events, hooks, tracking, comparison behavior, and duplicate-name handling match the stated expectations without losing providers.
Written by the indexing model from the issue text.
Description
Context
We conducted a cross-SDK comparison of all MultiProvider implementations using the js-sdk as the reference. The Java MultiProvider was recently moved into the core SDK in #1765, and while functional for basic use cases, we identified several gaps relative to the reference implementation. Some of these were already noted during the original PR review.
Gaps
1. Child provider event aggregation and status tracking (High)
The MultiProvider extends EventProvider but does not listen to or forward events from child providers. If a child provider emits PROVIDER_ERROR, PROVIDER_STALE, or PROVIDER_CONFIGURATION_CHANGED at runtime, those events are not surfaced. This was called out in the #1765 review by @guidobrei:
"we effectively lose the Event features when using MultiProvider"
Expected behavior:
- Listen to each child provider's events
- Maintain a per-provider status map
- Compute an aggregate status using "worst-wins" precedence:
FATAL > NOT_READY > ERROR > STALE > READY - Emit the corresponding event when the aggregate status changes
- Always forward
PROVIDER_CONFIGURATION_CHANGEDevents (pass-through)
Reference: js-sdk status-tracker.ts, dotnet-sdk HandleProviderEventAsync / DetermineAggregateStatus
2. Per-provider hook execution during evaluation (High)
The strategy calls provider evaluation methods directly (e.g. provider.getBooleanEvaluation(...)), bypassing the SDK's hook pipeline. If a child provider defines hooks via getProviderHooks(), those hooks are not executed.
Expected behavior:
- Before evaluating a child provider, run its
beforehooks with an isolated copy of the hook context - On success: run
afterhooks - On error: run
errorhooks - Always: run
finallyhooks - Hook context must be isolated per-provider to prevent cross-provider mutation
Reference: js-sdk hook-executor.ts, go-sdk isolation.go, dotnet-sdk ProviderExtensions.EvaluateAsync
3. Tracking event forwarding (High)
track() is not overridden. The default no-op implementation means tracking events are not forwarded to child providers.
Expected behavior:
- Iterate over child providers and forward
track()calls - The strategy should control which providers receive tracking (e.g. skip
NOT_READY/FATALproviders) - Errors from individual
track()calls should be caught and logged, not propagated
Reference: js-sdk multi-provider.ts track(), dotnet-sdk MultiProvider.cs Track()
4. ComparisonStrategy (Medium)
Only FirstMatchStrategy and FirstSuccessfulStrategy exist. There is no ComparisonStrategy for evaluating all providers and comparing results (useful for migration validation and consistency checks).
Expected behavior:
- Evaluate all providers (ideally in parallel)
- If all providers agree on the value, return it
- If providers disagree, call an optional
onMismatchcallback and return the designated fallback provider's result - If any provider errors, collect and report all errors
- Constructor accepts a
fallbackProviderand optionalonMismatchcallback
Reference: js-sdk comparison-strategy.ts, go-sdk comparison_strategy.go, dotnet-sdk ComparisonStrategy.cs
5. Duplicate provider name handling (Medium)
When two child providers share the same metadata.name, the later provider silently overwrites the earlier one in the internal LinkedHashMap. The first provider is effectively lost. Related to #1792.
Expected behavior:
- If an explicit name conflicts with an existing name, throw (misconfiguration)
- If multiple providers share the same metadata-derived name, auto-deduplicate with a numeric suffix (
name-1,name-2, etc.) - All providers should be preserved
Reference: js-sdk registerProviders(), dotnet-sdk RegisterProviders()
Spec Reference
https://openfeature.dev/specification/appendix-a/#multi-provider
- Dominant language
- Java
- Stars
- 128
- Forks
- 61
- Avg merge
- 5h 57m
- Merged PRs (30d)
- 26
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from open-feature/java-sdk
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
open-feature/java-sdk#2019 · 1 comment ·
-
Difficulty 1/5 Under an hour Newbie friendliness 88/100
open-feature/java-sdk#2014 · 1 comment ·
-
v0.9.0
Difficulty 5/5 Over a week Newbie friendliness 35/100
open-feature/java-sdk#1999 ·
-
on setProvider call, shutting down the previous provider should happen before creating the new one Open
Difficulty 3/5 1-2 days Newbie friendliness 50/100
open-feature/java-sdk#1934 · 1 reaction ·
-
open-feature/java-sdk#1792 · 1 assignee ·
All issues in open-feature/java-sdk
Similar issues
-
bug
Difficulty 1/5 Under an hour Newbie friendliness 90/100
apache/cloudstack#14222 ·
-
[BUG]茶杯方块在取茶时会引发崩溃 Open
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
1.0.0-alpha2 Type/Improvement
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
wso2/dpdp-accelerator#272 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
infinispan/infinispan#18150 ·
-
area/frontend
Difficulty 2/5 1-3 hours Newbie friendliness 65/100