fix(peer): refresh settled install state after operations
The follow-up review found a few stale lifecycle edges around local game transactions. Recovery could sweep active roots, post-operation refreshes still re-ran full startup recovery, and the UI kept inferring local-only state from downloaded and installed flags instead of the backend availability. This updates the peer lifecycle so startup recovery skips active operations, install/update/uninstall refresh only the affected game after the operation guard is dropped, and path-changing game-directory updates are rejected while operations are active. It also removes the dead UpdateGame command, drops the unused manifest_hash write field while preserving old JSON reads, renames the internal install-finished event, and carries availability through the DB, peer summaries, Tauri refreshes, and the React model. The included follow-up documents record the review source, implementation decisions, and the remaining FOLLOW_UP_2.md work so later commits can stay small instead of reopening the completed plan items. Test Plan: - git diff --check - just fmt - just clippy - just test Follow-up-Plan: FOLLOW_UP_PLAN.md
This commit is contained in:
+18
-6
@@ -3,18 +3,30 @@
|
||||
- Added a `just test` recipe so unit tests can be run through the repository's
|
||||
required `just ...` command surface instead of invoking `cargo test`
|
||||
directly.
|
||||
- Kept the existing frontend `game-unpack-finished` event name for successful
|
||||
transactional installs. The peer now emits install lifecycle events, but the
|
||||
compatibility event still lets the UI reuse its existing "install complete"
|
||||
path.
|
||||
- Renamed the frontend success event to `game-install-finished`; the old
|
||||
unpack name no longer matched the transactional install/update lifecycle.
|
||||
- Implemented watcher rescans by reusing the existing `.lanspread/library_index.json`
|
||||
cache and updating a single game entry in that index. This satisfies the
|
||||
per-ID optimized rescan requirement without adding a second cache format.
|
||||
- Split full startup recovery from ordinary settled refreshes. Startup and real
|
||||
`SetGameDir` changes run recovery plus a scan; install/update/uninstall
|
||||
completion only rescans the affected game after operation tracking has been
|
||||
cleared.
|
||||
- Rejected path-changing `SetGameDir` while operations are active. Same-path
|
||||
refreshes are allowed and deliberately skip full recovery so they cannot sweep
|
||||
download transients for in-flight work.
|
||||
- Kept a separate `active_downloads` cancellation-token map next to the single
|
||||
`active_operations` table. The operation table is the authoritative state for
|
||||
gates; the token map is only cancellation plumbing for in-flight downloads.
|
||||
- Treated a downloaded-but-not-installed game as immediately installable from
|
||||
Tauri by sending `PeerCommand::InstallGame` directly. A not-downloaded game
|
||||
still uses `GetGame`, and the peer auto-installs after the sentinel commit.
|
||||
- Derived the UI's `LocalOnly` badge from `installed && !downloaded` because the
|
||||
UI-facing `Game` type does not carry the protocol-level `Availability` enum.
|
||||
- Removed the dead internal `PeerCommand::UpdateGame` path. The UI update button
|
||||
intentionally sends `GetGame`, and the peer infers install versus update from
|
||||
the presence of `local/` after archives are available.
|
||||
- Kept `Availability::Downloading` in the wire protocol for compatibility, but
|
||||
local summaries do not emit it today because active operations are gated out
|
||||
of scans and serving decisions.
|
||||
- Threaded availability through the UI-facing `Game` payload so `LocalOnly`
|
||||
rendering follows backend state instead of reverse-engineering it from
|
||||
`installed && !downloaded`.
|
||||
|
||||
Reference in New Issue
Block a user