feat: store launcher state outside game dirs
Move launcher-owned metadata from game roots into the configured peer state area. Peer identity, the local library index, install intent logs, and setup markers now live under app/CLI state instead of being written beside games. The Tauri shell passes its app data directory into the peer, and the peer CLI runs the same path through its explicit --state-dir. Add a dedicated pre-start migration phase for legacy files. It migrates the old global library index, per-game install intents, and the old first-start marker into app state, then deletes legacy files only after the replacement write succeeds. Normal scan, install, recovery, and transfer paths no longer read legacy state files. Rename the old first-start meaning to setup_done and only set it after launching game_setup.cmd. Start/setup scripts keep the shared argument shape, while server_start.cmd now uses cmd /k and a visible window so server logs stay open for inspection. While validating the Docker scenario matrix, make download terminal events come from the handler after local state refresh and operation cleanup. This makes download-finished/download-failed safe points for immediate follow-up CLI commands. Also update the multi-peer chunking scenario to use a sparse archive large enough to actually span multiple production chunks. Test Plan: - just fmt - just test - just frontend-test - just build - just clippy - git diff --check - python3 crates/lanspread-peer-cli/scripts/run_extended_scenarios.py Refs: local app-state migration discussion
This commit is contained in:
@@ -124,7 +124,8 @@ Reserved per-game paths:
|
||||
- `.local.installing/` is extraction staging.
|
||||
- `.local.backup/` holds the previous install while an update or uninstall is in
|
||||
flight.
|
||||
- `.lanspread.json` is the atomic per-game intent log.
|
||||
- `games/<game_id>/install_intent.json` in the configured state directory is the
|
||||
atomic per-game intent log.
|
||||
- `.lanspread_owned` inside `.local.*` directories proves Lanspread ownership
|
||||
when the current intent is `None`.
|
||||
|
||||
@@ -133,11 +134,17 @@ game root only for a catalog ID that is a single direct child of the configured
|
||||
game directory, has a regular root-level `version.ini`, and has no `local/`,
|
||||
`.local.installing/`, or `.local.backup/` path.
|
||||
|
||||
Recovery reads `.lanspread.json` and combines the recorded intent with the
|
||||
observed `local/`, `.local.installing/`, and `.local.backup/` state. Intent
|
||||
states `Installing`, `Updating`, and `Uninstalling` prove ownership of the
|
||||
corresponding reserved directories even if the marker was not flushed before a
|
||||
crash. With intent `None`, markerless `.local.*` directories are left untouched.
|
||||
Recovery reads app-state `install_intent.json` and combines the recorded intent
|
||||
with the observed `local/`, `.local.installing/`, and `.local.backup/` state.
|
||||
Intent states `Installing`, `Updating`, and `Uninstalling` prove ownership of
|
||||
the corresponding reserved directories even if the marker was not flushed before
|
||||
a crash. With intent `None`, markerless `.local.*` directories are left
|
||||
untouched.
|
||||
|
||||
Legacy `.lanspread/`, `.lanspread.json`, `.lanspread.json.tmp`,
|
||||
`.softlan_game_installed`, and `local/.softlan_first_start_done` files are
|
||||
handled only by the dedicated pre-start migration phase. Normal operation does
|
||||
not read legacy state paths.
|
||||
|
||||
### Result
|
||||
|
||||
@@ -195,8 +202,8 @@ Most scans become O(number of game dirs), with full recursion only when needed.
|
||||
- Cache the last accepted `manifest_hash` per peer to short-circuit
|
||||
manifest requests when unchanged.
|
||||
5. Local index + scan optimizations:
|
||||
- Introduce a cached index file (e.g., `.lanspread/index.json`) that stores
|
||||
per-root fingerprints and computed manifests.
|
||||
- Use the cached `local_library/index.json` file in the configured state
|
||||
directory to store per-root fingerprints and computed manifests.
|
||||
- Use filesystem watchers with a debounce window to collect changes and
|
||||
incrementally update the cache.
|
||||
- Schedule a low-frequency full scan to reconcile missed watcher events.
|
||||
|
||||
Reference in New Issue
Block a user