Reader: optimize ReaderPostTable.comparePosts#22810
Open
Conversation
Replaces N per-post getBlogPost() lookups with a single SELECT that fetches only the columns compared by ReaderPost.isSamePost, probed via an in-memory map during the comparison loop. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Collaborator
Generated by 🚫 Danger |
Fetch all non-text columns in the single batched query and reuse ReaderPost.isSamePost, removing the bespoke PostComparisonRow helper. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the StringBuilder loop with String.join + Collections.nCopies and drop the descriptive comment that duplicated the helper's name. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Callers that loaded an existing row without the text column (comparePosts) previously forced every post with a non-empty body to be reported as CHANGED because the stored text was always empty. The new overload lets those callers opt out of the text comparison, so UNCHANGED now fires on true no-op refreshes. Default remains true to preserve existing callers. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
|
|
Contributor
|
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## trunk #22810 +/- ##
==========================================
- Coverage 37.15% 37.15% -0.01%
==========================================
Files 2314 2314
Lines 124294 124310 +16
Branches 16882 16884 +2
==========================================
Hits 46185 46185
- Misses 74366 74382 +16
Partials 3743 3743 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
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.


Background
ReaderPostTable.comparePosts()is the gate thatReaderPostLocalSource.saveUpdatedPostsuses to decide what to do after the Reader fetches posts from the server. Its three-valued result drives three distinct behaviors in the caller:HAS_NEW/CHANGED— runs the full write path: gap detection, delete-and-reinsert forREQUEST_REFRESH,addOrUpdatePosts, bookmark pseudo-id fixups, gap-marker placement, and the UI change events those trigger.UNCHANGED— skips the write path entirely, avoiding re-inserting rows we already have and suppressing UI refreshes when nothing has actually changed.UNCHANGED+REQUEST_OLDER_THAN_GAP— a special case where a gap-fill request returned nothing new, signalling that the gap marker was bogus and should be removed.In short,
comparePostsanswers "does the server response differ from what's already stored?" — used to short-circuit writes and UI refreshes on no-op refreshes, and to distinguish "gap filled nothing" from a real update.Description
ReaderPostTable.comparePosts()previously ran onegetBlogPost()SQL query per incoming post, each materializing a fullReaderPostthat was thrown away after theisSamePostcheck. For a typical Reader refresh of ~20 posts that's 20 round-trips to SQLite.This change replaces those N queries with a single
SELECTkeyed by(blog_id, post_id)viaORclauses, loads the matching rows into an in-memory map (using the existingCOLUMN_NAMES_NO_TEXTprojection andgetPostFromCursor), and has the comparison loop probe the map.Fix to
isSamePosttext comparisonWhile optimizing this, we noticed
comparePostswas also effectively never returningUNCHANGEDfor full-text streams. It loads existing rows withexcludeTextColumn=true, butReaderPost.isSamePostunconditionally comparedpost.getText().equals(existingPost.getText()). Since the stored side was always empty, any incoming post with a non-empty body was reported asCHANGED— forcingsaveUpdatedPostsdown the full write path on every refresh.To fix this,
isSamePostnow has an overload with acompareTextflag soUNCHANGEDnow fires correctly - and more often - on true no-op refreshes and the caller can skip re-inserting rows and firing UI change events.Testing instructions
Reader refresh smoke test: