From d994e741b1df02720c1ff50a65978400a39ee72c Mon Sep 17 00:00:00 2001 From: ddidderr Date: Wed, 12 Nov 2025 22:29:00 +0100 Subject: [PATCH] early error on peer's failure to determine file size --- crates/lanspread-peer/src/lib.rs | 63 +++++++++++++++++++++++++++++-- crates/lanspread-proto/src/lib.rs | 1 + 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/crates/lanspread-peer/src/lib.rs b/crates/lanspread-peer/src/lib.rs index a2a7e7a..6b3d264 100644 --- a/crates/lanspread-peer/src/lib.rs +++ b/crates/lanspread-peer/src/lib.rs @@ -38,6 +38,45 @@ use crate::{ peer::{send_game_file_chunk, send_game_file_data}, }; +/// Custom error types for peer operations +#[derive(Debug)] +pub enum PeerError { + FileSizeDetermination { + path: String, + source: std::io::Error, + }, + GameDirNotSet, + Other(eyre::Report), +} + +impl std::fmt::Display for PeerError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PeerError::FileSizeDetermination { path, source } => { + write!(f, "Failed to determine file size for {path}: {source}") + } + PeerError::GameDirNotSet => write!(f, "Game directory not set"), + PeerError::Other(err) => write!(f, "General error: {err}"), + } + } +} + +impl std::error::Error for PeerError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + PeerError::FileSizeDetermination { source, .. } => Some(source), + PeerError::Other(err) => Some(err.root_cause()), + PeerError::GameDirNotSet => None, + } + } +} + +impl From for PeerError { + fn from(err: eyre::Report) -> Self { + PeerError::Other(err) + } +} + /// Initialize and start the peer system /// This function replaces the main.rs entry point and allows the peer to be started from other crates pub fn start_peer( @@ -1489,6 +1528,15 @@ async fn handle_peer_stream( id, file_descriptions, }, + Err(PeerError::FileSizeDetermination { path, source }) => { + let error_msg = format!( + "Failed to determine file size for {path}: {source}" + ); + log::error!( + "File size determination error for game {id}: {error_msg}" + ); + Response::InternalPeerError(error_msg) + } Err(e) => { log::error!( "Failed to get game file descriptions for {id}: {e}" @@ -1754,6 +1802,9 @@ async fn request_game_details_from_peer( Response::GameNotFound(_) => { eyre::bail!("peer {peer_addr} does not have game {game_id}") } + Response::InternalPeerError(error_msg) => { + eyre::bail!("peer {peer_addr} reported internal error: {error_msg}") + } _ => eyre::bail!("unexpected response from {peer_addr}: {response:?}"), } } @@ -1855,12 +1906,15 @@ async fn ping_peer(peer_addr: SocketAddr) -> eyre::Result { async fn get_game_file_descriptions( game_id: &str, game_dir: &str, -) -> eyre::Result> { +) -> Result, PeerError> { let base_dir = PathBuf::from(game_dir); let game_path = base_dir.join(game_id); if !game_path.exists() { - eyre::bail!("Game directory does not exist: {}", game_path.display()); + return Err(PeerError::Other(eyre::eyre!( + "Game directory does not exist: {}", + game_path.display() + ))); } let mut file_descriptions = Vec::new(); @@ -1889,7 +1943,10 @@ async fn get_game_file_descriptions( Ok(metadata) => metadata.len(), Err(e) => { log::error!("Failed to read metadata for {relative_path}: {e}"); - eyre::bail!("Failed to read metadata for {relative_path}: {e}"); + return Err(PeerError::FileSizeDetermination { + path: relative_path.clone(), + source: e, + }); } } }; diff --git a/crates/lanspread-proto/src/lib.rs b/crates/lanspread-proto/src/lib.rs index 9ae1375..3e45192 100644 --- a/crates/lanspread-proto/src/lib.rs +++ b/crates/lanspread-proto/src/lib.rs @@ -31,6 +31,7 @@ pub enum Response { InvalidRequest(Bytes, String), EncodingError(String), DecodingError(Bytes, String), + InternalPeerError(String), } // Add Message trait