From 2cd376b5353bf5cd174c242d7de1094c2130e07e Mon Sep 17 00:00:00 2001 From: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co> Date: Fri, 17 Jul 2026 21:28:19 -0400 Subject: [PATCH] test(desktop): cover one-shot relay pin migration gate Extract the pending relay-stamp gate behind a synchronous helper so the production apply_workspace call and focused test share the same one-shot behavior. The helper completes the stamp before returning; workspace activation remains scheduled only after the enclosing blocking apply finishes. Co-authored-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co> Signed-off-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co> --- desktop/src-tauri/src/commands/workspace.rs | 56 +++++++++++++++++---- 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/desktop/src-tauri/src/commands/workspace.rs b/desktop/src-tauri/src/commands/workspace.rs index 4af457e0f..a428573f3 100644 --- a/desktop/src-tauri/src/commands/workspace.rs +++ b/desktop/src-tauri/src/commands/workspace.rs @@ -1,6 +1,6 @@ use nostr::Keys; use serde::{Deserialize, Serialize}; -use std::sync::atomic::Ordering; +use std::sync::atomic::{AtomicBool, Ordering}; use tauri::{AppHandle, Emitter, Manager, State}; use crate::app_state::AppState; @@ -166,14 +166,13 @@ pub async fn apply_workspace( // from floating to a later workspace switch. Runs before the restore // trigger below so restored agents spawn from stamped records. A // failure is logged and retried on the next boot. - if state - .agent_relay_stamp_pending - .swap(false, Ordering::AcqRel) - { - if let Err(error) = pin_blank_agent_relays(&app, &state, &relay_url) { - eprintln!("buzz-desktop: blank agent relay migration failed: {error}"); - } - } + run_pending_agent_relay_stamp(&state.agent_relay_stamp_pending, || { + pin_blank_agent_relays(&app, &state, &relay_url) + }) + .unwrap_or_else(|error| { + eprintln!("buzz-desktop: blank agent relay migration failed: {error}"); + None + }); // ── Filesystem side-effect (non-fatal) ──────────────────────────────── // Persist the *effective* repos_dir (None when the candidate failed @@ -260,6 +259,45 @@ pub async fn apply_workspace( Ok(()) } +fn run_pending_agent_relay_stamp( + pending: &AtomicBool, + stamp: impl FnOnce() -> Result, +) -> Result, String> { + if !pending.swap(false, Ordering::AcqRel) { + return Ok(None); + } + stamp().map(Some) +} + +#[cfg(test)] +mod tests { + use super::run_pending_agent_relay_stamp; + use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; + + #[test] + fn agent_relay_stamp_runs_once_and_completes_before_returning() { + let pending = AtomicBool::new(true); + let stamps = AtomicUsize::new(0); + + let first = run_pending_agent_relay_stamp(&pending, || { + stamps.fetch_add(1, Ordering::SeqCst); + Ok(7) + }) + .expect("first stamp succeeds"); + assert_eq!(first, Some(7)); + assert_eq!(stamps.load(Ordering::SeqCst), 1); + + let second = run_pending_agent_relay_stamp(&pending, || { + stamps.fetch_add(1, Ordering::SeqCst); + Ok(8) + }) + .expect("second apply skips the migration"); + assert_eq!(second, None); + assert_eq!(stamps.load(Ordering::SeqCst), 1); + assert!(!pending.load(Ordering::Acquire)); + } +} + /// Stamp legacy blank-relay agent records with the applied workspace relay. /// /// Store-lock + load/save wrapper around [`stamp_blank_agent_relay_urls`];