Files
buzz/migrations
npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7andWill Pfleger 1ab6d760dc feat(relay): add per-user storage metrics from audit log
Add logical-attribution storage observability, grouped by
(community_id, actor_pubkey): a partial index on audit_log for
media_uploaded actions, per-user/per-community/fleet byte and object
gauges in the usage poller, and a real-time upload-bytes counter in
the media handler.

Dedupe by (community_id, actor_pubkey, object_id) in a subquery so
idempotent re-uploads of the same blob are charged once, not once per
audit row. Fail safe on malformed historical detail->>'size' values
(non-numeric, negative, out-of-range, or exceeding bigint bounds)
by validating with a digits-only regex and a lexicographic bound check
against i64::MAX, then attributing 0 bytes instead of aborting the
whole poller query. The bound check uses ltrim + length comparison
and works on all PostgreSQL versions without requiring pg_input_is_valid
(PG 16+).

Storage aggregation is overflow-safe end to end: the per-user SUM
accumulates in numeric (SUM(bigint) returns numeric for wider precision)
and is clamped into [0, i64::MAX] before the final cast to bigint,
so an extreme historical aggregate degrades to a saturated reading
instead of erroring the whole query. Rust-side community/fleet rollups
use saturating addition for the same reason — individually valid
per-user values can still overflow i64 in aggregate, and these are
observability gauges, not a billing ledger.

The concurrent index build (migration 0021) is retry-safe via two
layers: a startup repair guard drops any indisvalid=false leftover
from a failed prior build, and IF NOT EXISTS skips creation when a
valid unrecorded index already exists from a bookkeeping race. Both
the repair guard and migrator run under a session-scoped advisory
lock on a single pinned connection — pg_advisory_lock is session-scoped,
so lock/guards/migrator/unlock must all execute on the same PG session;
if unlock fails, dropping the connection closes the session and releases
the lock automatically. The repair probe is schema-scoped (joins
pg_namespace, restricts to current_schema()) so a same-named invalid
index in another schema cannot interfere.

Named *_objects rather than *_uploads to stay distinct from the new
real-time buzz_media_upload_bytes_total event counter added in the
media handler. Per-user cardinality (two custom series per
community,pubkey pair) is intentional; BUZZ_USAGE_METRICS_PER_COMMUNITY=off
remains the emergency kill switch.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
2026-07-16 15:08:59 -05:00
..