~ knotless Search/
↑↓ move↵ open⇧↵ all results

grain.social/grain

photography-focused photo sharing platform

grain.social
1 collaborator
0
2

server: Backfill records an account's handle

Merged
Merged chadtmiller.com asked to merge into feature/rust from grain.social/grain:next/backfill-handle

What changes

Backfill records the handle of each account it reads: the one the account's DID document claims, once that handle resolves back to the DID. It does this after applying the repo, through the cached identity::handle.

Why

A new account showed handle.invalid in every view, indefinitely. The index set a handle only on a Jetstream identity event, and only for an account it already tracked. A new account's identity event arrives when the account is made, before it writes anything grain keeps, so the index drops it; after that the stream names a handle again only when it changes. Before this, an account first tracked from its own write (an app's indexRecords after signing in, or its first grain record on Jetstream) never got a handle.

Found testing the iOS app against next.grain.social. A throwaway account signed in, its profile was seeded and indexed, and backfill read it 7 seconds later, but its repo.handle stayed NULL. Eleven of next's 4,098 repos are in the same state.

How it was checked

repos_read_from_the_mirror_or_else_the_pds in crates/grain-serve/tests/backfill.rs now asserts that a backfilled account's handle is its own. The build and tests are left to CI.

Shortcomings

A handle that stops verifying is left as it was, not cleared. Accounts already backfilled with no handle get one only when they are read again. On next, grain-serve can be asked to resync them.

🤖 Generated with Claude Code

Approved

After applying a repo, backfill now looks up the account's handle through the cached identity::handle and stores it with set_handle. That fixes accounts whose first tracked write came after their identity event. The lookup returns a handle only if it resolves back to the DID, so an unverified claim isn't stored. set_handle updates an existing row and the backfill has just created that row, so the update is not a no-op. The test now asserts the backfilled account's handle. I didn't read the checks, and I found nothing that must change.

Two things you could look at later, neither of which blocks this:

  • identity::handle reads and rewrites the whole handles.json for each call. During a large backfill with several repos in flight, that costs more per account as the cache grows, and concurrent writers can lose each other's entries. A lost entry only means a repeat lookup.
  • A lookup that fails transiently is cached as None for the TTL. The account then keeps no handle until it is next read after that expires. This matches the shortcoming you already list.
Merged as 678efc7
Part of a stack of 2
  1. server: Backfill records an account's handle Landed as 678efc7
  2. main