Skip to content

Fix Mentions Watcher OOM and Tap Sync at_uri conflicts - #56

Open
hipstersmoothie wants to merge 1 commit into
mainfrom
sesh/check-prod-for-bugs
Open

hipstersmoothie wants to merge 1 commit into
mainfrom
sesh/check-prod-for-bugs

Conversation

@hipstersmoothie

Copy link
Copy Markdown
Collaborator

Prod issues

Mentions Watcher crash loop (OOM). The service dies roughly 220s after each start with JavaScript heap out of memory at 4 GB. Each Jetstream message (about 3.5k/sec while catching up) started a handler that wrote the cursor to the DB, with no backpressure. After 181s there were 621k messages but only 1,047 cursor saves, so pending handlers piled up. Each restart resumes further behind, so the service can't recover on its own.

  • Messages now go through a bounded queue and are processed one at a time. The socket pauses at 1000 queued messages and resumes at 100.
  • Cursor saves are throttled to once per second, plus a final save on shutdown.

Tap Sync retrying events forever. Events 5620 and 6419 fail on store_listings_at_uri_idx. upsertDirectoryListingFromTap matches rows by slug, but at_uri is also unique. When a record's slug doesn't match the row that already holds its at_uri, the upsert fails.

  • New resolveTapIngestSlug looks up the row by at_uri first. If the record's slug is free, the row takes it. If another listing already uses it, the row keeps its current slug and a warning is logged.

Testing

  • tsc --noEmit, oxlint and vitest (108 tests) pass. No test covers the new code paths.
  • Not yet run against live traffic.

Not fixed here

  • The OAuth Probe cron needs ATSTORE_IDENTIFIER and ATSTORE_APP_PASSWORD set in Railway. Page snapshot refresh fails for nearly every listing without them.

🤖 Generated with Claude Code

Jetstream consumer: process messages serially through a bounded queue,
pausing the socket above 1000 queued messages, and throttle cursor saves
to once per second. Previously every message spawned a concurrent DB
write, so replaying a saved cursor piled up handlers until the 4 GB heap
ran out, leaving the service in a crash loop.

Tap listing ingest: reconcile the record onto the row that owns its
at_uri before the slug-keyed upsert. A record whose slug didn't match its
existing row failed on store_listings_at_uri_idx and was retried forever.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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