fix(peer): settle current-protocol local state cleanup
The follow-up backlog had drifted into three settled peer/runtime issues: the legacy game-list fallback contradicted the one-wire-version policy, the Tauri shell still re-derived local install state from disk after peer snapshots, and `Availability::Downloading` existed even though active operations are already reported through a separate operation table. Remove the legacy `AnnounceGames` request and fallback service. Discovery now ignores peers that do not advertise the current protocol and a peer id, and library changes are sent through the current delta path only. This keeps the runtime aligned with the documented current-build-only interoperability model. Make peer `LocalGamesUpdated` snapshots authoritative for local fields in the Tauri database. The GUI-side catalog still owns static metadata such as names, sizes, and descriptions, but downloaded, installed, local version, and availability now come from the peer runtime instead of a second whole-library filesystem scan. Snapshot reconciliation also pins the missing-begin and missing-finish lifecycle cases in tests. Collapse availability back to the settled `Ready` and `LocalOnly` states. Aggregation now counts only `Ready` peers as download sources, and the frontend no longer carries a dead `Downloading` enum value. The core peer also exposes the small non-GUI hooks needed by scripted callers: startup options for state and mDNS, a local-ready event, direct connection, peer snapshots, and an explicit post-download install policy. Those hooks reuse the same current protocol path and do not add compatibility shims. Test Plan: - `git diff --check` - `just fmt` - `just clippy` - `just test` Refs: BACKLOG.md, FINDINGS.md, IMPL_DECISIONS.md
This commit is contained in:
@@ -1,15 +1,10 @@
|
||||
//! Shared helpers for remote peer identity and legacy game announcements.
|
||||
//! Shared helpers for remote peer identity.
|
||||
|
||||
use std::{collections::HashMap, net::SocketAddr, sync::Arc};
|
||||
use std::{net::SocketAddr, sync::Arc};
|
||||
|
||||
use lanspread_db::db::Game;
|
||||
use lanspread_proto::GameSummary;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use crate::{
|
||||
library::compute_library_digest,
|
||||
peer_db::{PeerGameDB, PeerId},
|
||||
};
|
||||
use crate::peer_db::{PeerGameDB, PeerId};
|
||||
|
||||
pub async fn ensure_peer_id_for_addr(
|
||||
peer_game_db: &Arc<RwLock<PeerGameDB>>,
|
||||
@@ -20,40 +15,7 @@ pub async fn ensure_peer_id_for_addr(
|
||||
return peer_id;
|
||||
}
|
||||
|
||||
let legacy_id = format!("legacy-{peer_addr}");
|
||||
db.upsert_peer(legacy_id.clone(), peer_addr);
|
||||
legacy_id
|
||||
}
|
||||
|
||||
pub fn summary_from_game(game: &Game) -> GameSummary {
|
||||
GameSummary {
|
||||
id: game.id.clone(),
|
||||
name: game.name.clone(),
|
||||
size: game.size,
|
||||
downloaded: game.downloaded,
|
||||
installed: game.installed,
|
||||
eti_version: game.eti_game_version.clone(),
|
||||
manifest_hash: 0,
|
||||
availability: game.normalized_availability(),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn update_peer_from_game_list(
|
||||
peer_game_db: &Arc<RwLock<PeerGameDB>>,
|
||||
peer_addr: SocketAddr,
|
||||
games: &[Game],
|
||||
) -> Vec<Game> {
|
||||
let summaries = games.iter().map(summary_from_game).collect::<Vec<_>>();
|
||||
let mut by_id = HashMap::with_capacity(summaries.len());
|
||||
for summary in &summaries {
|
||||
by_id.insert(summary.id.clone(), summary.clone());
|
||||
}
|
||||
let digest = compute_library_digest(&by_id);
|
||||
let peer_id = ensure_peer_id_for_addr(peer_game_db, peer_addr).await;
|
||||
|
||||
let mut db = peer_game_db.write().await;
|
||||
db.update_peer_games(&peer_id, summaries);
|
||||
let features = db.peer_features(&peer_id);
|
||||
db.update_peer_library(&peer_id, 0, digest, features);
|
||||
db.get_all_games()
|
||||
let addr_id = format!("addr-{peer_addr}");
|
||||
db.upsert_peer(addr_id.clone(), peer_addr);
|
||||
addr_id
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user