From 772727b0ef7d63144bf629d774f8b6c1c996bf78 Mon Sep 17 00:00:00 2001 From: salmonik Date: Thu, 29 Oct 2026 21:36:26 +0100 Subject: v2.3.1: settle orphaned reservations on server restart --- src/server/core.rs | 52 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 7 deletions(-) (limited to 'src/server/core.rs') diff --git a/src/server/core.rs b/src/server/core.rs index d4c95f6..e0f0ff2 100644 --- a/src/server/core.rs +++ b/src/server/core.rs @@ -17,6 +17,17 @@ pub struct ConnectionState { user: Option, } +/// Settle reservations left behind by a previous process. +/// +/// Call this **once at server startup, before accepting connections**. A +/// per-connection sweep would be wrong: it would settle another player's live +/// hand. Only one process may own the database. +pub fn recover_orphaned_reservations(db_path: &str) -> rusqlite::Result { + let mut conn = Connection::open(db_path)?; + database::init_db(&conn); + database::abandon_pending(&mut conn) +} + impl ConnectionState { pub fn user(&self) -> Option<&str> { self.user.as_deref() @@ -269,13 +280,23 @@ impl ServerCore { if balance < bet { return "ERROR Insufficient balance".to_string(); } - let balance = match database::debit(&mut self.conn, user, bet) { - Ok(balance) => balance, - Err(_) => return "ERROR Insufficient balance".to_string(), - }; let hand = self.blackjack.deal(bet as u64); let session_id = self.create_blackjack_session(user, &hand); + let balance = match database::reserve_play( + &mut self.conn, + &session_id, + user, + "blackjack", + bet, + &hand.to_json(), + ) { + Ok(balance) => balance, + Err(_) => { + let _ = self.sessions.remove_session(&session_id); + return "ERROR Insufficient balance".to_string(); + } + }; self.blackjack_response(user, &session_id, hand, balance) } @@ -330,11 +351,21 @@ impl ServerCore { if hand.player.len() != 2 { return "ERROR Double is only allowed on the first two cards".to_string(); } - if database::debit(&mut self.conn, user, hand.base_bet as i64).is_err() { + if database::extend_reservation( + &mut self.conn, + session_id, + hand.base_bet as i64, + ) + .is_err() + { return "ERROR Insufficient balance".to_string(); } if let Err(error) = hand.double() { - let _ = database::credit(&mut self.conn, user, hand.base_bet as i64); + let _ = database::refund_reservation( + &mut self.conn, + session_id, + hand.base_bet as i64, + ); return format!("ERROR {error}"); } } @@ -456,7 +487,14 @@ impl ServerCore { .sessions .create_session(user, "crash".to_string(), game_state); - let balance = match database::debit(&mut self.conn, user, bet) { + let balance = match database::reserve_play( + &mut self.conn, + &session_id, + user, + "crash", + bet, + &round.to_json(), + ) { Ok(balance) => balance, Err(_) => { let _ = self.sessions.remove_session(&session_id); -- cgit v1.2.3