Bug: Resolve feature flags for the member, not anonymously, from the first fetch - #3113
Draft
panasetskaya wants to merge 1 commit into
Draft
Bug: Resolve feature flags for the member, not anonymously, from the first fetch#3113panasetskaya wants to merge 1 commit into
panasetskaya wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The analytics-consent step appeared in onboarding on a build where
disable_analyticswas ON at 100% in production.Root cause
Unleash evaluates strategies server-side against the context of the fetch.
HedvigUnleashClientconstructedDefaultUnleashwithmemberId = null, started it, and only switched context onceMemberIdServiceemitted — so the first fetch of every launch was anonymous.disable_analyticsusedmemberIdstickiness. Flexible rollout resolves the stickiness field out of the context before applying the percentage and returns false when it's absent, so at 100% the flag still came back off. Confirmed against the frontend API: with the app's startup context the toggle is absent from the response; addproperties[memberId]and it comes back enabled.The SDK then raised
isReady()on that anonymous set, soawaitReady()was satisfied by it.neverFetchedDefaultsdidn't help — it only applies while!isReady(), and an absent toggle in a delivered set correctly reads false, since that's how Unleash expresses "off".OnboardingGateawaited readiness, read the kill switch as off, andOnboardingSessionStorepinned the resulting path for the whole flow, so the later correct value couldn't remove the step.Changes
client.start(), so the first fetch names them. This also makes the SDK's on-disk backup usable again — it's keyed bycontext.hashCode(), which the anonymous startup context never matched.awaitReady()now additionally requires that the toggles in hand were fetched for the context currently in effect. Seeding can't cover a login inside a running process, which is exactly whenOnboardingGateasks. It had one caller, so the iOS/JVM/fake implementations are untouched.userIdalongside thememberIdproperty.defaultstickiness resolves userId → sessionId → random, and the app sent neither, so any rollout under 100% was re-diced on every 2s poll.valueOf()is deliberately unchanged: gating it on member-match would push every flag to its default during the post-login window.