feat(qconnect): factor transport loop into QconnectApp::run_session_loop (slice 5)

Move the spawned transport event-loop body out of the Tauri adapter into the
shared QconnectApp::run_session_loop, so both frontends inherit takeover
arbitration / deferred renderer-join / reconnect resync / Lagged re-ask. The
adapter-coupled seams go through a new SessionLoopHost trait:

- update_lifecycle      -- Tauri gates on a live runtime + dedups, emits via sink
- bootstrap_after_reconnect
- deferred_renderer_join -- R2: the CoreBridge track-duration read stays adapter-side
- on_reconnect_exhausted -- R3: Exhausted + last_error + runtime=None teardown +
  the raw qconnect:status_changed emit; returns whether the loop should break
- on_loop_error          -- the raw qconnect:error channel

TauriSessionLoopHost implements it over the existing service handles; connect()
is reduced to: build host -> spawn(app.run_session_loop(host, idle_retry)). The
diagnostic/lifecycle/resync emits still route through self.sink, so the Svelte
wire surface is byte-identical. hex_preview + queue_payload_track_preview + the
re-ask budget const relocate with the loop; the dead Tauri copies are removed.
R3 (QconnectRuntime/JoinHandle ownership, #358 latch, disconnect teardown) stays
adapter-side.

qconnect-app 38 green, src-tauri qconnect 42 green (the byte-identity fence).

cc
This commit is contained in:
vicrodh committed 2026-06-02 16:23:46 -06:00
1 parent e8ea401af3
commit a07bb36327
5 files changed
+446 -388

No files matched your search

+2 -1
View File
@@ -12,7 +12,8 @@ pub mod startup;
mod sync_state;
pub use app::{
queue_payload_track_preview, QconnectApp, SessionApplyOutcome, SessionStateTakeoverInput,
queue_payload_track_preview, QconnectApp, SessionApplyOutcome, SessionLoopHost,
SessionStateTakeoverInput,
};
pub use startup::{compute_effective_startup, QconnectStartupMode};
pub use error::QconnectAppError;