chiark / gitweb /
infallible piece update
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 30 Jul 2020 21:49:51 +0000 (22:49 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 30 Jul 2020 21:49:51 +0000 (22:49 +0100)
src/api.rs
src/cmdlistener.rs
src/updates.rs

index 295a5e7b6901e28cc9b8b2fe0f7ca7e21ee7e909..a0c294e96e60dcfcb3b42b90213bb98a73d664b7 100644 (file)
@@ -17,7 +17,7 @@ trait ApiPieceOp : Debug {
         -> (PieceUpdateOp<()>, Vec<LogEntry>);
 }
 
-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<O: ApiPieceOp>(form : Json<ApiPiece<O>>)
       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);
     }
index 7a31ff57926ac25a593e224e34d636fb425ddd5f..d2082926e8d5d039ad9dd7cd6ddedff2daa6c456 100644 (file)
@@ -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 => { },
     }
index c157b55005e0921cee89e5899d5e6b5ba21f50c9..a5f4070f36124aa5de67b36cbaa6a511ecc9cce2 100644 (file)
@@ -33,6 +33,7 @@ pub enum PreparedUpdateEntry {
     op : PieceUpdateOp<PreparedPieceState>,
   },
   Log (Arc<LogEntry>),
+  RenderingError,
 }
 
 #[derive(Debug,Serialize)]
@@ -75,6 +76,7 @@ enum TransmitUpdateEntry<'u> {
     op : &'u PieceUpdateOp<PreparedPieceState>,
   },
   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<LogEntry>) {
     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);
     };