Files
buzz/crates/buzz-db
Luke Tornquist 745f7dac7c buzz-db: build the community deletion lock key in Rust (#9396)
## What

This is phase 1 of 2 for retiring the SQL function
`community_deletion_lock_key(uuid)`. Every relay caller now builds the
lock name in Rust, with
`buzz_db::deletion::community_deletion_lock_key(CommunityId) -> String`.
It then locks with the built-in `hashtextextended($1, 0)`, the same
pattern the other advisory locks here use (`channel_ttl_lock_key`,
`push_gate_lock_key`). The string is byte-for-byte the one the function
hashes (`'buzz-community-deletion:' || target::text`), so the lock is
identical. Old and new relays, and the fence functions still in the
database (`community_write_allowed`, `assert_community_write_allowed`),
keep excluding each other during a rolling deploy.

- **Production callers:** exclusive `lock_community_deletion`, shared
`lock_community_deletion_shared`, and the bulk shared lock in
`bind_nip_fi_issuers_to_active`. The bulk lock now binds a `text[]` of
keys, sorted by community id in Rust and locked `WITH ORDINALITY`. That
keeps the old `ORDER BY id` lock order, because `Uuid` and Postgres
`uuid` both compare bytewise.
- **Startup check:** `validate_serving_catalog_on` no longer requires
the function to exist, so the phase-2 drop can't make this release
refuse to serve or delete.
- **Tests and docs:** test lock holders use the helper.
`docs/database.md` gives repair scripts the inline expression, which
keeps working after the drop.
- The test-schema shims in `api/bridge.rs` and `handlers/ingest.rs`
stay. Test schemas still copy the fence functions that call the
function.

**Phase 2 (not here):** a migration and desired-state change drops the
function after this release is fully deployed and the fence functions
are gone (#8323). It also removes the two test shims.

## Tests

-
`deletion::postgres_tests::community_deletion_lock_key_matches_the_sql_function`
checks that `hashtextextended(rust_key, 0)` equals
`community_deletion_lock_key(uuid)` for the nil UUID, the max UUID and
64 random ones.
- `migration_schema_fence_objects_are_optional_for_serving_and_deletion`
already drops the universal fence objects by hand. It now also drops
`community_deletion_lock_key(UUID)`. With both present and absent, it
runs the startup and readiness checks, serving leases (shared lock),
`bind_nip_fi_issuers_to_active` (bulk shared lock) and
`lock_community_deletion` (exclusive lock).

Must-fail mutants, each run on Blox against its guarding test: a changed
key prefix, the shared, exclusive and bulk locks reverted to the SQL
function, and the startup check requiring the function again.

## What got simpler

No relay code path calls a database function to build this lock any
more. The key has one definition in Rust instead of one in SQL plus
about 20 SQL call sites. One fewer object stands between the schema and
declarative-only management (`docs/database.md` Rule 1).

## Verification

Blox, at `3020a44148d942f1502395640730cd0548a76400` (clean tree):

| Gate | Result |
|---|---|
| `cargo fmt --all --check` | pass |
| `cargo clippy -p buzz-db -p buzz-relay --all-targets -- -D warnings` |
pass |
| `cargo nextest run -p buzz-db --lib` | 214/214 |
| `scripts/postgres-test-run.sh -p buzz-db --lib` over
`deletion::postgres_tests`, `nip_fi_binding::postgres_tests` and the
reaction and channel-member lock tests | 101/101 |
| Must-fail mutants (prefix, shared, exclusive, bulk, startup check) |
5/5 killed |

CI runs the full Postgres lanes.

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


buzz-review-completed

Signed-off-by: Luke Tornquist <tornquist@squareup.com>
Co-authored-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 19:34:23 -05:00
..