From: Ian Jackson Date: Thu, 3 Sep 2020 20:09:04 +0000 (+0100) Subject: piece state in piece update error X-Git-Tag: otter-0.2.0~1030 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=99788452daa1ea625aa6f5596486314808fdbeab;p=otter.git piece state in piece update error --- diff --git a/src/api.rs b/src/api.rs index e8ece7ec..1ae3f709 100644 --- a/src/api.rs +++ b/src/api.rs @@ -80,7 +80,8 @@ fn api_piece_op(form : Json>) let piece = lens.decode_visible_pieceid(form.piece, player); match (||{ - let pc = gs.pieces.byid_mut(piece)?; + let pc = gs.pieces.byid_mut(piece) + .map_err(|()| OnlineError::PieceGone)?; let q_gen = form.gen; let u_gen = @@ -122,21 +123,20 @@ impl ApiPieceOpError { match self { ReportViaUpdate(poe) => { let gen = ig.gs.gen; - ig.updates.get_mut(player) - .ok_or(OE::NoPlayer)? - .push(Arc::new(PreparedUpdate { - gen, - us : vec![ PreparedUpdateEntry::Error( - Some(client), - ErrorSignaledViaUpdate::PieceOpError( - lens.pieceid2visible(piece), - poe, - ), - )], - })); - - let mut buf = PrepareUpdatesBuffer::new(ig, None, None); - buf.piece_update(piece, PieceUpdateOp::Modify(()), lens); + let pc = ig.gs.pieces.byid_mut(piece).map_err(|()| OE::PieceGone)?; + let pri = lens.svg_pri(piece,pc,player); + let state = pc.prep_piecestate(&pri)?; + let pl_updates = ig.updates.get_mut(player).ok_or(OE::NoPlayer)?; + let pue = PreparedUpdateEntry::Error( + Some(client), + ErrorSignaledViaUpdate::PieceOpError { + piece: pri.id, + error: poe, + state, + }, + ); + let update = PreparedUpdate { gen, us : vec![ pue ] }; + pl_updates.push(Arc::new(update)); }, ReportViaResponse(err) => { diff --git a/src/error.rs b/src/error.rs index c945df31..452cecf0 100644 --- a/src/error.rs +++ b/src/error.rs @@ -11,12 +11,14 @@ pub enum OnlineError { NoPlayer, #[error("invalid Z coordinate")] InvalidZCoord, - #[error("improper piece hold status for op (client should have known)")] - PieceHeld, #[error("Server operational problems - consult administrator: {0:?}")] ServerFailure(#[from] InternalError), #[error("JSON deserialisation error: {0:?}")] BadJSON(serde_json::Error), + #[error("referenced piece is gone (maybe race)")] + PieceGone, + #[error("improper piece hold status for op (maybe race)")] + PieceHeld, } from_instance_lock_error!{OnlineError} @@ -46,17 +48,20 @@ impl From for SpecError { } } -#[derive(Error,Debug,Serialize,Copy,Clone)] +#[derive(Error,Debug,Serialize,Clone)] pub enum ErrorSignaledViaUpdate { InternalError, PlayerRemoved, - PieceOpError(VisiblePieceId, PieceOpError), + PieceOpError { + piece: VisiblePieceId, + error: PieceOpError, + state: PreparedPieceState, + }, } display_as_debug!{ErrorSignaledViaUpdate} #[derive(Error,Debug,Serialize,Copy,Clone)] pub enum PieceOpError { - Gone, Conflict, PosOffTable, } @@ -128,8 +133,8 @@ impl IdForById for T where T : AccessId { } impl IdForById for PieceId { - type Error = PieceOpError; - const ERROR : PieceOpError = PieceOpError::Gone; + type Error = (); + const ERROR : () = (); } #[macro_export] diff --git a/src/http.rs b/src/http.rs index 494bae62..3b996521 100644 --- a/src/http.rs +++ b/src/http.rs @@ -15,8 +15,11 @@ impl<'r> Responder<'r> for OnlineError { use OnlineError::*; let status = match self { ServerFailure(_) => Status::InternalServerError, - NoClient | NoPlayer | GameBeingDestroyed => Status::NotFound, - InvalidZCoord | BadJSON(_) | OnlineError::PieceHeld + NoClient | NoPlayer | GameBeingDestroyed + => Status::NotFound, + OnlineError::PieceHeld | OnlineError::PieceGone + => Status::Conflict, + InvalidZCoord | BadJSON(_) => Status::BadRequest, }; let mut resp = Responder::respond_to(msg,req).unwrap(); diff --git a/src/updates.rs b/src/updates.rs index 7f0114dc..479cc379 100644 --- a/src/updates.rs +++ b/src/updates.rs @@ -48,7 +48,7 @@ pub enum PreparedUpdateEntry { Error (Option /* none: all */, ErrorSignaledViaUpdate), } -#[derive(Debug,Serialize)] +#[derive(Debug,Clone,Serialize)] pub struct PreparedPieceState { pub pos : Pos, pub svg : String, @@ -89,7 +89,7 @@ enum TransmitUpdateEntry<'u> { }, SetTableSize(Pos), Log (&'u LogEntry), - Error(ErrorSignaledViaUpdate), + Error(&'u ErrorSignaledViaUpdate), } // ========== implementation ========== @@ -240,12 +240,9 @@ impl<'r> PrepareUpdatesBuffer<'r> { (update, pri_for_all.id) }, - Err(PieceOpError::Gone) => { + Err(()) => { (PieceUpdateOp::Delete(), lens.pieceid2visible(piece)) } - Err(e) => { - panic!(format!("unexpected error {:?} from pices.byid_mut", &e)); - } }; PreparedUpdateEntry::Piece { @@ -325,8 +322,8 @@ eprintln!("FOR_TRANSMIT TO={:?} {:?}", dest, &u); &PreparedUpdateEntry::SetTableSize(size) => { TransmitUpdateEntry::SetTableSize(size) }, - &PreparedUpdateEntry::Error(c, e) => { - if let Some(c) = c { if c != dest { continue } } + PreparedUpdateEntry::Error(c, e) => { + if let Some(c) = c { if *c != dest { continue } } TransmitUpdateEntry::Error(e) } };