markdown formatting

This commit is contained in:
2026-08-09 16:16:45 +02:00
parent f4a6259cf3
commit 18dd3b7e07
21 changed files with 1630 additions and 893 deletions
+32 -32
View File
@@ -23,19 +23,20 @@ It is designed to run headless other crates (most notably
`Game` definitions, tracks the latest ETI version per title, and keeps the
last seen list of `GameFileDescription` entries for each peer.
Internally the peer runtime owns four long-lived tasks that run for the
lifetime of the process:
Internally the peer runtime owns four long-lived tasks that run for the lifetime
of the process:
1. **Server component** (`run_server_component`) listens for QUIC connections,
advertises via mDNS, and serves `Request::ListGames`, `Request::GetGame`,
`Request::GetGameFileData`, `Request::GetGameFileChunk`, and
`Request::StreamInstall` by reading from the local game directory.
2. **Discovery loop** (`run_peer_discovery`) uses the `lanspread-mdns`
helper to discover other peers. The blocking mDNS work is executed on a
dedicated thread via `tokio::task::spawn_blocking` so that the Tokio runtime
remains responsive.
3. **Ping service** (`run_ping_service`) periodically issues QUIC ping requests
to keep peer liveness up to date and prunes stale entries from `PeerGameDB`.
2. **Discovery loop** (`run_peer_discovery`) uses the `lanspread-mdns` helper
to discover other peers. The blocking mDNS work is executed on a dedicated
thread via `tokio::task::spawn_blocking` so that the Tokio runtime remains
responsive.
3. **Ping service** (`run_ping_service`) periodically issues QUIC ping
requests to keep peer liveness up to date and prunes stale entries from
`PeerGameDB`.
4. **Local game monitor** (`run_local_game_monitor`) watches the configured
game directory and each game root non-recursively, gates per-ID rescans while
operations are active, emits local-library changes separately from active
@@ -61,8 +62,9 @@ When the UI asks to download a game:
1. The UI first issues `PeerCommand::GetGame` for a new download, or
`PeerCommand::FetchLatestFromPeers` for an update that must bypass local
archives. The selected peers are queried via `request_game_details_from_peer`,
and their file manifests are merged inside `PeerGameDB`.
archives. The selected peers are queried via
`request_game_details_from_peer`, and their file manifests are merged inside
`PeerGameDB`.
2. Once the UI receives `PeerEvent::GotGameFiles`, it forwards the selected file
list back with `PeerCommand::DownloadGameFiles`.
3. `download_game_files` starts a version-sentinel transaction, parks any old
@@ -84,8 +86,8 @@ When the UI asks to download a game:
sweep `.version.ini.tmp` and `.version.ini.discarded` without restoring the
previous sentinel. Cancelled downloads also discard the peer-owned download
payload while preserving `local/` and install transaction metadata.
7. After a successful sentinel commit, `PeerEvent::DownloadGameFilesFinished`
is emitted and the peer auto-runs the install transaction.
7. After a successful sentinel commit, `PeerEvent::DownloadGameFilesFinished` is
emitted and the peer auto-runs the install transaction.
### Streamed Install Pipeline
@@ -108,25 +110,24 @@ renamed to `local/`, post-promote intent or launch-settings cleanup failures are
logged for startup recovery rather than reported as a failed install.
`PeerCommand::CancelDownload` cancels the tracked download token for an active
transfer. The transfer task remains responsible for clearing `active_operations`,
discarding partial payload files, and refreshing the settled local snapshot, so
the UI continues to treat active-operation snapshots as the single source of
truth for whether a download is still running.
transfer. The transfer task remains responsible for clearing
`active_operations`, discarding partial payload files, and refreshing the
settled local snapshot, so the UI continues to treat active-operation snapshots
as the single source of truth for whether a download is still running.
### Install Transactions
Install, update, uninstall, downloaded-file removal, and startup recovery live
under `src/install/`.
Install-side operation intent is stored atomically under the configured peer
state directory, at `games/<game_id>/install_intent.json`. Game roots still use
Lanspread-owned `.local.installing/` and `.local.backup/` directories marked by
`.lanspread_owned`. Startup recovery combines the recorded intent with the
observed filesystem state and only deletes reserved directories when intent or
marker ownership proves they belong to Lanspread.
Downloaded-file removal is deliberately separate from uninstall: it only accepts
catalog IDs that are direct children of the configured game directory, refuses
installed or in-flight roots, and deletes the whole game root only after finding
a regular root-level `version.ini` sentinel.
under `src/install/`. Install-side operation intent is stored atomically under
the configured peer state directory, at `games/<game_id>/install_intent.json`.
Game roots still use Lanspread-owned `.local.installing/` and `.local.backup/`
directories marked by `.lanspread_owned`. Startup recovery combines the recorded
intent with the observed filesystem state and only deletes reserved directories
when intent or marker ownership proves they belong to Lanspread. Downloaded-file
removal is deliberately separate from uninstall: it only accepts catalog IDs
that are direct children of the configured game directory, refuses installed or
in-flight roots, and deletes the whole game root only after finding a regular
root-level `version.ini` sentinel.
Legacy launcher-owned files in game directories are migrated by a dedicated
pre-start phase. Normal install, recovery, scan, and transfer paths use only the
@@ -142,11 +143,10 @@ The Tauri application embeds this crate in
game directory.
- The Tauri commands (`request_games`, `install_game`, `update_game`,
`remove_downloaded_game`, and `update_game_directory`) translate UI actions
into `PeerCommand`s. In
particular, `update_game_directory` validates the filesystem path before
storing it, loads the bundled catalog on first use, kicks off the peer runtime
on demand, and mirrors the installed/uninstalled state into the UI-facing
database.
into `PeerCommand`s. In particular, `update_game_directory` validates the
filesystem path before storing it, loads the bundled catalog on first use,
kicks off the peer runtime on demand, and mirrors the installed/uninstalled
state into the UI-facing database.
- A background task consumes `PeerEvent`s and fans them out to the front-end via
Tauri publish/subscribe events (`games-list-updated`, `game-download-*`,
`game-install-*`, `game-uninstall-*`, `peer-*`). The Tauri crate now only