Repository navigation
Fix builder disposal and keep collection views additive - #44
Merged
danReynolds merged 5 commits intoSep 30, 2026
Merged
Conversation
`observe()` on an observed document or query returns the same observer, so a builder given one was disposing the caller's observer when it was removed or switched sources, closing it for every other listener. The builders now dispose an observer only if they created it. Removal is the case this branch introduced; disposing on a source switch predates it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The public `CollectionView<S>(collection)` constructor accepted any type, so `CollectionView<String>(animals)` compiled and silently matched nothing. `view<S>()` requires S to extend the collection's type at compile time, and is now the only way to create a view. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A collection view compared by identity, so a view created inline in `build` made `QueryStreamBuilder` observe and scan the collection again on every rebuild. Views of the same type over the same collection select the same documents, so they now compare equal, as collections compare by path and document views by path and type. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Accepting views in DocumentStreamBuilder and QueryStreamBuilder changed their callbacks to read-only snapshots for every caller, so existing builders could no longer write through `snap.doc`, and `Queryable.toQuery()` changed type. Those builders keep their signatures from main. DocumentViewStreamBuilder and QueryViewStreamBuilder build from views, and also accept ordinary documents and queries through the read interfaces they implement. With this, the view layer only adds API: no existing signature changes, and the example app is back to writing through `userSnap.doc`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ator A view's sort ran in the underlying query, with a comparator that looked up both snapshots' projections on every comparison. The view now keeps its sort and applies it to its projected snapshots, so each snapshot's projection is looked up once per read. In interleaved local runs over 2,000 matching documents, `get()`, reads after a write, and stream emissions were faster in every round, by roughly 2-2.7x at the median. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Follow-ups to #41 from its review and the comparison with #43, keeping views read-only. There is one commit per change so any of them can be dropped; each passes
flutter analyzeand the core suite on its own.Dispose only the observers stream builders create (
2bae11c).observe()on an observed document or query returns the same observer. A builder given one disposed the caller's observer when the builder was removed, closing it for every other listener, so a second builder sharing it silently stopped updating. Builders now dispose only observers they created. Disposing on a source switch had the same problem and predates Add live read-only subtype collection views #41; that is fixed too.test/core/stream_builder_test.dartcovers both, and its caller-owned cases fail on Add live read-only subtype collection views #41.Construct collection views only through
view()(6d007f8).CollectionView<String>(animals)compiled and silently matched nothing. The constructor is now private, soview<S>(), which boundsSat compile time, is the only way to create a view.Compare collection views by collection and subtype (
0fb3f70). Views compared by identity, so a view created inline inbuildmadeQueryStreamBuilderobserve and rescan the collection on every rebuild. Views of the same type over the same collection now compare equal, as collections compare by path and document views by path and type.Give views their own stream builders (
a033225). Add live read-only subtype collection views #41 changed theDocumentStreamBuilderandQueryStreamBuildercallbacks to read-only snapshots for every caller, so existing builders could no longer write throughsnap.doc, andQueryable.toQuery()changed type. Those builders keep their signatures from main.DocumentViewStreamBuilderandQueryViewStreamBuilderbuild from views, and also accept ordinary documents and queries through the read interfaces they implement. With this, the view layer only adds API: the example app is back to its main version, and 6.0.0 code that edits throughsnap.docin a builder compiles unchanged. This is the one design change here; drop the commit to keep the unified builders.Sort a view's projected snapshots instead of projecting in the comparator (
2440e9d). The view keeps its sort and applies it to its projected snapshots, so comparisons no longer look up projections. In interleaved local runs over 2,000 matching documents,get(), reads after a write, and stream emissions were faster in every round, by roughly 2–2.7× at the median. The machine was under heavy load, so the absolute timings are not meaningful.Validation
CI only runs for pull requests into main, so these ran locally at the branch head:
flutter analyzereports no issues for the package or the example.flutter analyzeand the core suite on its own.🤖 Generated with Claude Code