fix(#297): reconcile FeedDB category membership on each fetch#308
Merged
Conversation
Synthetic category keys (e.g. NewsCategoryHighlights) were only ever unioned into FeedDB.categories on upsert, never removed. A post dropped by the server from a category (classic case: de-highlighted) kept showing under that category forever. getFeed now fetches all six categories in parallel and hands each category's result to a grouped save that reconciles membership within the pubDate window the fetch actually covers - adding the key to matching posts and removing it from posts inside that window the fetch no longer returned. Reconciliation is scoped per category so multi-category posts and deep pagination (categories paginate at different rates) are unaffected; .news stays add-only. Co-Authored-By: Claude <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.
Summary
FeedDB.categorieswas updated with a pure union on every fetch (existing.categories = Array(Set(existing.categories + feed.categories))), so a synthetic category key (e.g.NewsCategoryHighlights) could only ever be added, never removed — a post de-highlighted (or otherwise re-categorized) on the server kept showing under its old category forever.getFeed(page:)now fetches all six categories (5 special + news) in parallel and hands each category's result to a new grouped save that reconciles membership within thepubDatewindow that fetch actually returned: it adds the category key to matches as before, and removes it from any locally stored post inside that window which the fetch no longer includes..newsis excluded from removal since every post belongs to it.Test plan
xcodebuild build— BUILD SUCCEEDED (iPhone 17 Pro simulator unavailable on the build machine; substituted iPhone 17)xcodebuild test -testPlan MacMagazine— 523 checks passed, 0 failuresStorageServiceTestscases: add via grouped save, stale-key removal, sibling-category preserved, empty-result no-wipe, out-of-window safety,.newsexcluded from reconciliationswiftlint lint --strict— 0 violations on changed filesKnown limitation (documented in code review, not fixed here): if a highlight is rotated out and happens to be the single newest/oldest post in its batch, its
pubDatecan fall just outside the remaining window and survive one extra refresh cycle before clearing. Acceptable for the curated-highlights case.Co-Authored-By: Claude noreply@anthropic.com