mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
`get_thread_replies` and every other relay read go out on the app-wide `http_client`, which carries no response deadline. A pooled connection that is open but dead — the far end gone without a FIN, a proxy holding the socket, a NAT rebind — leaves the request awaiting headers that never arrive. The thread panel then sits pending with no data, no error, and no spinner resolution, which is exactly the reported symptom shape. Give the bridge (`POST /query`, `POST /events`, `GET /info`) its own client with a 30s `read_timeout`, and give every client a 15s `connect_timeout`. The read timeout cannot simply go on the shared client. Probed against reqwest 0.13.4 with real sockets rather than assumed: - `read_timeout` bounds time-to-response-headers, and afterwards acts as an idle timer between body frames — both correct for small interactive JSON. - It is NOT reset by request-*body* progress, so any budget tight enough to catch a dead read also aborts a healthy slow upload. `do_upload` mints a 1-hour auth window for video; the STT model download is ~100 MB. - A per-request override is not available: reqwest 0.13's `RequestBuilder` exposes only the total `.timeout()`, never read semantics. One number cannot serve both surfaces, so this follows the existing `media_fetch_client` precedent and splits the client. `connect_timeout` is shared by all three because it stops at connection establishment and never measures a transfer. A new `http_client_base()` holds the common `resolve`/pool/connect config so the three cannot drift apart. Tests cover the stall abort, the upload that must survive, the absence of a deadline on the streaming clients, and — structurally, via reqwest's Debug output — that only the bridge client carries one. That last test exists because moving the read timeout onto the shared client is the tempting simplification and the worst regression, yet it is invisible to any behavioural test that finishes in under 30s. `paused_time_would_void_these_tests` pins the trap that cost the most here: under `start_paused` tokio auto-advances the clock whenever it is idle, and a pending socket read counts as idle, so the budgets elapse in zero real time and every assertion passes while measuring nothing. Co-authored-by: Dawn (sprout agent) <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@sprout-oss.stage.blox.sqprod.co> Signed-off-by: Dawn <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@buzz.block.builderlab.xyz>
Buzz
Desktop chat shell with:
- Tauri + React + TypeScript + Vite
- Tailwind CSS
- shadcn/ui-ready shared components
- Biome (lint/format/check)
- Feature-driven frontend structure
Scripts
pnpm dev- run the web frontendpnpm tauri dev- run the desktop apppnpm build- typecheck and build frontendpnpm typecheck- TypeScript checkspnpm lint- Biome lintpnpm format- Biome format (write)pnpm check- Biome check
Structure
src/shared- reusable app-wide code (ui,lib,styles)src/features- feature modules (vertical slices)src/app- top-level app composition