mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
fix(desktop): defer event sync off setup path
Finding: L2 event_sync boot reconcile did best-effort JSON reads, SQLite retention checks/writes, and event signing synchronously during Tauri setup after identity resolution. Snapshot the resolved owner keys, then spawn the reconcile after setup-critical boot work begins. The reconcile runs on spawn_blocking so no filesystem, SQLite, or signing work occupies the GUI setup path or an async worker. Secret-store identity resolution remains synchronous and out of scope by design. Co-authored-by: Tyler Longwell <tlongwell@block.xyz> Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
This commit is contained in:
co-authored by
Tyler Longwell
parent
13578737fe
commit
7d2cdba6f0
@@ -19,6 +19,24 @@ pub fn run_event_sync(app: &tauri::AppHandle, owner_keys: &nostr::Keys) {
|
||||
crate::managed_agents::reconcile::reconcile_agents_to_events(app, owner_keys);
|
||||
}
|
||||
|
||||
/// Spawn the best-effort event reconcile off the synchronous Tauri setup path.
|
||||
///
|
||||
/// The owner keys are cloned before spawning so the task never touches the
|
||||
/// `AppState::keys` mutex. The reconcile itself is still synchronous JSON,
|
||||
/// SQLite, and signing work, so it runs on the blocking pool rather than an
|
||||
/// async worker.
|
||||
pub fn spawn_event_sync(app: tauri::AppHandle, owner_keys: nostr::Keys) {
|
||||
tauri::async_runtime::spawn(async move {
|
||||
if let Err(e) = tauri::async_runtime::spawn_blocking(move || {
|
||||
run_event_sync(&app, &owner_keys);
|
||||
})
|
||||
.await
|
||||
{
|
||||
eprintln!("buzz-desktop: event-sync: spawn_blocking failed: {e}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Reconcile `personas.json` into the persona-event retention store.
|
||||
///
|
||||
/// Must run AFTER `migrate_packs_to_teams` (depends on field renames being
|
||||
|
||||
@@ -226,14 +226,13 @@ pub fn run() {
|
||||
resolve_persisted_identity(&app_handle, &state)
|
||||
.map_err(|e| -> Box<dyn std::error::Error> { e.into() })?;
|
||||
|
||||
// Sync team-dir edits and reconcile persona/team events. Needs the
|
||||
// resolved owner keys, so it runs after identity resolution.
|
||||
// Snapshot owner keys after identity resolution; the best-effort
|
||||
// event reconcile itself runs off the synchronous setup path below.
|
||||
let owner_keys = state
|
||||
.keys
|
||||
.lock()
|
||||
.map(|k| k.clone())
|
||||
.map_err(|e| -> Box<dyn std::error::Error> { e.to_string().into() })?;
|
||||
event_sync::run_event_sync(&app_handle, &owner_keys);
|
||||
|
||||
// Backfill the pinned persona snapshot for any pre-existing agent
|
||||
// that predates the record-authoritative-spawn cutover (persona_id
|
||||
@@ -332,6 +331,12 @@ pub fn run() {
|
||||
|
||||
try_regenerate_nest(&app_handle);
|
||||
|
||||
// Sync team-dir edits and reconcile persona/team/agent events after
|
||||
// setup can continue. It is best-effort retention backfill, unlike
|
||||
// identity resolution above, so JSON/SQLite/signing work must not
|
||||
// hold the boot path hostage.
|
||||
event_sync::spawn_event_sync(app_handle.clone(), owner_keys);
|
||||
|
||||
if let Some(mgr) = huddle::models::global_model_manager() {
|
||||
mgr.start_stt_download(state.http_client.clone());
|
||||
mgr.start_tts_download(state.http_client.clone());
|
||||
|
||||
Reference in New Issue
Block a user