]> git.seodisparate.com - EN605.607.81.SP22_ASDM_Project/commitdiff
back_end refactorings
authorStephen Seo <seo.disparate@gmail.com>
Wed, 20 Apr 2022 03:21:02 +0000 (12:21 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Wed, 20 Apr 2022 05:14:03 +0000 (14:14 +0900)
Have back_end cleanup stale players/games on an interval, not every
iteration of its loop.

Replace usage of recursion in db_handler.rs .

back_end/Cargo.lock
back_end/Cargo.toml
back_end/src/db_handler.rs
front_end/src/constants.rs

index c5d4c5016daf94cd6e31c251e0d68e56a1022cac..43badf227d6afeed071fe70f3d156ae3a2d8e729 100644 (file)
@@ -154,7 +154,7 @@ dependencies = [
 
 [[package]]
 name = "four_line_dropper_backend"
-version = "0.1.0"
+version = "0.1.1"
 dependencies = [
  "bytes",
  "futures",
index 64b2d70f79ecfae7e181c9c07a54bb0231e729ba..cfcef057aa27b174dad83bd9e6b240bd7e3d0129 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "four_line_dropper_backend"
-version = "0.1.0"
+version = "0.1.1"
 edition = "2021"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
index 534239f843b242f1506e707803420c113131eb19..2e912dfc87a1f781b8a31e4f6a3b16367d06c9c9 100644 (file)
@@ -8,12 +8,13 @@
 //You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
 use crate::ai::{get_ai_choice, AIDifficulty};
 use crate::constants::{
-    COLS, GAME_CLEANUP_TIMEOUT, PLAYER_CLEANUP_TIMEOUT, PLAYER_COUNT_LIMIT, ROWS, TURN_SECONDS,
+    BACKEND_CLEANUP_INTERVAL_SECONDS, COLS, GAME_CLEANUP_TIMEOUT, PLAYER_CLEANUP_TIMEOUT,
+    PLAYER_COUNT_LIMIT, ROWS, TURN_SECONDS,
 };
 use crate::state::{board_from_string, new_string_board, string_from_board, BoardState, Turn};
 
 use std::sync::mpsc::{Receiver, RecvTimeoutError, SyncSender};
-use std::time::Duration;
+use std::time::{Duration, Instant};
 use std::{fmt, thread};
 
 use rand::{thread_rng, Rng};
@@ -314,10 +315,13 @@ impl DBHandler {
     }
 
     fn create_new_player(&self, conn: Option<&Connection>) -> Result<u32, String> {
-        if conn.is_none() {
-            return self.create_new_player(Some(&self.get_conn(DBFirstRun::NotFirstRun)?));
-        }
-        let conn = conn.unwrap();
+        let mut _conn_result = Err(String::new());
+        let conn = if conn.is_none() {
+            _conn_result = self.get_conn(DBFirstRun::NotFirstRun);
+            _conn_result.as_ref().unwrap()
+        } else {
+            conn.unwrap()
+        };
 
         let row_result: Result<usize, _> =
             conn.query_row("SELECT count(id) FROM players;", [], |row| row.get(0));
@@ -358,10 +362,14 @@ impl DBHandler {
     }
 
     fn pair_up_players(&self, conn: Option<&Connection>) -> Result<(), String> {
-        if conn.is_none() {
-            return self.pair_up_players(Some(&self.get_conn(DBFirstRun::NotFirstRun)?));
-        }
-        let conn = conn.unwrap();
+        let mut _conn_result = Err(String::new());
+        let conn = if conn.is_none() {
+            _conn_result = self.get_conn(DBFirstRun::NotFirstRun);
+            _conn_result.as_ref().unwrap()
+        } else {
+            conn.unwrap()
+        };
+
         let mut to_pair: Option<u32> = None;
         let mut unpaired_players_stmt = conn
             .prepare("SELECT id FROM players WHERE game_id ISNULL ORDER BY date_added;")
@@ -388,10 +396,14 @@ impl DBHandler {
     }
 
     fn create_game(&self, conn: Option<&Connection>, players: &[u32; 2]) -> Result<u32, String> {
-        if conn.is_none() {
-            return self.create_game(Some(&self.get_conn(DBFirstRun::NotFirstRun)?), players);
-        }
-        let conn = conn.unwrap();
+        let mut _conn_result = Err(String::new());
+        let conn = if conn.is_none() {
+            _conn_result = self.get_conn(DBFirstRun::NotFirstRun);
+            _conn_result.as_ref().unwrap()
+        } else {
+            conn.unwrap()
+        };
+
         let mut game_id: u32 = thread_rng().gen();
         {
             let mut get_game_stmt = conn
@@ -435,13 +447,13 @@ impl DBHandler {
             }
         }
 
-        if conn.is_none() {
-            return self.check_if_player_is_paired(
-                Some(&self.get_conn(DBFirstRun::NotFirstRun)?),
-                player_id,
-            );
-        }
-        let conn = conn.unwrap();
+        let mut _conn_result = Err(String::new());
+        let conn = if conn.is_none() {
+            _conn_result = self.get_conn(DBFirstRun::NotFirstRun);
+            _conn_result.as_ref().unwrap()
+        } else {
+            conn.unwrap()
+        };
 
         let check_player_row = conn.query_row("SELECT games.cyan_player FROM players JOIN games where games.id = players.game_id AND players.id = ?;", [player_id], |row| row.get::<usize, u32>(0));
         if let Ok(cyan_player) = check_player_row {
@@ -478,11 +490,14 @@ impl DBHandler {
         conn: Option<&Connection>,
         player_id: u32,
     ) -> Result<bool, String> {
-        if conn.is_none() {
-            return self
-                .check_if_player_exists(Some(&self.get_conn(DBFirstRun::NotFirstRun)?), player_id);
-        }
-        let conn = conn.unwrap();
+        let mut _conn_result = Err(String::new());
+        let conn = if conn.is_none() {
+            _conn_result = self.get_conn(DBFirstRun::NotFirstRun);
+            _conn_result.as_ref().unwrap()
+        } else {
+            conn.unwrap()
+        };
+
         let check_player_row: Result<u32, _> =
             conn.query_row("SELECT id FROM players WHERE id = ?;", [player_id], |row| {
                 row.get(0)
@@ -499,13 +514,13 @@ impl DBHandler {
         conn: Option<&Connection>,
         player_id: u32,
     ) -> Result<bool, String> {
-        if conn.is_none() {
-            return self.check_if_player_in_game(
-                Some(&self.get_conn(DBFirstRun::NotFirstRun)?),
-                player_id,
-            );
-        }
-        let conn = conn.unwrap();
+        let mut _conn_result = Err(String::new());
+        let conn = if conn.is_none() {
+            _conn_result = self.get_conn(DBFirstRun::NotFirstRun);
+            _conn_result.as_ref().unwrap()
+        } else {
+            conn.unwrap()
+        };
 
         let check_player_game_row: Result<u32, _> = conn.query_row(
             "SELECT games.id FROM games JOIN players WHERE players.id = ? AND players.game_id NOTNULL AND players.game_id = games.id;",
@@ -523,10 +538,13 @@ impl DBHandler {
         conn: Option<&Connection>,
         player_id: u32,
     ) -> Result<BoardStateType, String> {
-        if conn.is_none() {
-            return self.get_board_state(Some(&self.get_conn(DBFirstRun::NotFirstRun)?), player_id);
-        }
-        let conn = conn.unwrap();
+        let mut _conn_result = Err(String::new());
+        let conn = if conn.is_none() {
+            _conn_result = self.get_conn(DBFirstRun::NotFirstRun);
+            _conn_result.as_ref().unwrap()
+        } else {
+            conn.unwrap()
+        };
 
         // TODO maybe handle "opponent_disconnected" case
         let row_result: Result<(String, i64, Option<u32>, Option<u32>), RusqliteError> = conn.query_row(
@@ -595,11 +613,13 @@ impl DBHandler {
     }
 
     fn disconnect_player(&self, conn: Option<&Connection>, player_id: u32) -> Result<(), String> {
-        if conn.is_none() {
-            return self
-                .disconnect_player(Some(&self.get_conn(DBFirstRun::NotFirstRun)?), player_id);
-        }
-        let conn = conn.unwrap();
+        let mut _conn_result = Err(String::new());
+        let conn = if conn.is_none() {
+            _conn_result = self.get_conn(DBFirstRun::NotFirstRun);
+            _conn_result.as_ref().unwrap()
+        } else {
+            conn.unwrap()
+        };
 
         let stmt_result = conn.execute("DELETE FROM players WHERE id = ?;", [player_id]);
         if let Ok(1) = stmt_result {
@@ -610,10 +630,13 @@ impl DBHandler {
     }
 
     fn clear_empty_games(&self, conn: Option<&Connection>) -> Result<(), String> {
-        if conn.is_none() {
-            return self.clear_empty_games(Some(&self.get_conn(DBFirstRun::NotFirstRun)?));
-        }
-        let conn = conn.unwrap();
+        let mut _conn_result = Err(String::new());
+        let conn = if conn.is_none() {
+            _conn_result = self.get_conn(DBFirstRun::NotFirstRun);
+            _conn_result.as_ref().unwrap()
+        } else {
+            conn.unwrap()
+        };
 
         // Only fails if no rows were removed, and that is not an issue
         conn.execute(
@@ -631,18 +654,13 @@ impl DBHandler {
         player_id: u32,
         pos: usize,
     ) -> PlaceResultType {
-        if conn.is_none() {
-            return self.place_token(
-                Some(
-                    &self
-                        .get_conn(DBFirstRun::NotFirstRun)
-                        .map_err(|_| DBPlaceError::InternalError)?,
-                ),
-                player_id,
-                pos,
-            );
-        }
-        let conn = conn.unwrap();
+        let mut _conn_result = Err(String::new());
+        let conn = if conn.is_none() {
+            _conn_result = self.get_conn(DBFirstRun::NotFirstRun);
+            _conn_result.as_ref().unwrap()
+        } else {
+            conn.unwrap()
+        };
 
         // check if player exists
         let player_exist_check_result = self.check_if_player_exists(Some(conn), player_id);
@@ -884,15 +902,13 @@ impl DBHandler {
             ));
         }
 
-        if conn.is_none() {
-            return self.have_ai_take_players_turn(
-                Some(&self.get_conn(DBFirstRun::NotFirstRun)?),
-                game_id,
-                status,
-                board_string,
-            );
-        }
-        let conn = conn.unwrap();
+        let mut _conn_result = Err(String::new());
+        let conn = if conn.is_none() {
+            _conn_result = self.get_conn(DBFirstRun::NotFirstRun);
+            _conn_result.as_ref().unwrap()
+        } else {
+            conn.unwrap()
+        };
 
         let is_cyan = status == 0;
         let board = board_from_string(board_string);
@@ -958,10 +974,13 @@ impl DBHandler {
     }
 
     fn cleanup_stale_games(&self, conn: Option<&Connection>) -> Result<(), String> {
-        if conn.is_none() {
-            return self.cleanup_stale_games(Some(&self.get_conn(DBFirstRun::NotFirstRun)?));
-        }
-        let conn = conn.unwrap();
+        let mut _conn_result = Err(String::new());
+        let conn = if conn.is_none() {
+            _conn_result = self.get_conn(DBFirstRun::NotFirstRun);
+            _conn_result.as_ref().unwrap()
+        } else {
+            conn.unwrap()
+        };
 
         conn.execute(
             "DELETE FROM games WHERE unixepoch() - unixepoch(date_added) > ?;",
@@ -973,10 +992,13 @@ impl DBHandler {
     }
 
     fn cleanup_stale_players(&self, conn: Option<&Connection>) -> Result<(), String> {
-        if conn.is_none() {
-            return self.cleanup_stale_players(Some(&self.get_conn(DBFirstRun::NotFirstRun)?));
-        }
-        let conn = conn.unwrap();
+        let mut _conn_result = Err(String::new());
+        let conn = if conn.is_none() {
+            _conn_result = self.get_conn(DBFirstRun::NotFirstRun);
+            _conn_result.as_ref().unwrap()
+        } else {
+            conn.unwrap()
+        };
 
         conn.execute(
             "DELETE FROM players WHERE unixepoch() - unixepoch(date_added) > ? AND game_id ISNULL;",
@@ -1007,6 +1029,8 @@ pub fn start_db_handler_thread(
             return;
         }
 
+        let mut cleanup_instant = Instant::now();
+        let cleanup_duration = Duration::from_secs(BACKEND_CLEANUP_INTERVAL_SECONDS);
         'outer: loop {
             if handler.handle_request() {
                 handler.shutdown_tx.send(()).ok();
@@ -1017,11 +1041,14 @@ pub fn start_db_handler_thread(
                 println!("{}", e);
             }
 
-            if let Err(e) = handler.cleanup_stale_games(None) {
-                println!("{}", e);
-            }
-            if let Err(e) = handler.cleanup_stale_players(None) {
-                println!("{}", e);
+            if cleanup_instant.elapsed() > cleanup_duration {
+                cleanup_instant = Instant::now();
+                if let Err(e) = handler.cleanup_stale_games(None) {
+                    println!("{}", e);
+                }
+                if let Err(e) = handler.cleanup_stale_players(None) {
+                    println!("{}", e);
+                }
             }
         }
     });
index e4eceb7c1fe16858634e3b8e85f5f3ac826a4718..1c082aa8608cf6b56015ef7a5b22ae182a8c24f5 100644 (file)
@@ -21,6 +21,7 @@ pub const GAME_CLEANUP_TIMEOUT: u64 = (TURN_SECONDS + 1) * ((ROWS * COLS) as u64
 pub const PLAYER_CLEANUP_TIMEOUT: u64 = 300;
 
 pub const BACKEND_TICK_DURATION_MILLIS: i32 = 500;
+pub const BACKEND_CLEANUP_INTERVAL_SECONDS: u64 = 120;
 
 // TODO: Change this to "https://asdm.seodisparate.com/api" when backend is installed
 #[cfg(debug_assertions)]