feat(desktop): add configurable transport reconnect hook#1059
Open
wpfleger96 wants to merge 8 commits into
Open
feat(desktop): add configurable transport reconnect hook#1059wpfleger96 wants to merge 8 commits into
wpfleger96 wants to merge 8 commits into
Conversation
ba254b1 to
16191d3
Compare
Build-time env var BUZZ_BUILD_RELAY_RECONNECT_CMD carries a JSON config blob validated into a typed ReconnectHookConfig struct at compile time. If unset (OSS builds), the Tauri command is a pure no-op. If set, the frontend invokes it before relay preconnect() to run transport-layer recovery steps (e.g. warp-cli connect + access-reauth) and poll for readiness. All subprocess steps are non-fatal — timeout or failure falls through to the existing relay reconnect. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Rust Lint CI (cargo fmt --check) flagged the from_value closure in build.rs and the Command builder chain in relay_reconnect.rs. Let cargo fmt produce the canonical reflow so CI matches byte-for-byte. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
std::process::Command::output() blocks until the child exits, so a wedged warp-cli (the degraded-transport case this hook targets) would hang the spawn_blocking task forever — the frontend invoke never resolves, the Reconnect button spins, and a blocking-pool thread is pinned. timeout_ms only gated the poll loop between probe attempts, not any single subprocess. Route the step loop and the probe through a spawn + try_wait + kill-on-deadline helper modeled on media_transcode.rs run_ffmpeg_with_timeout, so each child is killed and reaped at the cap. Steps reuse timeout_ms per step; the probe phase stays a single timeout_ms ceiling by capping each attempt at the remaining budget. No config-schema change. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Stdio::null() replaces Stdio::piped() for stderr since the helper never reads it — removes a latent deadlock if a future command floods the OS pipe buffer. Doc comment on timeout_ms now accurately describes its broader role as a per-process wall-clock cap. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
16191d3 to
01680d9
Compare
The sidebar reconnect prompt only appeared once channelsQuery errored, which lags 60-120s behind a dropped socket (React Query staleTime + refetchInterval 60s plus one retry). OR-in the live, debounced connection state already powering ConnectionBanner so the prompt surfaces within ~2s of degradation, regardless of query error timing. Cached channels stay visible alongside the prompt. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
The Reconnect to relay item in the profile popover rendered unconditionally because SidebarProfileCard always passed a truthy onReconnect. Gate it on the same isRelayConnectionDegraded live-state check the sidebar prompt uses so the popover hides the item when healthy. The || isPending guard keeps it visible while a reconnect is in flight so it does not vanish mid-click. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Captures the profile-popover reconnect item and the sidebar relay-unreachable block in both healthy and degraded relay states, driving the real connectionStateEmitter via the E2E bridge. Each test asserts the failable gate condition before screenshotting so a regression breaks the capture, not just the image. Registers the spec in the smoke testMatch allowlist (both Playwright projects use explicit allowlists; an unlisted spec yields no tests). Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
wpfleger96
pushed a commit
that referenced
this pull request
Jun 16, 2026
The 03/04 sidebar screenshots were visually identical: the sidebar-relay-unreachable block renders at the bottom of the scroll region, painted under the absolute z-30 profile footer, so it was occluded even though toBeVisible passed (it is in-DOM). The prior scroll helper matched the wrong overflowing descendant and no-opped. Scroll the exact [data-sidebar="content"] container fully down before capture so the block clears the footer, applied symmetrically to 03 (absent) and 04 (present). Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
wpfleger96
pushed a commit
that referenced
this pull request
Jun 16, 2026
Collaborator
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.




Adds a build-time-configured transport reconnect hook so internal builds can recover the underlying transport (e.g. WARP VPN) before the relay reconnect, while OSS builds stay a pure no-op.
The generic "Reconnect to relay" button is transport-agnostic; internal users behind a VPN need the transport re-established first. A build-time env var
BUZZ_BUILD_RELAY_RECONNECT_CMD(set only insquareup/buzz-releases) carries a JSON config validated into a typed Rust struct at compile time, so the OSS binary ships with zero VPN knowledge.relay_reconnect_hookruns structured fixed-argv steps plus a readiness probe, wrapped intokio::task::spawn_blocking; non-fatal end-to-end so any failure falls through topreconnect().ReconnectHookConfiglives in one dep-free source fileinclude!'d by bothbuild.rsand the runtime command, so the compile-time validation and runtime parse cannot drift.useReconnectRelay.tsinvokes the hook before relay preconnect, guarded so a hook rejection cannot abort the reconnect.BUZZ_BUILD_RELAY_RECONNECT_CMDis unset (OSS), the command compiles to an early-return no-op.