You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We conducted a cross-SDK comparison of all MultiProvider implementations using the js-sdk as the reference. The Swift MultiProvider is functional for basic use cases, but we identified several gaps relative to the reference implementation.
Note: Some gaps (like shutdown propagation) are blocked by SDK-level prerequisites that are tracked separately (#97).
Gaps
1. Aggregate event/status tracking (High)
The MultiProvider merges child provider event streams via Publishers.MergeMany, which forwards raw events directly to subscribers with no aggregation. If one child provider emits .error while another is .ready, both events pass through independently and there is no composite status. Consumers have no way to know the overall health of the MultiProvider.
Expected behavior:
Maintain a per-provider status map
Compute an aggregate status using "worst-wins" precedence: FATAL > NOT_READY > ERROR > STALE > RECONCILING > READY
Only emit an event when the aggregate status actually changes (deduplication)
Always forward .configurationChanged events as a pass-through regardless of status changes
2. Per-provider hook execution during evaluation (High)
The hooks property returns an empty array. The strategy calls provider evaluation methods directly, bypassing any hooks the child providers may define. If a child provider returns hooks via its hooks property, those hooks are not executed.
Expected behavior:
Before evaluating a child provider, run its before hooks with an isolated copy of the hook context
On success: run after hooks
On error: run error hooks
Always: run finally hooks
Hook context must be isolated per-provider to prevent cross-provider mutation
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 onMismatch callback and return the designated fallback provider's result
If any provider errors, collect and report all errors
Constructor accepts a fallbackProvider and optional onMismatch callback
5. Unique provider naming with deduplication (Low)
There is no unique naming or deduplication for child providers. If two providers share the same metadata name, there is no disambiguation. This affects event attribution and debugging.
Expected behavior:
If multiple providers share the same metadata-derived name, auto-deduplicate with a numeric suffix (name-1, name-2, etc.)
Expose child provider metadata keyed by unique name
Context
We conducted a cross-SDK comparison of all MultiProvider implementations using the js-sdk as the reference. The Swift MultiProvider is functional for basic use cases, but we identified several gaps relative to the reference implementation.
Note: Some gaps (like shutdown propagation) are blocked by SDK-level prerequisites that are tracked separately (#97).
Gaps
1. Aggregate event/status tracking (High)
The MultiProvider merges child provider event streams via
Publishers.MergeMany, which forwards raw events directly to subscribers with no aggregation. If one child provider emits.errorwhile another is.ready, both events pass through independently and there is no composite status. Consumers have no way to know the overall health of the MultiProvider.Expected behavior:
FATAL > NOT_READY > ERROR > STALE > RECONCILING > READY.configurationChangedevents as a pass-through regardless of status changesReference: js-sdk
status-tracker.ts, dotnet-sdkHandleProviderEventAsync/DetermineAggregateStatus, kotlin-sdkhandleProviderEvent/calculateAggregateStatus2. Per-provider hook execution during evaluation (High)
The
hooksproperty returns an empty array. The strategy calls provider evaluation methods directly, bypassing any hooks the child providers may define. If a child provider returns hooks via itshooksproperty, those hooks are not executed.Expected behavior:
beforehooks with an isolated copy of the hook contextafterhookserrorhooksfinallyhooksReference: js-sdk
hook-executor.ts, go-sdkisolation.go, dotnet-sdkProviderExtensions.EvaluateAsync3. Tracking event forwarding (High)
The MultiProvider relies on the default no-op
track()extension onFeatureProvider. Tracking events are not forwarded to child providers.Expected behavior:
track()callstrack()calls should be caught and logged, not propagatedReference: js-sdk
multi-provider.tstrack(), dotnet-sdkMultiProvider.csTrack()4. ComparisonStrategy (Medium)
Only
FirstMatchStrategyandFirstSuccessfulStrategyexist. There is noComparisonStrategyfor evaluating all providers and comparing results (useful for migration validation and consistency checks).Expected behavior:
onMismatchcallback and return the designated fallback provider's resultfallbackProviderand optionalonMismatchcallbackReference: js-sdk
comparison-strategy.ts, go-sdkcomparison_strategy.go, dotnet-sdkComparisonStrategy.cs5. Unique provider naming with deduplication (Low)
There is no unique naming or deduplication for child providers. If two providers share the same metadata name, there is no disambiguation. This affects event attribution and debugging.
Expected behavior:
name-1,name-2, etc.)Reference: js-sdk
registerProviders(), dotnet-sdkRegisterProviders(), kotlin-sdktoChildFeatureProviders()Blocked / Deferred
Spec Reference
https://openfeature.dev/specification/appendix-a/#multi-provider