feat(db): configurable writer session timeouts (lock, idle-txn, statement) - #6229
Conversation
wpfleger96
left a comment
There was a problem hiding this comment.
🤖 Combined review — two independent agent passes (Paul and Thufir) that converged on the migration finding, deduped into the inline comments below. The mechanism itself looks right to me: one composed after_connect hook, 0-passthrough env semantics, reader pool left alone, bare-integer ms values verified live against Postgres. Nobody's asking for a different design — two blocking items and two nits.
wpfleger96
left a comment
There was a problem hiding this comment.
🤖 Re-reviewed the exact current head. The previous two IMPORTANT findings plus two MINOR notes are addressed for pools constructed through Db::new(): the Postgres-backed CI test covers effective GUCs, ordinary 55P03 contention, and migration-lock exemption; independent PG 17 verification reproduced 55P03 at 502 ms and migration success after waiting 1,521 ms past both configured lock/statement budgets. Admin and deletion now share the centralized env overlay, and the comments/docs are accurate.
IMPORTANT / Correctness — crates/buzz-relay/src/main.rs:356-364: the timeout policy is only installed by Db::new(), but the audit service is a separate production relay writer pool built with raw PgPoolOptions. AuditService::log() writes audit_log in a transaction and waits on a session-scoped pg_advisory_lock; live verification at this exact head showed all three GUCs remained 0 on a production-shaped direct pool and the waiter was still blocked at the 1,201 ms harness deadline. Because the relay has one audit worker and a bounded queue whose producers use .send().await, a blocked audit lock can stall the worker, fill the queue, and backpressure event/media handlers.
Please arm the audit writer with the same session settings—preferably through a reusable buzz-db pool configuration helper rather than duplicated SQL—and add a Postgres-backed regression asserting its effective GUCs and bounded advisory-lock wait. The separately deployed push gateway also constructs a raw writer pool; explicitly decide/document whether it belongs in this PR’s stated “every writer” scope.
There was a problem hiding this comment.
🤖 Combined review of exact head 9bbcade722b7a680e764feabcdb5acf738347ed3 — three independent agent passes (two source reviews plus a clean-relay live E2E run), deduped here. Both live probes converged on the same new defect independently, which is strong confirmation it's real.
Previous round's findings — all addressed:
- The audit pool now goes through the renamed public
Db::connect_writer_poolviaconnect_audit_pool()(crates/buzz-relay/src/main.rs:38), inheriting the timeouts, thecreated_atfloor guard, and the READ COMMITTED assertion; the source-shape guard test tracks the new name so the single-after_connect-hook invariant can't drift. - Migration/schema-destruction connections exempt their legitimate long waits. Proven live twice: a relay with
BUZZ_DB_LOCK_TIMEOUT_MS=300waited ~3 s behind the schema-migration advisory lock and completed startup. - Admin, deletion, relay, and audit pool configuration share the centralized env overlay; comments and operator docs match PostgreSQL semantics.
- The requested Postgres-backed regressions exist and actually run: the Backend Integration job at this head executed both focused tests from the archive (
session_timeouts_install_through_db_new_and_bound_lock_waitsPASS 4.96 s,audit_writer_pool_installs_timeouts_and_bounds_advisory_lock_waitsPASS 0.52 s). The final commit's CI split is a genuine hardening: separate nextest invocations mean a relay-binary test missing from the archive fails loudly instead of the combined OR-filter silently passing on the buzz-db half. - Push-gateway scope decision is documented consistently in
.env.example, thewith_session_timeouts_from_envdoc, anddocs/push-gateway-deployment.md.
Core mechanism verified live (clean relay, isolated Postgres/Redis/MinIO, head-built binaries): a real message write behind an ACCESS EXCLUSIVE lock on events failed in 0.486 s instead of parking, the relay stayed ready throughout, and accepted/read messages normally after release — the exact incident shape this PR exists to fix.
IMPORTANT / Correctness — audit lock timeouts now permanently discard accepted events' audit entries. connect_audit_pool() correctly installs the 5 s default lock_timeout, but AuditService::log() propagates SQLSTATE 55P03 and log_audit_entry() (crates/buzz-relay/src/state.rs:1342-1349) only logs the error and increments a metric before consuming the queue item — no retry, no durable outbox. Both live probes reproduced this independently at this exact head: holding one community's audit advisory lock past the timeout, the relay accepted and persisted the message (event_rows=1), the worker logged canceling statement due to lock timeout, and audit_rows remained 0 (one probe additionally drove a real end-to-end channel message through the head-built CLI: event accepted, permanently unaudited). Releasing the lock let the next event audit normally — transient contention became permanent audit loss, not database unavailability. Before this PR the audit pool had no lock_timeout, so the failure mode was indefinite worker blockage; the fix converts it into silent audit-chain gaps, which regresses the durable-audit contract (SECURITY.md:67-74, VISION_MODERATION.md) and the queue's stated no-drop intent.
Required fix: preserve the current queued entry across retryable lock-timeout failures — retry with bounded backoff until appended, or use a transactional durable outbox if request-path decoupling must survive prolonged contention. Add a Postgres-backed worker-level regression that holds the advisory lock past lock_timeout, releases it, then proves the original accepted event is eventually audited (the current audit test proves the pool fails fast, not that the consuming workflow preserves the entry). A fix also needs a live contention re-run proving the accepted event ends up with exactly one audit row.
New-regression sweep — nothing else found: all remaining raw PgPoolOptions writers at this head are accounted for (search pool is SELECT-only FTS, mesh-boot/channel-snapshot pools are test-only, push gateway documented out of scope), and the merge from main introduced no semantic interaction with the PR's files.
Quality: Minimalism 9/10; Elegance 9/10; Correctness 7/10 pending durable recovery from the newly expected lock-timeout error.
## Why Database pressure currently collapses several distinct delays into one symptom. This adds the evidence layer needed to distinguish pool acquisition wait, logical database operation time, advisory-lock wait, and selected transaction duration before changing timeout or retry policy. This is the phase 2 Lane A observability bundle for [#26](TheSentinel454#26), [#28](TheSentinel454#28), and [#33](TheSentinel454#33). It is stacked on #6668. ## What - Record explicit reader/writer checkout wait and acquisition outcomes with `buzz_db_pool_acquire_wait_seconds` and `buzz_db_pool_acquisitions_total`. - Extend the compile-time `#[datastore_span(name = "...")]` seam with `buzz_db_operation_duration_seconds`, so operation labels remain static source literals instead of request data. - Route correctness-critical replacement, membership, push-gate, deletion, and migration/schema-safety advisory locks through one observer without changing their SQL, order, scope, or blocking behavior. - Measure six internally owned transaction lifetimes with `buzz_db_transaction_duration_seconds`, starting after `BEGIN` succeeds and ending after explicit commit/rollback or scope exit. - Emit root slow-operation warnings at 500 ms, logging the first slow completion and then 1/100 per call site with only `operation`, `outcome`, and `elapsed_ms`. - Document names, units, fixed label vocabularies, measurement boundaries, and blind spots in this PR description. Fixed labels are deliberately small: - `pool_role`: `writer`, `reader` - `lock_type`: `replacement`, `membership`, `push_gate`, `deletion`, `migration_schema_safety` - `outcome`: `success`, `error`, `timeout` where SQLx/PostgreSQL can distinguish it accurately - `operation`: compile-time datastore names plus the six closed transaction operation names documented in the runbook No metric or slow warning contains community IDs, event IDs, event kinds, coordinates, d-tags, SQL/query text, query IDs, returned errors, or event content. ## Coverage boundaries - Operation duration is the complete annotated logical function body, not pure SQL execution; it may include implicit checkout, lock wait, nested operations, and application work. Cancelled futures do not reach its completion hook. - Pool timing covers explicit helper checkouts, including proved-reader routing and selected writer-owned transactions. Implicit SQLx checkout through `&PgPool` remains folded into operation duration. - Lock timing covers application-side blocking locks in the five named families. Trigger/stored-procedure locks, channel-TTL locking, the usage try-lock, and the audit service session lock remain outside this slice. - Transaction timing covers only the six wholly owned boundaries documented in the runbook. It excludes pool wait, `BEGIN`, asynchronous rollback cleanup after an early return, and caller-owned `Db::begin_transaction` lifetime. ## Relationship to #6229 #6229 is the incident-driven timeout precursor. This PR does not add or change `statement_timeout`, `lock_timeout`, `idle_in_transaction_session_timeout`, retries, audit durability, or client-visible conflicts. It provides the missing distributions needed to evaluate those policies later and intentionally leaves #6229's open audit retry/durability finding untouched. The branches overlap in `crates/buzz-db/src/lib.rs` and `crates/buzz-db/src/migration.rs`, so a later rebase may need textual conflict resolution, but the behavior is complementary rather than duplicated. ## Risk assessment Moderate-low. The primary risk is instrumentation overhead and added static series. Cardinality is source-bounded, slow logs are sampled/redacted root events, and the lock/transaction changes wrap existing awaits without changing policy or ordering. ## Verification Author workstation: `buzz-tornquist-db-pressure-observability` (`2010927`), exact head `d7cf833e26c528adfcde3917ded80daf6f4ddac9`, parent `6f50e6b2b2a996349149af61d35bdd6a355f77fd`. - `cargo fmt --all --check` — passed - `cargo clippy -p buzz-datastore-tracing -p buzz-db -p buzz-audit -p buzz-search -p buzz-relay --all-targets -- -D warnings` — passed - `cargo test -p buzz-datastore-tracing --quiet` — 4 passed - `cargo test -p buzz-db --quiet` — 109 passed, 200 ignored - `cargo test -p buzz-audit -p buzz-search --quiet` — 16 passed, 25 ignored - `cargo test -p buzz-relay --lib --quiet -- --test-threads=1` — 906 passed, 48 ignored - Native PostgreSQL focused tests for pool success/timeout/error, lock success/contention/timeout/error, replacement, membership serialization, push ordering, deletion fencing, migration/schema exclusion, and reader fallback — 8 passed The default-parallel relay run passed once; subsequent runs exposed the existing load-sensitive `api::mesh_demo::tests::demo_join_forwarded_arm_round_trips_echo` 504 at the end of the suite. That test passes in isolation and the full relay suite passes serially. Independent exact-head review workstation: `buzz-tornquist-db-pressure-observability-review` (`2013067`). Formatting, the same all-target clippy command, datastore instrumentation tests, DB unit tests, source privacy guards, and diff/non-goal audits passed; no review findings. Generated with Codex --------- Signed-off-by: tornquist <tornquist@squareup.com>
9bbcade to
2305bb4
Compare
🔐 Codex Security Review
|
Signed-off-by: Luke Tornquist <tornquist@squareup.com>
Signed-off-by: Luke Tornquist <tornquist@squareup.com>
2305bb4 to
896c3fe
Compare
|
🤖 Codex update: PR #6229 is rebased onto current This directly reruns the live contention case requested in the latest changes-requested review:
Also passed on the rebased head:
@wpfleger96, please re-review the current head when you have a chance. |
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
wpfleger96
left a comment
There was a problem hiding this comment.
I re-reviewed the exact current head. The writer policy is centralized in the single composed after_connect hook; relay, admin, deletion, and audit pools receive the shared env overlay; migration/schema-destruction connections deliberately clear lock and statement limits while retaining idle-transaction protection; and the read/search/push-gateway exclusions are explicit and consistent with their ownership.
The three PostgreSQL-backed regressions ran and passed in current-head CI: effective writer GUCs plus bounded relation-lock wait and migration exemption, audit-pool advisory-lock timeout, and preservation/retry of the original audit entry exactly once. The retry loop is bounded by the existing five-second audit shutdown drain at process exit, so persistent contention does not make shutdown unbounded.
No blocking findings.
|
Codex Review: Didn't find any major issues. 👍 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
wpfleger96
left a comment
There was a problem hiding this comment.
🤖 Post-merge combined review at 896c3fe9edd3098be067c1cd1d347cf7c44e45db. The central writer-timeout mechanism, migration exemption, and 55P03 retry path are sound, but independent source and live verification found one confirmed audit-loss defect plus one cross-tenant liveness risk that need a follow-up fix:
-
IMPORTANT — a supported timeout ordering permanently drops accepted events' audit entries. The audit pool inherits
BUZZ_DB_STATEMENT_TIMEOUT_MS, but the worker retries only SQLSTATE55P03. WithBUZZ_DB_LOCK_TIMEOUT_MS=1000andBUZZ_DB_STATEMENT_TIMEOUT_MS=250, a live relay accepted and persisted a real event while its community audit advisory lock was held. The advisory-lock statement failed first with57014(statement_timeout), the worker treated it as terminal, and the audit row remained absent after the lock was released. Reject/clamp configurations where statement timeout preempts lock timeout, or preserve and retry the entry for this cancellation. Add a production-path regression with nonzero statement timeout proving eventual exactly-once audit persistence. -
IMPORTANT — one persistently contended community can monopolize the global audit worker.
55P03retries have capped delay but no retry deadline or cancellation check. The single 1,000-entry FIFO is shared across communities, and event/media producers await capacity. A permanent holder can therefore pin the worker, fill the queue, and backpressure unrelated communities; shutdown only times out externally after five seconds and abandons the worker. Bound or cancel per-entry retries while preserving the audit record durably, and add saturation/cross-community progress plus teardown coverage.
The existing suite causally exercises only lock_timeout; it reads the idle-transaction and statement GUCs but does not prove idle-session termination/pool replacement or the nonzero statement-timeout recovery path. Also update the stale comment in crates/buzz-relay/src/handlers/event.rs that says worker DB failures are not retried: 55P03 is retried while other errors are currently terminal.
…ment) (block#6229) (#7) ## Why A wedged relay boot pod holding a relation lock can park every other writer in the fleet behind it: DB load pins at pool capacity in `Lock:relation` waits while CPU stays flat, and nothing server-side releases the lock until the holder dies. We hit exactly this in production — ~1,400 sessions queued behind one crash-looping pod's boot transaction for ~20 minutes until kubelet killed the container. ## What Applies session-level Postgres timeouts to every **writer** connection inside the existing single `after_connect` hook in `buzz-db`, all env-tunable through the same `Config::from_env → DbConfig` path as the existing pool-size knobs: | Env var | GUC | Default | Effect | |---|---|---|---| | `BUZZ_DB_LOCK_TIMEOUT_MS` | `lock_timeout` | 5000 | statements waiting on any lock fail fast instead of parking behind a wedged holder | | `BUZZ_DB_IDLE_TXN_TIMEOUT_MS` | `idle_in_transaction_session_timeout` | 60000 | reaps wedged clients idling inside an open transaction while holding locks | | `BUZZ_DB_STATEMENT_TIMEOUT_MS` | `statement_timeout` | 0 (off) | opt-in runaway-statement cap; off by default because startup migrations/backfills legitimately run long statements | `0` disables a timeout (Postgres semantics) and deliberately passes through the env parsing — unlike the pool-size knobs where `0` falls back to the default. The reader pool is untouched: replica sessions never take contended locks and already fail acquire in 150 ms. Deployers tune these via plain env vars (`.env`, or `relay.extraEnv` in the Helm chart) — no code changes needed. ## Behavior change to note With the 5 s default `lock_timeout`, a boot-time migration or backfill that waits >5 s on a lock now errors (surfacing in logs / crash-looping the pod) instead of stalling silently. That is the intended visible-failure-over-fleet-stall tradeoff; deployers with slow contended migrations can set `BUZZ_DB_LOCK_TIMEOUT_MS=0`. ## Testing - `cargo test -p buzz-db -p buzz-relay` — buzz-db green; buzz-relay has 9 failures that also fail on clean `main` in this environment (api::admin/api::media/mesh_demo — unrelated, pre-existing). - New config test covers override / `0`-passthrough / invalid-fallback for all three env vars. - Extended the existing `writer_pool_safety_hook_is_single_and_composed` source-shape test so the timeouts can't drift out of the single `after_connect` hook (SQLx replaces hooks — a second hook would silently disarm the floor guard). - `cargo fmt --check` and `cargo clippy --all-targets` clean for the touched crates. Closest existing PR/issue: none found. --- **Update Aug 28, 17:06 EDT:** Rebased onto `main` at `a3730784fc` and addressed the latest correctness review. - Ported the timeout policy onto the refactored `buzz-db::runtime` pool constructor and kept the shared env overlay for relay, admin, deletion, and audit writers. - Migration/schema-destruction connections now disable `lock_timeout` and `statement_timeout` for their intentional long wait/DDL path. This supersedes the earlier “Behavior change to note”: contended boot migrations wait for the current migration owner rather than crash-looping after five seconds. - The audit worker now preserves and retries the same entry on PostgreSQL `55P03` lock timeouts, using exponential backoff capped at one second. Other database errors retain the existing terminal error behavior, and retries emit `buzz_audit_log_lock_retries_total`. - Added CI-backed PostgreSQL regressions for writer GUC installation/migration exemption, audit-pool lock timeouts, and worker recovery. The worker regression holds the real audit advisory lock past `lock_timeout`, observes a retry, releases the lock, and proves the original entry is appended exactly once. Current verification supersedes the earlier testing notes: workspace Rust clippy passed with warnings denied; all nine infrastructure-free backend unit-test lanes passed; all three focused PostgreSQL regressions passed against PostgreSQL 17; formatting, diff checks, file-size guards, and desktop frontend checks passed. The Linux Blox workstation could not run the unrelated Tauri native lane because `glib-2.0` is absent, so that platform check is left to PR CI. --- **Update Aug 31, 11:09 EDT:** Rebased onto current `main` at `c3132c3ee9` and reran the requested audit-lock contention scenario on Blox at head `896c3fe9ed`. - `git range-diff` reports both PR commits unchanged by the rebase; the branch remains two commits and the worktree is clean. - `cargo fmt --all -- --check` and clippy with warnings denied passed for `buzz-db`, `buzz-relay`, `buzz-admin`, and `buzz-deletion`. - All three focused PostgreSQL 17 regressions passed: writer session timeout/migration exemption, audit writer timeout bounds, and audit worker recovery of the original entry exactly once. - Live protocol verification used a head-built relay and CLI, native PostgreSQL 17/Redis, `BUZZ_DB_LOCK_TIMEOUT_MS=300`, and an eight-second hold on the community audit advisory lock. The real message was accepted and persisted once while the lock was held; its audit-row count remained zero during contention while retries accumulated. After release, exactly one `event_created` audit row appeared and remained exactly one after an additional two-second duplicate check. The run recorded nine lock-timeout retries, zero audit failures, and event ID `7f8c4ffae28e78555fcf2d56396d6e6c01b3712e5411288dc79e9a54af9d9444`. Generated with Codex --------- Signed-off-by: Luke Tornquist <tornquist@squareup.com> Co-authored-by: Luke Tornquist <tornquist@squareup.com>
…h-coordinator * origin/main: fix: retrieving cold memories; add regression task (#6950) Enforce NIP-OA authorization time bounds (#7004) feat(db): configurable writer session timeouts (lock, idle-txn, statement) (#6229) feat(desktop): use segmented controls for channel creation (#6845) feat(buzz-agent): surface stop reason and silent-turn WARN in telemetry (#7038) Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
…h-coordinator * origin/main: fix: retrieving cold memories; add regression task (#6950) Enforce NIP-OA authorization time bounds (#7004) feat(db): configurable writer session timeouts (lock, idle-txn, statement) (#6229) feat(desktop): use segmented controls for channel creation (#6845) feat(buzz-agent): surface stop reason and silent-turn WARN in telemetry (#7038) Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz> Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
…h-coordinator * origin/main: fix: retrieving cold memories; add regression task (#6950) Enforce NIP-OA authorization time bounds (#7004) feat(db): configurable writer session timeouts (lock, idle-txn, statement) (#6229) feat(desktop): use segmented controls for channel creation (#6845) feat(buzz-agent): surface stop reason and silent-turn WARN in telemetry (#7038) Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz> Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
…on-runtime * origin/main: fix: retrieving cold memories; add regression task (#6950) Enforce NIP-OA authorization time bounds (#7004) feat(db): configurable writer session timeouts (lock, idle-txn, statement) (#6229) feat(desktop): use segmented controls for channel creation (#6845) feat(buzz-agent): surface stop reason and silent-turn WARN in telemetry (#7038) fix(desktop): surface channel history load failures (#7013) fix(composer): polish automatic mentions (#6956) Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
* origin/main: feat: render agent avatars as squircles (#7106) fix(ci): salvage Codex review output on PTY-shutdown hang (#7042) fix: retrieving cold memories; add regression task (#6950) Enforce NIP-OA authorization time bounds (#7004) feat(db): configurable writer session timeouts (lock, idle-txn, statement) (#6229) feat(desktop): use segmented controls for channel creation (#6845) feat(buzz-agent): surface stop reason and silent-turn WARN in telemetry (#7038) fix(desktop): surface channel history load failures (#7013) fix(composer): polish automatic mentions (#6956) Signed-off-by: Hayt <9e1c23a3fd83f61da34420e4e88ff1b16e45cafcc0cd9019eb07d4ecfa8ca9b0@buzz.block.builderlab.xyz>
…age-rw * origin/main: feat: render agent avatars as squircles (#7106) fix(ci): salvage Codex review output on PTY-shutdown hang (#7042) fix: retrieving cold memories; add regression task (#6950) Enforce NIP-OA authorization time bounds (#7004) feat(db): configurable writer session timeouts (lock, idle-txn, statement) (#6229) feat(desktop): use segmented controls for channel creation (#6845) feat(buzz-agent): surface stop reason and silent-turn WARN in telemetry (#7038) fix(desktop): surface channel history load failures (#7013) fix(composer): polish automatic mentions (#6956) Signed-off-by: Joel Robotham <jrobotham@squareup.com>
…-history * origin/main: feat: render agent avatars as squircles (#7106) fix(ci): salvage Codex review output on PTY-shutdown hang (#7042) fix: retrieving cold memories; add regression task (#6950) Enforce NIP-OA authorization time bounds (#7004) feat(db): configurable writer session timeouts (lock, idle-txn, statement) (#6229) feat(desktop): use segmented controls for channel creation (#6845) feat(buzz-agent): surface stop reason and silent-turn WARN in telemetry (#7038) Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
* origin/main: (32 commits) fix(acp): wake agents from workflow messages (#6953) feat: render agent avatars as squircles (#7106) fix(ci): salvage Codex review output on PTY-shutdown hang (#7042) fix: retrieving cold memories; add regression task (#6950) Enforce NIP-OA authorization time bounds (#7004) feat(db): configurable writer session timeouts (lock, idle-txn, statement) (#6229) feat(desktop): use segmented controls for channel creation (#6845) feat(buzz-agent): surface stop reason and silent-turn WARN in telemetry (#7038) fix(desktop): surface channel history load failures (#7013) fix(composer): polish automatic mentions (#6956) fix(desktop): resolve bundled sidecar on cheap path and bound login-shell spawns (#6904) perf(mobile): reduce cold startup and channel rendering delays (#6996) feat(mobile): push notifications MVP (#6269) refactor(db): extract domain stores from database runtime (#6987) feat(desktop): add team sharing to community catalog (#3995) Refresh mobile utility surfaces and theme picker (#6944) fix(desktop): complete project empty and context states (#6980) Fix mobile jump-to-latest flicker (#6807) refactor(relay): NIP-98 admin auth with Operator/Moderator roles and NIP-11 discovery (#3777) refactor(db): split channel membership store (#6782) ... Signed-off-by: Carl <1f967df5817845a2a5d74c82ac3098dea0bb7342665352af6643c5ac5c878dd3@buzz.block.builderlab.xyz> # Conflicts: # desktop/src/features/channels/ui/ChannelPane.tsx
…n-surface * origin/main: fix(desktop): back split thread headers (#7137) add public descriptions to agent personas (#7126) feat(desktop): add protected-build Bestie experiment (#6902) fix(relay): reject a frame on its own acknowledgement channel (#6961) fix(acp): wake agents from workflow messages (#6953) feat: render agent avatars as squircles (#7106) fix(ci): salvage Codex review output on PTY-shutdown hang (#7042) fix: retrieving cold memories; add regression task (#6950) Enforce NIP-OA authorization time bounds (#7004) feat(db): configurable writer session timeouts (lock, idle-txn, statement) (#6229) feat(desktop): use segmented controls for channel creation (#6845) feat(buzz-agent): surface stop reason and silent-turn WARN in telemetry (#7038) fix(desktop): surface channel history load failures (#7013) fix(composer): polish automatic mentions (#6956) fix(desktop): resolve bundled sidecar on cheap path and bound login-shell spawns (#6904) perf(mobile): reduce cold startup and channel rendering delays (#6996) feat(mobile): push notifications MVP (#6269) Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
…enericize * origin/main: fix(desktop): back split thread headers (#7137) add public descriptions to agent personas (#7126) feat(desktop): add protected-build Bestie experiment (#6902) fix(relay): reject a frame on its own acknowledgement channel (#6961) fix(acp): wake agents from workflow messages (#6953) feat: render agent avatars as squircles (#7106) fix(ci): salvage Codex review output on PTY-shutdown hang (#7042) fix: retrieving cold memories; add regression task (#6950) Enforce NIP-OA authorization time bounds (#7004) feat(db): configurable writer session timeouts (lock, idle-txn, statement) (#6229) feat(desktop): use segmented controls for channel creation (#6845) feat(buzz-agent): surface stop reason and silent-turn WARN in telemetry (#7038) fix(desktop): surface channel history load failures (#7013) fix(composer): polish automatic mentions (#6956) Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
…n-surface * origin/main: docs: add review-proven failure-path & async-state rules to AGENTS.md (#7061) fix(desktop): back split thread headers (#7137) add public descriptions to agent personas (#7126) feat(desktop): add protected-build Bestie experiment (#6902) fix(relay): reject a frame on its own acknowledgement channel (#6961) fix(acp): wake agents from workflow messages (#6953) feat: render agent avatars as squircles (#7106) fix(ci): salvage Codex review output on PTY-shutdown hang (#7042) fix: retrieving cold memories; add regression task (#6950) Enforce NIP-OA authorization time bounds (#7004) feat(db): configurable writer session timeouts (lock, idle-txn, statement) (#6229) feat(desktop): use segmented controls for channel creation (#6845) feat(buzz-agent): surface stop reason and silent-turn WARN in telemetry (#7038) fix(desktop): surface channel history load failures (#7013) fix(composer): polish automatic mentions (#6956) fix(desktop): resolve bundled sidecar on cheap path and bound login-shell spawns (#6904) perf(mobile): reduce cold startup and channel rendering delays (#6996) feat(mobile): push notifications MVP (#6269) Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
* origin/main: feat(desktop): add thread-scoped ACP session experiment (#6909) fix(desktop): scope composer autocomplete to focus (#6860) feat(desktop): add isolated named demo builds (#6407) fix(model-capabilities): humanize databricks goose model names (#7135) feat(db): add NIP-FI identity and final-admission schema foundation (#6994) feat(buzz-acp): give each channel thread its own agent session (#6732) docs: add review-proven failure-path & async-state rules to AGENTS.md (#7061) fix(desktop): back split thread headers (#7137) add public descriptions to agent personas (#7126) feat(desktop): add protected-build Bestie experiment (#6902) fix(relay): reject a frame on its own acknowledgement channel (#6961) fix(acp): wake agents from workflow messages (#6953) feat: render agent avatars as squircles (#7106) fix(ci): salvage Codex review output on PTY-shutdown hang (#7042) fix: retrieving cold memories; add regression task (#6950) Enforce NIP-OA authorization time bounds (#7004) feat(db): configurable writer session timeouts (lock, idle-txn, statement) (#6229) feat(desktop): use segmented controls for channel creation (#6845) feat(buzz-agent): surface stop reason and silent-turn WARN in telemetry (#7038) Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com> # Conflicts: # crates/buzz-acp/src/config.rs # crates/buzz-acp/src/pool.rs # crates/buzz-acp/src/relay.rs # desktop/src-tauri/src/commands/agent_config_tests.rs # desktop/src-tauri/src/commands/agent_models_tests.rs # desktop/src-tauri/src/commands/agents_deploy.rs # desktop/src-tauri/src/commands/agents_tests.rs # desktop/src-tauri/src/commands/personas/delete_cascade_tests.rs # desktop/src-tauri/src/commands/personas/inbound/inbound_tests.rs # desktop/src-tauri/src/commands/personas/pending.rs # desktop/src-tauri/src/commands/personas/sharing.rs # desktop/src-tauri/src/commands/personas/snapshot/fidelity_tests.rs # desktop/src-tauri/src/commands/personas/snapshot/tests.rs # desktop/src-tauri/src/commands/personas/update/name_propagation_tests.rs # desktop/src-tauri/src/commands/team_snapshot/tests.rs # desktop/src-tauri/src/managed_agents/agent_events.rs # desktop/src-tauri/src/managed_agents/agent_snapshot_envelope.rs # desktop/src-tauri/src/managed_agents/agent_snapshot_tests.rs # desktop/src-tauri/src/managed_agents/config_bridge/reader_tests.rs # desktop/src-tauri/src/managed_agents/discovery/tests.rs # desktop/src-tauri/src/managed_agents/effective_config/tests.rs # desktop/src-tauri/src/managed_agents/global_config/tests.rs # desktop/src-tauri/src/managed_agents/parallelism.rs # desktop/src-tauri/src/managed_agents/persona_events/tests.rs # desktop/src-tauri/src/managed_agents/personas/tests.rs # desktop/src-tauri/src/managed_agents/readiness.rs # desktop/src-tauri/src/managed_agents/runtime/test_fixtures.rs # desktop/src-tauri/src/managed_agents/runtime/tests.rs # desktop/src-tauri/src/managed_agents/spawn_snapshot/tests.rs # desktop/src-tauri/src/managed_agents/team_snapshot.rs # desktop/src-tauri/src/managed_agents/teams_tests.rs # desktop/src-tauri/src/managed_agents/types/requests.rs # desktop/src-tauri/src/managed_agents/types/tests.rs # desktop/src-tauri/src/migration_avatar_tests.rs # desktop/src/features/agents/AGENTS.md # desktop/src/shared/api/types.ts
…bound-membership * origin/main: (32 commits) fix(model-capabilities): humanize databricks goose model names (#7135) feat(db): add NIP-FI identity and final-admission schema foundation (#6994) feat(buzz-acp): give each channel thread its own agent session (#6732) docs: add review-proven failure-path & async-state rules to AGENTS.md (#7061) fix(desktop): back split thread headers (#7137) add public descriptions to agent personas (#7126) feat(desktop): add protected-build Bestie experiment (#6902) fix(relay): reject a frame on its own acknowledgement channel (#6961) fix(acp): wake agents from workflow messages (#6953) feat: render agent avatars as squircles (#7106) fix(ci): salvage Codex review output on PTY-shutdown hang (#7042) fix: retrieving cold memories; add regression task (#6950) Enforce NIP-OA authorization time bounds (#7004) feat(db): configurable writer session timeouts (lock, idle-txn, statement) (#6229) feat(desktop): use segmented controls for channel creation (#6845) feat(buzz-agent): surface stop reason and silent-turn WARN in telemetry (#7038) fix(desktop): surface channel history load failures (#7013) fix(composer): polish automatic mentions (#6956) fix(desktop): resolve bundled sidecar on cheap path and bound login-shell spawns (#6904) perf(mobile): reduce cold startup and channel rendering delays (#6996) ... Signed-off-by: Storme Drone <49c46e84758b2ebff4abf5abbbd44ee4ce788fc3b55db9fa703eec124eead621@buzz.block.builderlab.xyz> # Conflicts: # desktop/src/testing/e2eBridge.ts
…c-agent-commit-identity * origin/main: Add voice notes to desktop messages (#6978) feat(desktop): add thread-scoped ACP session experiment (#6909) fix(desktop): scope composer autocomplete to focus (#6860) feat(desktop): add isolated named demo builds (#6407) fix(model-capabilities): humanize databricks goose model names (#7135) feat(db): add NIP-FI identity and final-admission schema foundation (#6994) feat(buzz-acp): give each channel thread its own agent session (#6732) docs: add review-proven failure-path & async-state rules to AGENTS.md (#7061) fix(desktop): back split thread headers (#7137) add public descriptions to agent personas (#7126) feat(desktop): add protected-build Bestie experiment (#6902) fix(relay): reject a frame on its own acknowledgement channel (#6961) fix(acp): wake agents from workflow messages (#6953) feat: render agent avatars as squircles (#7106) fix(ci): salvage Codex review output on PTY-shutdown hang (#7042) fix: retrieving cold memories; add regression task (#6950) Enforce NIP-OA authorization time bounds (#7004) feat(db): configurable writer session timeouts (lock, idle-txn, statement) (#6229) feat(desktop): use segmented controls for channel creation (#6845) feat(buzz-agent): surface stop reason and silent-turn WARN in telemetry (#7038) Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
Why
A wedged relay boot pod holding a relation lock can park every other writer in the fleet behind it: DB load pins at pool capacity in
Lock:relationwaits while CPU stays flat, and nothing server-side releases the lock until the holder dies. We hit exactly this in production — ~1,400 sessions queued behind one crash-looping pod's boot transaction for ~20 minutes until kubelet killed the container.What
Applies session-level Postgres timeouts to every writer connection inside the existing single
after_connecthook inbuzz-db, all env-tunable through the sameConfig::from_env → DbConfigpath as the existing pool-size knobs:BUZZ_DB_LOCK_TIMEOUT_MSlock_timeoutBUZZ_DB_IDLE_TXN_TIMEOUT_MSidle_in_transaction_session_timeoutBUZZ_DB_STATEMENT_TIMEOUT_MSstatement_timeout0disables a timeout (Postgres semantics) and deliberately passes through the env parsing — unlike the pool-size knobs where0falls back to the default. The reader pool is untouched: replica sessions never take contended locks and already fail acquire in 150 ms.Deployers tune these via plain env vars (
.env, orrelay.extraEnvin the Helm chart) — no code changes needed.Behavior change to note
With the 5 s default
lock_timeout, a boot-time migration or backfill that waits >5 s on a lock now errors (surfacing in logs / crash-looping the pod) instead of stalling silently. That is the intended visible-failure-over-fleet-stall tradeoff; deployers with slow contended migrations can setBUZZ_DB_LOCK_TIMEOUT_MS=0.Testing
cargo test -p buzz-db -p buzz-relay— buzz-db green; buzz-relay has 9 failures that also fail on cleanmainin this environment (api::admin/api::media/mesh_demo — unrelated, pre-existing).0-passthrough / invalid-fallback for all three env vars.writer_pool_safety_hook_is_single_and_composedsource-shape test so the timeouts can't drift out of the singleafter_connecthook (SQLx replaces hooks — a second hook would silently disarm the floor guard).cargo fmt --checkandcargo clippy --all-targetsclean for the touched crates.Closest existing PR/issue: none found.
Update Aug 28, 17:06 EDT: Rebased onto
mainata3730784fcand addressed the latest correctness review.buzz-db::runtimepool constructor and kept the shared env overlay for relay, admin, deletion, and audit writers.lock_timeoutandstatement_timeoutfor their intentional long wait/DDL path. This supersedes the earlier “Behavior change to note”: contended boot migrations wait for the current migration owner rather than crash-looping after five seconds.55P03lock timeouts, using exponential backoff capped at one second. Other database errors retain the existing terminal error behavior, and retries emitbuzz_audit_log_lock_retries_total.lock_timeout, observes a retry, releases the lock, and proves the original entry is appended exactly once.Current verification supersedes the earlier testing notes: workspace Rust clippy passed with warnings denied; all nine infrastructure-free backend unit-test lanes passed; all three focused PostgreSQL regressions passed against PostgreSQL 17; formatting, diff checks, file-size guards, and desktop frontend checks passed. The Linux Blox workstation could not run the unrelated Tauri native lane because
glib-2.0is absent, so that platform check is left to PR CI.Update Aug 31, 11:09 EDT: Rebased onto current
mainatc3132c3ee9and reran the requested audit-lock contention scenario on Blox at head896c3fe9ed.git range-diffreports both PR commits unchanged by the rebase; the branch remains two commits and the worktree is clean.cargo fmt --all -- --checkand clippy with warnings denied passed forbuzz-db,buzz-relay,buzz-admin, andbuzz-deletion.BUZZ_DB_LOCK_TIMEOUT_MS=300, and an eight-second hold on the community audit advisory lock. The real message was accepted and persisted once while the lock was held; its audit-row count remained zero during contention while retries accumulated. After release, exactly oneevent_createdaudit row appeared and remained exactly one after an additional two-second duplicate check. The run recorded nine lock-timeout retries, zero audit failures, and event ID7f8c4ffae28e78555fcf2d56396d6e6c01b3712e5411288dc79e9a54af9d9444.Generated with Codex