-- AppView database schema 0006: handle-sync attempt tracking. -- -- Why -- The `handle_sync` worker SELECTs DIDs whose `posts.handle` is empty -- and tries to resolve them via the local PDS → PLC directory → -- `did:web:` resolver. Some DIDs are *unresolvable* (e.g. a `did:key:` -- user not hosted on the local PDS, or any `did:foo:` method that -- neither PLC nor Web understands). Without tracking these, every -- pass re-selects them and they dominate the 100-row batch — and -- since `did:key:` sorts lexicographically before `did:plc:` / -- `did:web:`, the worker would process the same 100 unresolvable -- `did:key:` rows forever and never reach any resolvable DID. -- -- With this column the worker marks each empty-handle row with the -- time of its last attempt. The SELECT filter excludes rows -- attempted within the last hour, so an unresolvable DID gets at -- most one attempt per hour and stops blocking forward progress. -- Rows whose `handle` later gets filled (by another code path) are -- naturally no longer in the candidate set. -- -- The column is per-post (not per-DID) because the candidate set is -- already per-post and the update is cheap (the empty-handle slice -- is small in steady state). ALTER TABLE posts ADD COLUMN IF NOT EXISTS handle_sync_attempted_at TIMESTAMPTZ;