feat(peer): journal download file ownership
Track the exact regular files owned by each completed and in-flight peer download instead of sweeping every non-reserved path after cancellation. Bind the record to the canonical games directory, publish pending ownership before payload mutation, and use the final version.ini rename as the recovery commit point. Make replacement, cancellation, and startup recovery preserve unknown files and install state while removing stale or partial downloader-owned bytes. Add a new-format baseline so legacy discarded sentinels cannot make partially modified payloads ready, sync payload and journal state in transaction order, and serialize startup recovery against operation admission. Document ambiguous legacy target adoption, portable alias transitions, and the other ownership tradeoffs in the refactor decision log. Test Plan: - `just clippy` -- passed - `just test` -- passed (182 peer-core tests plus the full workspace) - `just fmt` -- Rust, TOML, and Prettier formatting completed; the command then stopped on 40 pre-existing rumdl findings in unrelated Markdown content - `git diff --cached --check` -- passed
This commit is contained in:
@@ -2,21 +2,6 @@
|
||||
|
||||
## Open
|
||||
|
||||
### Crash-during-download leaves orphan archive files
|
||||
|
||||
`crates/lanspread-peer/src/install/transaction.rs:329` —
|
||||
`recover_download_transients` sweeps only `.version.ini.tmp` and
|
||||
`.version.ini.discarded` on startup. The new cancel-cleanup
|
||||
(`download/storage.rs::discard_cancelled_download`) is only invoked from the
|
||||
in-flight orchestrator, so a crash mid-download leaves partial `.eti` archives
|
||||
in the game root. After restart the user sees a game that looks half-downloaded
|
||||
with no way to clean it up except `RemoveDownloadedGame`. Closing this would
|
||||
mean calling the same discard pass during recovery for any game root whose
|
||||
intent is `None` and whose `version.ini` is absent.
|
||||
|
||||
Not blocking. The cancel-button fix is correct in its scope; this is the
|
||||
symmetric crash-recovery case.
|
||||
|
||||
### `handleErrorEvent` still writes status fields directly
|
||||
|
||||
`crates/lanspread-tauri-deno-ts/src/hooks/useGames.ts:80-89` — the error handler
|
||||
@@ -37,8 +22,12 @@ No out-of-scope code smells or issues were identified in Claude's review. All
|
||||
four points were direct follow-up cleanup for the current protocol change and
|
||||
were handled in code.
|
||||
|
||||
The previous three findings have landed in code and tests:
|
||||
The previous four findings have landed in code and tests:
|
||||
|
||||
- Download ownership is now journaled before payload mutation. Cancellation and
|
||||
startup recovery remove only exact downloader-owned paths and preserve unknown
|
||||
root files, instead of leaving crashed partial archives or broadly deleting
|
||||
the game root.
|
||||
- `update_game` now uses `PeerCommand::FetchLatestFromPeers` to skip local
|
||||
manifest serving and fetch fresh peer metadata. Covered by
|
||||
`update_fetch_emits_fresh_manifest_from_latest_peer` and
|
||||
|
||||
Reference in New Issue
Block a user