Skip to content

fix(#297): reconcile FeedDB category membership on each fetch#308

Merged
cassio-rossi merged 1 commit into
release/v5from
fix/feed-category-reconciliation
Jul 17, 2026
Merged

fix(#297): reconcile FeedDB category membership on each fetch#308
cassio-rossi merged 1 commit into
release/v5from
fix/feed-category-reconciliation

Conversation

@cassio-rossi

Copy link
Copy Markdown
Collaborator

Summary

  • FeedDB.categories was 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 the pubDate window 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.
  • Reconciliation is scoped per category and by date window (not page number), so multi-category posts and deep pagination (different categories paginate at different rates) are unaffected — a fetch only ever touches its own key, within its own window. .news is 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 failures
  • New StorageServiceTests cases: add via grouped save, stale-key removal, sibling-category preserved, empty-result no-wipe, out-of-window safety, .news excluded from reconciliation
  • swiftlint lint --strict — 0 violations on changed files

Known 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 pubDate can 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

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>
@cassio-rossi
cassio-rossi merged commit d716fdd into release/v5 Jul 17, 2026
1 of 2 checks passed
@cassio-rossi
cassio-rossi deleted the fix/feed-category-reconciliation branch July 17, 2026 17:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant