From 62091741cffeba716d8c746ce604a7d8805d8a9b Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Thu, 30 Jul 2020 22:49:51 +0100 Subject: [PATCH] infallible piece update --- src/api.rs | 7 ++++--- src/cmdlistener.rs | 8 ++++---- src/updates.rs | 34 ++++++++++++++++++++++++++++------ 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/api.rs b/src/api.rs index 295a5e7b..a0c294e9 100644 --- a/src/api.rs +++ b/src/api.rs @@ -17,7 +17,7 @@ trait ApiPieceOp : Debug { -> (PieceUpdateOp<()>, Vec); } -pub trait Lens { +pub trait Lens : Debug { fn pieceid2visible(&self, piece: PieceId) -> VisiblePieceId; fn log_pri(&self, piece: PieceId, pc: &PieceState) -> PieceRenderInstructions; @@ -27,6 +27,7 @@ pub trait Lens { fn decode_visible_pieceid(&self, vpiece: VisiblePieceId, player: PlayerId) -> PieceId; } +#[derive(Debug)] pub struct TransparentLens { // when lenses become nontrivial, make this nonconstructable // to find all the places where a TransparentLens was bodged @@ -95,8 +96,8 @@ fn api_piece_op(form : Json>) let mut buf = PrepareUpdatesBuffer::new(g, Some((client, form.cseq)), Some(1 + logents.len())); - buf.piece_update(piece, update, &lens)?; - buf.log_updates(logents)?; + buf.piece_update(piece, update, &lens); + buf.log_updates(logents); eprintln!("API {:?} OK", &form); } diff --git a/src/cmdlistener.rs b/src/cmdlistener.rs index 7a31ff57..d2082926 100644 --- a/src/cmdlistener.rs +++ b/src/cmdlistener.rs @@ -316,9 +316,9 @@ impl UpdateHandler { let mut buf = PrepareUpdatesBuffer::new(g, None, Some(estimate)); for (upiece, uuop) in upieces { let lens = TransparentLens { }; - buf.piece_update(upiece, uuop, &lens)?; + buf.piece_update(upiece, uuop, &lens); } - buf.log_updates(ulogs)?; + buf.log_updates(ulogs); }, } } @@ -331,13 +331,13 @@ impl UpdateHandler { let mut buf = PrepareUpdatesBuffer::new(g, None, None); for (upiece, uuop) in bulk.pieces { let lens = TransparentLens { }; - buf.piece_update(upiece, uuop, &lens)?; + buf.piece_update(upiece, uuop, &lens); } buf.log_updates(vec![LogEntry { html: "The facilitator (re)configured the game".to_owned(), // xxx use cs.desc - }])?; + }]); }, Online => { }, } diff --git a/src/updates.rs b/src/updates.rs index c157b550..a5f4070f 100644 --- a/src/updates.rs +++ b/src/updates.rs @@ -33,6 +33,7 @@ pub enum PreparedUpdateEntry { op : PieceUpdateOp, }, Log (Arc), + RenderingError, } #[derive(Debug,Serialize)] @@ -75,6 +76,7 @@ enum TransmitUpdateEntry<'u> { op : &'u PieceUpdateOp, }, Log (&'u LogEntry), + ServerUpdateGenerationError, } // ========== implementation ========== @@ -105,6 +107,9 @@ impl PreparedUpdateEntry { Log(logent) => { logent.html.as_bytes().len() * 3 } + RenderingError => { + 100 + } } } } @@ -180,11 +185,12 @@ impl<'r> PrepareUpdatesBuffer<'r> { } #[throws(SVGProcessingError)] - pub fn piece_update(&mut self, piece: PieceId, update: PieceUpdateOp<()>, - lens: &dyn Lens) { + fn piece_update_fallible(&mut self, piece: PieceId, + update: PieceUpdateOp<()>, + lens: &dyn Lens) -> PreparedUpdateEntry { let gs = &mut self.g.gs; - // xxx check pos is within range, everywhere + // xxx enforce pos is within range, everywhere let (update, piece) = match gs.pieces.byid_mut(piece) { Ok(pc) => { @@ -217,15 +223,28 @@ impl<'r> PrepareUpdatesBuffer<'r> { } }; - self.us.push(PreparedUpdateEntry::Piece { + PreparedUpdateEntry::Piece { piece, client : self.by_client, sameclient_cseq : self.cseq, op : update, - }); + } + } + + pub fn piece_update(&mut self, piece: PieceId, update: PieceUpdateOp<()>, + lens: &dyn Lens) { + // Caller needs us to be infallible since it is too late by + // this point to back out a game state change. + + let update = self.piece_update_fallible(piece, update, lens) + .unwrap_or_else(|e| { + eprintln!("piece update error! piece={:?} lens={:?} error={:?}", + piece, &lens, &e); + PreparedUpdateEntry::RenderingError + }); + self.us.push(update); } - #[throws(SVGProcessingError)] pub fn log_updates(&mut self, logents: Vec) { for logentry in logents { let logentry = Arc::new(logentry); @@ -270,6 +289,9 @@ impl PreparedUpdate { PreparedUpdateEntry::Log(logent) => { TransmitUpdateEntry::Log(&logent) }, + PreparedUpdateEntry::RenderingError => { + TransmitUpdateEntry::ServerUpdateGenerationError + } }; ents.push(ue); }; -- 2.30.2