Files
buzz/crates
Bradley Axen bcc46fe835 perf(relay): cache ephemeral-path serving and restriction reads (#8208)
## Summary

Typing pulses and agent observer frames each ran two Postgres reads on
the WebSocket path in `handlers/event.rs`: whether the community still
serves writes (`is_serving_active`), and the sender's ban/timeout row
(`moderation_restriction_state`). Both now read through short-TTL moka
caches on `AppState`, following the membership cache's pattern.

- **Serving state, keyed per community, 10 s TTL.** Every typer in a
community shares one entry, so a pod does about one read per community
per 10 s.
- **Raw restriction row, keyed per (community, pubkey), 30 s TTL.** It
caches the row, not the verdict, so the verdict is still taken at "now"
and a cached timeout lifts the second it ends. One exception: `banned`
is computed when the row is read, so a ban with an expiry can outlast
that expiry by up to the TTL.
- **The TTL is the staleness bound.** On every pod, and for every way a
ban or timeout changes (signed commands, the admin API, report
resolution, an owner's moderation reaching their agents), the ephemeral
path sees the change within 30 s (10 s for archive/delete). As a best
effort, signed ban/unban/timeout/untimeout (9040–9043) also drop the
target's own entry on the pod that handles the command. Bans also keep
their existing cluster-wide socket disconnect, and archiving a community
disconnects all of its sockets.
- **Hit/miss counters** `buzz_serving_active_cache_{hits,misses}_total`
and `buzz_restriction_cache_{hits,misses}_total`, matching the
membership cache, so the saved reads can be confirmed in prod.
- **The durable fence stays uncached.** Persistent ingest, moderation
commands, auth, and NIP-43 leave (28936, ephemeral-range but ingested)
still read Postgres directly. The worst staleness case is a
just-timed-out user's typing dots or observer frames getting through on
another pod for up to 30 s. Real messages are never affected.

### Related issue
N/A. This is the ephemeral-path Postgres read cost raised in the
typing-indicator load discussion. Searched for existing PRs and found
none.

### Testing
- New Postgres tests:
- The ephemeral gate honours a cached ban and admits an expired cached
timeout.
  - The ephemeral fence honours a cached "fenced" community.
  - A cache miss fills both caches.
- At the `handle_event` seam, a stored write (kind 1) is accepted
despite a cached ban or a cached "fenced" state, and NIP-43 leave skips
the cached ban. Mutation-checked: switching either ingest check to its
cached variant, or dropping the 28936 carve-out, turns one red.
- Timeout and untimeout commands drop the cached row. Mutation-checked:
removing the invalidation turns it red.
- Live test on a local relay: 100 typing pulses made 0
restriction/serving reads; 10 real messages made 10 of each. A timeout
written straight to the DB refused messages at once and typing after ~30
s; an archive written straight to the DB fenced typing after ~10 s.
- `scripts/postgres-test-run.sh -p buzz-relay --lib --tests`: 384/384
passed (local PG14).
- `cargo nextest run -p buzz-relay --lib --tests`: 1470 passed. The 6
`api::media` failures are environmental: those tests seed through the
default `:5432` database, which locally has no `buzz` role.
- `cargo clippy -p buzz-relay --all-targets -D warnings` is clean.
- Review follow-up commit pushed with the full pre-push hook passing.
- Also adds a `sadscan:disable` marker to an existing dev-only test URL
in `ingest.rs`. The commit hook flagged it once the file was staged, and
the identical URLs elsewhere in that file already carry the marker.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: Bradley Axen <baxen@squareup.com>
Signed-off-by: Honey <8e307ae0076a4dab6b94b036ea3edc7e08f823a625269c1e6919e881a048b4d2@buzz.block.builderlab.xyz>
Signed-off-by: ART <ea39c1c8acf57180161ef4ba4ed68abf8589f5291956b909a5aa991fc66664ca@buzz.block.builderlab.xyz>
Co-authored-by: Honey <8e307ae0076a4dab6b94b036ea3edc7e08f823a625269c1e6919e881a048b4d2@buzz.block.builderlab.xyz>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: ART <ea39c1c8acf57180161ef4ba4ed68abf8589f5291956b909a5aa991fc66664ca@buzz.block.builderlab.xyz>
2026-10-09 14:53:27 -07:00
..