a love letter to tangled (android, iOS, and a search API)
at main 132 lines 2.9 kB view raw view rendered
1--- 2title: Backfill & Resync Playbook 3updated: 2026-03-26 4--- 5 6Twisted has four recovery tools. Choose based on what broke. 7 8| Situation | Recovery path | 9| --- | --- | 10| Search results wrong but documents exist | `twister reindex` | 11| Documents missing because Tap never delivered them | `twister backfill` | 12| Documents exist but derived metadata is empty or stale | `twister enrich` | 13| Full database loss or migration to a fresh PostgreSQL instance | migrate, backfill, enrich, reindex | 14 15## Commands 16 17### `twister migrate` 18 19Applies the embedded schema migrations for the configured database. 20 21### `twister indexer` 22 23Runs the Tap consumer continuously. Persists its cursor in `sync_state`. 24 25### `twister backfill` 26 27Default source is `lightrail`. Use graph mode only for targeted fallback. 28 29```sh 30twister backfill --dry-run 31twister backfill 32twister backfill --source graph --seeds seeds.txt --max-hops 2 33``` 34 35Safe to rerun. Discovery is deduplicated and Tap registration is treated as 36idempotent. 37 38### `twister reindex` 39 40Re-upserts stored documents so PostgreSQL recomputes search state from the 41canonical `documents` rows. 42 43```sh 44twister reindex 45twister reindex --collection sh.tangled.repo 46twister reindex --did did:plc:abc123 47twister reindex --dry-run 48``` 49 50### `twister enrich` 51 52Fills missing `author_handle`, `repo_name`, and `web_url`. 53 54```sh 55twister enrich 56twister enrich --collection sh.tangled.repo.issue 57twister enrich --did did:plc:abc123 58twister enrich --dry-run 59``` 60 61## Scenario Playbooks 62 63### Search drift 64 65If search results look stale but the document rows are present: 66 67```sh 68twister reindex --dry-run 69twister reindex 70``` 71 72### Missing documents 73 74If a record is fetchable through the API but not searchable: 75 761. make sure Tap is tracking the DID 772. run targeted `backfill` if needed 783. let `indexer` drain 794. re-run `enrich` if metadata is still incomplete 80 81### Metadata gaps 82 83If `author_handle` or `repo_name` is empty: 84 85```sh 86twister enrich --dry-run 87twister enrich 88twister reindex 89``` 90 91### Full PostgreSQL rebuild 92 93Use this after restoring to a fresh database or moving to a new PostgreSQL 94instance. 95 961. run `twister migrate` 972. start `indexer` 983. run `twister backfill` 994. run `twister enrich` 1005. run `twister reindex` 1016. verify `/readyz`, `/health`, and smoke checks 102 103This is the default migration path from the old Turso-backed deployment too. 104 105### Tap cursor reset 106 107If the Tap cursor is ahead of the retained event window: 108 109```sql 110DELETE FROM sync_state WHERE consumer_name = 'indexer-tap-v1'; 111``` 112 113Then restart the `indexer`. 114 115## Status Checks 116 117With admin routes enabled: 118 119```sh 120curl -H "Authorization: Bearer $ADMIN_AUTH_TOKEN" \ 121 http://localhost:8080/admin/status 122``` 123 124Watch: 125 126- `tap.cursor` 127- `jetstream.cursor` 128- `documents` 129- `read_through.pending` 130- `read_through.processing` 131- `read_through.failed` 132- `read_through.dead_letter`