update CLAUDE.md, README.md and justfile
This commit is contained in:
@@ -5,6 +5,7 @@ the current idea: mDNS discovery, QUIC transport, on-demand metadata, and
|
||||
chunked file transfers.
|
||||
|
||||
## Goals (unchanged)
|
||||
|
||||
- Local LAN discovery via mDNS.
|
||||
- QUIC + JSON messages for control, raw streams for file data.
|
||||
- UI drives operations through `PeerCommand`, peers remain headless.
|
||||
@@ -13,6 +14,7 @@ chunked file transfers.
|
||||
## Peer lifecycle and message flow
|
||||
|
||||
### 1) Startup and advertise
|
||||
|
||||
- Start QUIC server.
|
||||
- Advertise via mDNS with TXT records:
|
||||
- `peer_id` (stable ID, not tied to IP)
|
||||
@@ -21,7 +23,9 @@ chunked file transfers.
|
||||
- optional `hostname`
|
||||
|
||||
### 2) Discovery and handshake
|
||||
|
||||
When a peer is discovered:
|
||||
|
||||
1. Connect and send `Hello { peer_id, proto_ver, library_rev, library_digest, features }`.
|
||||
2. Receive `HelloAck { peer_id, proto_ver, library_rev, library_digest, features }`.
|
||||
3. If the remote `peer_id` is already known but the address changed, update it.
|
||||
@@ -32,11 +36,13 @@ When a peer is discovered:
|
||||
- Otherwise request `LibrarySnapshot`.
|
||||
|
||||
### 3) Steady state
|
||||
|
||||
- Any message updates `last_seen`.
|
||||
- Pings run only when idle (or on a longer interval), not every 5 seconds.
|
||||
- Library updates are pushed as deltas, debounced and coalesced.
|
||||
|
||||
### 4) Shutdown
|
||||
|
||||
- Optional `Goodbye { peer_id }` lets others remove the peer quickly.
|
||||
- If a peer vanishes without goodbye, stale timeout + ping removal handle it.
|
||||
- Goodbye is a hint, never required for correctness.
|
||||
@@ -44,20 +50,24 @@ When a peer is discovered:
|
||||
## Library sync protocol
|
||||
|
||||
### Summary and snapshot
|
||||
|
||||
- `LibrarySummary { library_rev, library_digest, game_count }`
|
||||
- `LibrarySnapshot { library_rev, games: Vec<GameSummary> }`
|
||||
|
||||
### Delta updates
|
||||
|
||||
- `LibraryDelta { from_rev, to_rev, added, updated, removed }`
|
||||
- `removed` is a list of game IDs.
|
||||
- Deltas are idempotent; ignore if `to_rev` <= known rev.
|
||||
|
||||
### GameSummary (concept)
|
||||
|
||||
- `id`, `name`, `eti_version`, `size`, `downloaded`, `installed`
|
||||
- `manifest_hash` (hash of file list + sizes)
|
||||
- `availability` (e.g., `ready`, `downloading`, `local_only`)
|
||||
|
||||
## When peers broadcast their game list
|
||||
|
||||
- Only on changes, not on a timer.
|
||||
- Use a short debounce (1-2 seconds) to coalesce bursts of filesystem events.
|
||||
- Send `LibraryDelta` to known peers; send `LibrarySummary` on new connections.
|
||||
@@ -65,6 +75,7 @@ When a peer is discovered:
|
||||
## Local game scanning: fast and low cost
|
||||
|
||||
### Strategy
|
||||
|
||||
1. Maintain a persistent on-disk index (per game):
|
||||
- `manifest_hash`, total size, file list (optional), and a fingerprint
|
||||
(version.ini mtime, .eti mtime/size, local install dir presence).
|
||||
@@ -73,6 +84,7 @@ When a peer is discovered:
|
||||
missed events.
|
||||
|
||||
### Fast-path scanning
|
||||
|
||||
- On startup, list only top-level game directories.
|
||||
- For each game, read a cheap fingerprint:
|
||||
- `.eti` size + mtime
|
||||
@@ -82,20 +94,24 @@ When a peer is discovered:
|
||||
- Only run a recursive scan for new or changed games.
|
||||
|
||||
### Result
|
||||
|
||||
Most scans become O(number of game dirs), with full recursion only when needed.
|
||||
|
||||
## File manifests and downloads
|
||||
|
||||
- Keep `GetGame`/manifest requests, but keyed by `manifest_hash` so repeated
|
||||
calls can be skipped when unchanged.
|
||||
- Downloads remain chunked QUIC streams with the existing integrity checks.
|
||||
|
||||
## Fault tolerance rules
|
||||
|
||||
- Every peer is keyed by `peer_id`, not by IP address.
|
||||
- `library_rev` is monotonic and guards against out-of-order updates.
|
||||
- Any mismatch or missing delta falls back to `LibrarySnapshot`.
|
||||
- Loss of goodbye is harmless; stale timeout is authoritative.
|
||||
|
||||
## Roadmap from current design to this one
|
||||
|
||||
1. Protocol updates in `lanspread-proto`:
|
||||
- Define `Hello`, `HelloAck`, `LibrarySummary`, `LibrarySnapshot`,
|
||||
`LibraryDelta`, and optional `Goodbye` messages.
|
||||
|
||||
@@ -67,7 +67,7 @@ When the UI asks to download a game:
|
||||
4. Each plan is executed in its own task (`download_from_peer`). Chunk requests
|
||||
use per-chunk QUIC streams and write into pre-created files. The chunk writer
|
||||
keeps existing data intact and only truncates when we intentionally fall back
|
||||
to a full file transfer, which prevents corruption when multiple peers fill
|
||||
to a full file transfer, which prevents corruption when multiple peers fill
|
||||
different regions of the same file.
|
||||
5. Failures are accumulated and retried (up to `MAX_RETRY_COUNT`) via
|
||||
`retry_failed_chunks`. If everything succeeds,
|
||||
|
||||
Reference in New Issue
Block a user