ChatGPT Codex 5.2 xhigh refactored > 45min
This commit is contained in:
@@ -1,17 +1,23 @@
|
||||
//! Command handlers for peer commands.
|
||||
|
||||
use std::{collections::HashSet, net::SocketAddr, sync::Arc};
|
||||
use std::{net::SocketAddr, sync::Arc};
|
||||
|
||||
use lanspread_db::db::{Game, GameDB, GameFileDescription};
|
||||
use lanspread_db::db::{Game, GameFileDescription};
|
||||
use tokio::sync::{RwLock, mpsc::UnboundedSender};
|
||||
|
||||
use crate::{
|
||||
PeerEvent,
|
||||
context::Ctx,
|
||||
download::download_game_files,
|
||||
local_games::{get_game_file_descriptions, load_local_game_db, local_download_available},
|
||||
network::{announce_games_to_peer, request_game_details_from_peer},
|
||||
peer_db::PeerGameDB,
|
||||
identity::FEATURE_LIBRARY_DELTA,
|
||||
local_games::{
|
||||
LocalLibraryScan,
|
||||
get_game_file_descriptions,
|
||||
local_download_available,
|
||||
scan_local_library,
|
||||
},
|
||||
network::{announce_games_to_peer, request_game_details_from_peer, send_library_delta},
|
||||
peer_db::{PeerGameDB, PeerId},
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
@@ -35,6 +41,20 @@ pub async fn emit_peer_game_list(
|
||||
}
|
||||
}
|
||||
|
||||
async fn ensure_peer_id_for_addr(
|
||||
peer_game_db: &Arc<RwLock<PeerGameDB>>,
|
||||
peer_addr: SocketAddr,
|
||||
) -> PeerId {
|
||||
let mut db = peer_game_db.write().await;
|
||||
if let Some(peer_id) = db.peer_id_for_addr(&peer_addr).cloned() {
|
||||
return peer_id;
|
||||
}
|
||||
|
||||
let legacy_id = format!("legacy-{peer_addr}");
|
||||
db.upsert_peer(legacy_id.clone(), peer_addr);
|
||||
legacy_id
|
||||
}
|
||||
|
||||
/// Tries to serve a game from local files.
|
||||
async fn try_serve_local_game(
|
||||
ctx: &Ctx,
|
||||
@@ -128,10 +148,11 @@ async fn request_game_details_and_update(
|
||||
peer_game_db: Arc<RwLock<PeerGameDB>>,
|
||||
) -> eyre::Result<Vec<GameFileDescription>> {
|
||||
let (file_descriptions, _) = request_game_details_from_peer(peer_addr, game_id).await?;
|
||||
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_game_files(peer_addr, game_id, file_descriptions.clone());
|
||||
db.update_peer_game_files(&peer_id, game_id, file_descriptions.clone());
|
||||
}
|
||||
|
||||
Ok(file_descriptions)
|
||||
@@ -277,9 +298,9 @@ pub async fn handle_set_game_dir_command(
|
||||
let ctx_clone = ctx.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
match load_local_game_db(&game_dir).await {
|
||||
Ok(db) => {
|
||||
update_and_announce_games(&ctx_clone, &tx_notify_ui, db).await;
|
||||
match scan_local_library(&game_dir).await {
|
||||
Ok(scan) => {
|
||||
update_and_announce_games(&ctx_clone, &tx_notify_ui, scan).await;
|
||||
log::info!("Local game database loaded successfully");
|
||||
}
|
||||
Err(e) => {
|
||||
@@ -306,67 +327,61 @@ pub async fn handle_get_peer_count_command(ctx: &Ctx, tx_notify_ui: &UnboundedSe
|
||||
pub async fn update_and_announce_games(
|
||||
ctx: &Ctx,
|
||||
tx_notify_ui: &UnboundedSender<PeerEvent>,
|
||||
new_db: GameDB,
|
||||
scan: LocalLibraryScan,
|
||||
) {
|
||||
let local_game_db = ctx.local_game_db.clone();
|
||||
let mut db_guard = local_game_db.write().await;
|
||||
let LocalLibraryScan {
|
||||
game_db,
|
||||
summaries,
|
||||
revision,
|
||||
} = scan;
|
||||
|
||||
let previous_games = db_guard
|
||||
.as_ref()
|
||||
.map(|db| db.games.keys().cloned().collect::<HashSet<_>>())
|
||||
.unwrap_or_default();
|
||||
let delta = {
|
||||
let mut library_guard = ctx.local_library.write().await;
|
||||
library_guard.update_from_scan(summaries, revision)
|
||||
};
|
||||
|
||||
let current_game_ids = new_db.games.keys().cloned().collect::<HashSet<_>>();
|
||||
let Some(delta) = delta else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Check if any games were removed
|
||||
let removed_games: Vec<String> = previous_games
|
||||
.difference(¤t_game_ids)
|
||||
{
|
||||
let mut db_guard = ctx.local_game_db.write().await;
|
||||
*db_guard = Some(game_db.clone());
|
||||
}
|
||||
|
||||
let all_games = game_db
|
||||
.all_games()
|
||||
.into_iter()
|
||||
.cloned()
|
||||
.collect();
|
||||
.collect::<Vec<Game>>();
|
||||
|
||||
if removed_games.is_empty() {
|
||||
// Check if any games were added or updated
|
||||
if previous_games != current_game_ids {
|
||||
log::debug!("Local games directory structure changed, updating database");
|
||||
*db_guard = Some(new_db);
|
||||
if let Err(e) = tx_notify_ui.send(PeerEvent::LocalGamesUpdated(all_games.clone())) {
|
||||
log::error!("Failed to send LocalGamesUpdated event: {e}");
|
||||
}
|
||||
|
||||
let all_games = db_guard
|
||||
.as_ref()
|
||||
.map(|db| db.all_games().into_iter().cloned().collect::<Vec<Game>>())
|
||||
.unwrap_or_default();
|
||||
let peer_targets = {
|
||||
let db = ctx.peer_game_db.read().await;
|
||||
db.peer_identities()
|
||||
.into_iter()
|
||||
.map(|(peer_id, addr)| {
|
||||
let features = db.peer_features(&peer_id);
|
||||
(peer_id, addr, features)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
|
||||
if let Err(e) = tx_notify_ui.send(PeerEvent::LocalGamesUpdated(all_games.clone())) {
|
||||
log::error!("Failed to send LocalGamesUpdated event: {e}");
|
||||
}
|
||||
|
||||
// Broadcast update to all peers
|
||||
let peer_addresses = { ctx.peer_game_db.read().await.get_peer_addresses() };
|
||||
for peer_addr in peer_addresses {
|
||||
let games_clone = all_games.clone();
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = announce_games_to_peer(peer_addr, games_clone).await {
|
||||
log::warn!("Failed to announce games to {peer_addr}: {e}");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log::info!("Detected removed games: {removed_games:?}");
|
||||
*db_guard = Some(new_db);
|
||||
|
||||
// Notify UI about the change
|
||||
let all_games = db_guard
|
||||
.as_ref()
|
||||
.map(|db| db.all_games().into_iter().cloned().collect::<Vec<Game>>())
|
||||
.unwrap_or_default();
|
||||
|
||||
if let Err(e) = tx_notify_ui.send(PeerEvent::LocalGamesUpdated(all_games.clone())) {
|
||||
log::error!("Failed to send LocalGamesUpdated event: {e}");
|
||||
}
|
||||
|
||||
// Broadcast update to all peers
|
||||
let peer_addresses = { ctx.peer_game_db.read().await.get_peer_addresses() };
|
||||
for peer_addr in peer_addresses {
|
||||
for (_peer_id, peer_addr, features) in peer_targets {
|
||||
if features
|
||||
.iter()
|
||||
.any(|feature| feature == FEATURE_LIBRARY_DELTA)
|
||||
{
|
||||
let delta = delta.clone();
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = send_library_delta(peer_addr, delta).await {
|
||||
log::warn!("Failed to send library delta to {peer_addr}: {e}");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
let games_clone = all_games.clone();
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = announce_games_to_peer(peer_addr, games_clone).await {
|
||||
|
||||
Reference in New Issue
Block a user