chiark / gitweb /
piece state in piece update error
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 3 Sep 2020 20:09:04 +0000 (21:09 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 3 Sep 2020 20:09:04 +0000 (21:09 +0100)
src/api.rs
src/error.rs
src/http.rs
src/updates.rs

index e8ece7ec018724a65b5012007132c257652704d3..1ae3f709eb9b34ac1c7e668fa584ef949f1bb883 100644 (file)
@@ -80,7 +80,8 @@ fn api_piece_op<O: ApiPieceOp>(form : Json<ApiPiece<O>>)
   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) => {
index c945df312170ed834ddb232a578e92fe3996142d..452cecf058cc4f3ed30c4f5e441b31bb95c89f8a 100644 (file)
@@ -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<InternalError> 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<T> IdForById for T where T : AccessId {
 }
 
 impl IdForById for PieceId {
-  type Error = PieceOpError;
-  const ERROR : PieceOpError = PieceOpError::Gone;
+  type Error = ();
+  const ERROR : () = ();
 }
 
 #[macro_export]
index 494bae62ef82cb46de4155b0bd1b088eb96068f4..3b996521e74de2f2667e315e87ae67f25907e3ca 100644 (file)
@@ -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();
index 7f0114dc15ce25c833af9758da6090be96b03b45..479cc379fcbbefc64a3654e9efc541c5dff15ab7 100644 (file)
@@ -48,7 +48,7 @@ pub enum PreparedUpdateEntry {
   Error (Option<ClientId> /* 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)
         }
       };