Repository navigation
fix(firestore): always send the final loadBundle snapshot - #18813
Conversation
The plugin started loading the bundle and only then attached its progress listener (Android) or observer (Apple). Neither SDK replays the current state to a listener added later, so when the bundle finished loading first, the success snapshot was never sent and LoadBundleTask.stream never closed. Send the final snapshot from a callback registered with the task itself, which also runs for a task that has already completed: addOnSuccessListener on Android, and the loadBundle:completion: handler on iOS and macOS. Progress listeners now only forward in-progress snapshots, so success is sent once.
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. |
Description
LoadBundleTask.streamcan hang forever on Android and Apple platforms because the finalsuccesssnapshot is sometimes never sent.The Dart stream only closes when it receives a snapshot with
taskState == success. Natively, the plugin starts the load and then attaches a progress listener (AndroidaddOnProgressListener, AppleaddObserver). Neither SDK replays the current state to a listener added late:LoadBundleTask.setResult(Android) andLoadBundleTask::SetSuccess(Apple) only notify the listeners registered at that moment. If the bundle finishes loading before the listener is attached,successis never sent andawait task.stream.lastnever completes. This is likely for small bundles or bundles already in the cache.This is what keeps failing
loadBundle(): LoadBundleTaskProgress stream snapshotson the Android e2e job: it runs into the 5 minute test timeout onmainand on unrelated PRs. #18522 already bounded the fixture download, so the remaining hang is the stream itself.The final snapshot now comes from a callback registered with the task itself, which also runs when the task has already completed:
addOnSuccessListenersends the final snapshot. The progress listener only forwards non-success snapshots, sosuccessis sent once.loadBundle:completion:handler, which the SDK registers when the task is created, sends the final snapshot as well as errors. The observer only forwards in-progress snapshots.Windows is not affected: its progress callback is passed to
LoadBundlewhen the load starts.Testing
On an Android emulator (API 36) against the Firestore emulator, I ran a local stress loop that reloads an already-cached bundle and waits up to 5 s for
task.stream.lasteach time:With the fix, the
loadBundle()andnamedQuery*()e2e tests pass on Android. I haven't run iOS/macOS locally, so the e2e jobs here cover them. The no-replay behavior is the same in the Apple SDK (LoadBundleTask::Observe/SetSuccess).Related Issues
loadBundle(): LoadBundleTaskProgress stream snapshotsAndroid e2e failure (e.g. on feat(core): bump Firebase Android SDK to 35.0.2 #18812).Checklist
///).melos run analyze) does not report any problems on my PR.Breaking Change