Skip to content

fix(follows): reconcile local follow cache with newest relay kind-3#385

Open
dmnyc wants to merge 1 commit into
mainfrom
fix/follow-list-stale-cache
Open

fix(follows): reconcile local follow cache with newest relay kind-3#385
dmnyc wants to merge 1 commit into
mainfrom
fix/follow-list-stale-cache

Conversation

@dmnyc

@dmnyc dmnyc commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes the bug where editing your follow list inside Wisp could restore an old, larger list — undoing a change made in another client. Closes #384.

The follow-edit source of truth (FollowsCacheUserDefaults["follow_pubkeys_<pubkey>"]) was only ever written at onboarding and on in-app follow/unfollow. Nothing reconciled it against a newer kind-3 arriving from relays, so a follow list edited elsewhere (e.g. trimmed from ~1700 to ~1100 via an external tool) was never reflected locally — and the next in-app follow/unfollow rebuilt off the stale set and republished it, clobbering the out-of-band change.

What changed

  • FollowsCache now tracks the created_at of the kind-3 that produced the stored set (new follow_pubkeys_ts_<pubkey> key) and exposes reconcile(pubkey:follows:createdAt:), which adopts a relay copy only when it's strictly newer than what's held locally. This replaces a frozen snapshot while refusing a stale copy that would undo a fresher local edit.
  • Reconcile runs on launch in FeedViewModel.loadUserProfile() (which already fetches the user's own kind-0) and when viewing your own profile in ProfileViewModel.loadContacts().
  • FollowSender (follow/unfollow) and onboarding now stamp the cache with the event's timestamp so a later relay fetch of the same event doesn't re-trigger.
  • NostrKey clears the new timestamp key on account deletion.

Note: this prevents future clobbering; it can't recover a list the old code already overwrote on relays.

Test plan

  • Builds clean; installed on sim
  • Trim follow list externally (e.g. 1700 → 1100), relaunch Wisp — bio shows ~1100
  • Follow/unfollow one account in Wisp — count stays ~1100 (±1 for self), does not jump back to 1700
  • Normal in-app follow/unfollow still persists across relaunch
  • Fresh onboarding still seeds the follow list correctly

The follow-edit source of truth (FollowsCache) was only ever written at
onboarding and on in-app follow/unfollow, and never reconciled against a
newer kind-3 arriving from relays. A follow list edited in another client
(e.g. trimmed via an external tool) was therefore never reflected locally,
and the next in-app follow/unfollow rebuilt off the stale set and
republished it, clobbering the out-of-band change.

Track the created_at of the kind-3 that produced the stored set and add
FollowsCache.reconcile, which adopts a relay copy only when it is strictly
newer than what is held locally — replacing a frozen snapshot while
refusing a stale copy that would undo a fresher local edit. Reconcile on
launch (FeedViewModel.loadUserProfile, which already fetches the user's own
kind-0) and when viewing one's own profile (ProfileViewModel.loadContacts).
Follow/unfollow and onboarding now stamp the cache with the event timestamp.
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.

fix(follows): in-app follow/unfollow republishes a stale follow list, clobbering external edits

1 participant