41e9a0efc1
Replace the `a9f9845` local-update dedup cache with explicit peer event semantics. Local scans now emit `LocalLibraryChanged` when the library changes, while operation mutations emit `ActiveOperationsChanged` from the mutation path. Tauri keeps joining those facts into the existing `games-list-updated` payload, so the frontend contract stays stable. This removes the cache/invalidation coupling between scan emission and operation state. The remaining forced local snapshot is explicit: accepted game directory changes can refresh the UI for an equivalent new path without sending a peer library delta. Operation guard cleanup and liveness cancellation now publish the same active operation snapshot as normal command-handler transitions. The peer CLI JSONL events follow the same split with `local-library-changed` and `active-operations-changed`. Test Plan: - `just fmt` - `CARGO_BUILD_RUSTC_WRAPPER= just test` - `CARGO_BUILD_RUSTC_WRAPPER= just clippy` - `git diff --check` Refs: CLEAN_CODE_PLAN_1.md
3.3 KiB
3.3 KiB
Clean Code Plan 1: Split Local Library and Operation UI Signals
Goal
Replace the a9f9845 local-update dedup cache with explicit event semantics.
The peer runtime should report local library changes and active operation
changes as separate facts, while the Tauri layer keeps joining those facts into
the existing games-list-updated payload for the frontend.
Architectural Picture
The current overloaded shape makes LocalGamesUpdated carry two independent
signals:
- local library contents, whose source of truth is
LocalLibraryStateandLocalLibraryState::update_from_scan; - active operation status, whose source of truth is
Ctx::active_operations.
The clean boundary is:
- peer scanning emits a local-library event when the scanned library state changes, with an explicit force policy for accepted path changes where the UI needs a fresh snapshot but peers do not need a delta;
- operation-state mutation emits an operation snapshot when the mutation happens;
- Tauri owns UI joining: it stores the latest catalog/local games and latest
operation snapshot, then emits
games-list-updatedfor the frontend.
That keeps the frontend contract stable while removing the cross-cutting cache and every manual invalidation call.
Implementation Steps
- Remove commit
a9f9845from the local branch history before implementing the replacement, so the final code is not built on the band-aid. - Replace
PeerEvent::LocalGamesUpdated { games, active_operations }with:PeerEvent::LocalLibraryChanged { games };PeerEvent::ActiveOperationsChanged { active_operations }.
- Add one operation-snapshot publisher near the peer event helpers. All normal
operation mutations must go through helpers that mutate
Ctx::active_operationsand then emitActiveOperationsChanged. - Make
OperationGuardpublish an operation snapshot when it performs exceptional cleanup on drop, so cancellation or aborted tasks do not leave UI state stale. - Keep the existing scan behavior that freezes active game summaries while an
operation is running, but emit
LocalLibraryChangedonly whenupdate_from_scanreturns a real delta or the scan was explicitly forced by an accepted path change. - Update the Tauri event loop to reconcile
ActiveOperationsChangedindependently, and callemit_games_listafter both library and operation state changes. - Update focused tests in peer handlers, local monitor, liveness, context guard,
and Tauri reconciliation to prove:
- unchanged settled scans do not emit local-library events;
- operation starts/transitions/ends emit authoritative snapshots;
- exceptional guard cleanup clears the operation snapshot;
- Tauri still emits the same
games-list-updatedUI payload.
- Update
CLEAN_CODE.md,crates/lanspread-peer/ARCHITECTURE.md, andcrates/lanspread-peer/README.mdso the docs describe the new shape rather than the dedup warning.
Review Gates
- No
last_local_update_key,LocalUpdateKey, or invalidate helper remains. - No operation-state mutation that should be visible to the UI bypasses the snapshot publisher.
- The peer event names reflect domain facts, not UI implementation details.
- Tauri remains the compatibility boundary for the frontend payload.
- Verification runs through
just fmt,just test,just clippy, andgit diff --check.