Repository navigation
fix: re-evaluate remotely on every context change and discard stale responses - #186
Closed
vazarkevych wants to merge 3 commits into
Closed
vazarkevych wants to merge 3 commits into
vazarkevych wants to merge 3 commits into
Conversation
This was referenced Oct 20, 2026
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.
Summary
Fixes the remote-evaluation flow so a context change always reaches the server, streamed updates work with remote evaluation, and the SDK never settles on a response built for an older state. Split out of #176 (section 2, "Remote-eval flow"); the other parts of #176 follow as separate PRs.
Bugs fixed
setAttributes,setAttributesAsyncandsetForcedFeaturesdid not trigger a new evaluation, so the server kept evaluating the previous inputs. They now do;setAttributesAsyncawaits it. (setAttributeOverridesandsetForcedVariationsalready did.)features-updated, a payload-less "please refetch" event, which the SDK ignored; afeaturesevent, had one arrived, would have replaced the personalized features with the unevaluated payload.DioClientnow reportsfeatures-updatedas an empty payload, and in remote-eval mode any stream event triggers a fresh POST instead of being applied, asfeature-repository.tsdoes in the JS SDK. Without remote evaluation,features-updatedtriggers a GET.The payload is built by a provider at the start of each round (
RemoteEvalRequestProvider), so every request carries the inputs as they are at that moment.Compatibility
FeatureViewModel.fetchFeatures(remoteEval:, payload:)is deprecated but still works for callers that construct the view model themselves.BaseClient.consumeSseConnectionsnow documents that afeatures-updatedevent is reported as an empty map. Custom clients that never report it keep working as before.setAttributesandsetForcedFeaturesnow issue a POST. Rapid changes mean more requests; superseded responses are discarded.Test plan
flutter test: 357 tests. 16 new:mainand pass here. The 2 control tests (remote evaluation off) pass on both.features-updatedtests forDioClientand for the non-remote-eval refetch, each fail when the corresponding fix is reverted.caching_manager_testis flaky onmainas well (shared temp cache directory); feat: add CacheStorage abstraction with per-connection namespace and custom cache directory #185 isolates the test caches.dart analyze --fatal-infosanddart format --set-exit-if-changed: clean.backgroundSync: true) with the example app on the iOS simulator:setForcedFeaturesapplied the forced value;features-updated→ POST, while the personalized and forced values were kept.FeatureViewModelconstructor call (both add an argument). The combination passes onceFeatureViewModel.manageris optional, which feat: add CacheStorage abstraction with per-connection namespace and custom cache directory #185 now does.