Files
lanspread/IMPL_DECISIONS.md
T
ddidderr 6242d64583 fix(peer): repair update lifecycle regressions
FINDINGS.md identified three merge blockers in the post-plan install/update
flow.

Updates now use FetchLatestFromPeers so the Tauri update command bypasses
local manifest serving and asks peers that advertise the latest version for
fresh file metadata. PeerGameDB now aggregates and validates file descriptions
from latest-version peers, keeping stale cached metadata for older versions
from poisoning chunk planning when filenames stay the same but sizes change.

Download-to-install handoff now performs explicit async state transitions.
The download task mutates Downloading to Installing or Updating under the
active-operation write lock, clears the cancellation token, and then runs the
install transaction. OperationGuard remains armed only as crash or abort
cleanup and is disarmed after normal explicit cleanup, so final refreshes no
longer race a deferred Drop cleanup.

Local library index writers now serialize the load/mutate/save window with one
async mutex. The index fingerprint also includes the root version.ini contents
so a same-length version rewrite in the same mtime second still updates the
reported local version.

The tradeoff is that local index mutations are serialized in-process instead
of moved into a dedicated actor. That keeps the fix small and scoped to the
merge blockers while preserving the existing scanner API.

Test Plan:
- just fmt
- just test
- just clippy
- just build
- git diff --check

Refs:
- FINDINGS.md
2026-05-16 14:19:10 +02:00

34 lines
2.1 KiB
Markdown

# Implementation Decisions
- 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.
- 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.
- Removed the dead internal `PeerCommand::UpdateGame` path. The UI update button
now sends `FetchLatestFromPeers`, which skips local manifest serving and asks
latest-version peers for fresh file metadata before the normal download and
update transaction runs.
- 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`.