From 47df45ece9b0d4d0c0d22565c0c29b30ff24eaf2 Mon Sep 17 00:00:00 2001 From: "NG (Graham)" Date: Mon, 5 Jan 2026 20:34:53 -0500 Subject: [PATCH] Add more db stats to chat command --- rc_chat_room/src/main.rs | 2 ++ rc_chat_room/src/state/chat/config.rs | 8 ++++++-- rc_core/src/persist/user/common.rs | 14 ++++++++++++++ rc_core/src/persist/user/traits.rs | 1 + rc_database/src/wrapper.rs | 12 ++++++++++++ 5 files changed, 35 insertions(+), 2 deletions(-) diff --git a/rc_chat_room/src/main.rs b/rc_chat_room/src/main.rs index fc6c280..e6ffea0 100644 --- a/rc_chat_room/src/main.rs +++ b/rc_chat_room/src/main.rs @@ -20,6 +20,7 @@ pub type UserTy = std::sync::Arc; pub static START_TIMESTAMP_S: std::sync::atomic::AtomicI64 = std::sync::atomic::AtomicI64::new(0); pub static READY_DURATION_NS: std::sync::atomic::AtomicI64 = std::sync::atomic::AtomicI64::new(0); pub static ONLINE_USERS: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0); +pub static LOGINS: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0); #[tokio::main] async fn main() -> std::io::Result<()> { @@ -67,6 +68,7 @@ async fn process_socket(mut socket: net::TcpStream, address: std::net::SocketAdd return; } }; + LOGINS.fetch_add(1, std::sync::atomic::Ordering::SeqCst); ONLINE_USERS.store(chat.system().await.user_count() as u64 + 1, std::sync::atomic::Ordering::SeqCst); let (chann_tx, chann_rx) = tokio::sync::mpsc::unbounded_channel(); let user_state = std::sync::Arc::new(oj_rc_core::UserState::<()>::new(users, chann_tx.clone())); diff --git a/rc_chat_room/src/state/chat/config.rs b/rc_chat_room/src/state/chat/config.rs index d5019e4..dbc0848 100644 --- a/rc_chat_room/src/state/chat/config.rs +++ b/rc_chat_room/src/state/chat/config.rs @@ -171,9 +171,13 @@ impl BuiltIn { "db" | "database" => { let db_stats = format!("(chat db) {}", ctx.user.db_metrics().await); stats.push(db_stats); + let counters = ctx.user.db_counters().await; + for (key, val) in counters { + stats.push(format!("(db) {}: {}", key, val)); + } }, "perms" | "permission" | "permissions" => { - let com_stats = format!("(perms {}) mod:{} admin:{} dev:{} banned:{} royal:{}", + let com_stats = format!("(perms {}) mod:{} admin:{} dev:{} banned:{} r:{}", ctx.user.public_id(), ctx.user.is_mod(), ctx.user.is_admin(), @@ -245,7 +249,7 @@ impl BuiltIn { Self::System(s) => s.do_help(), Self::OnlineUsers => "Show total users online".to_owned(), Self::TotalUsers => "Show total users registered".to_owned(), - Self::Stats => "Show server metrics (db|perms)".to_owned(), + Self::Stats => "Show server metrics (db|perms|uptime|counts)".to_owned(), Self::Version => "Show chat server version information".to_owned(), Self::Help => "Display this message".to_owned(), } diff --git a/rc_core/src/persist/user/common.rs b/rc_core/src/persist/user/common.rs index 9e4e5de..b293868 100644 --- a/rc_core/src/persist/user/common.rs +++ b/rc_core/src/persist/user/common.rs @@ -1,5 +1,9 @@ use super::account_json::UserData; +fn u64_negative_on_err(result: Result) -> i64 { + result.map(|x| x as i64).unwrap_or(-1) +} + #[async_trait::async_trait] impl super::CommonUser for UserData { fn public_id(&self) -> &'_ str { @@ -34,10 +38,20 @@ impl super::CommonUser for UserData { self.db.metrics().await } + async fn db_counters(&self) -> Vec<(&'static str, i64)> { + let mut count_map = Vec::with_capacity(4); + count_map.push(("users", u64_negative_on_err(self.db.user_count().await))); + count_map.push(("garages", u64_negative_on_err(self.db.garage_count().await))); + count_map.push(("games", u64_negative_on_err(self.db.game_count().await))); + count_map + } + async fn currency(&self, ty: super::CurrencyType, op: super::CurrencyOp) -> Result { self.currency_op(ty, op).await.map_err(|e| polariton_server::operations::SimpleOpError::with_message( crate::data::error_codes::WebServicesError::DatabaseError as i16, format!("Currency operation failed for user {}: {}", self.account.id, e), )) } + + } diff --git a/rc_core/src/persist/user/traits.rs b/rc_core/src/persist/user/traits.rs index ddf606a..e646a32 100644 --- a/rc_core/src/persist/user/traits.rs +++ b/rc_core/src/persist/user/traits.rs @@ -417,6 +417,7 @@ pub trait CommonUser: Send + Sync { fn is_royal(&self) -> bool; fn is_banned(&self) -> bool; async fn db_metrics(&self) -> oj_rc_database::DatabaseMetrics; + async fn db_counters(&self) -> Vec<(&'static str, i64)>; async fn currency(&self, ty: CurrencyType, op: CurrencyOp) -> Result; } diff --git a/rc_database/src/wrapper.rs b/rc_database/src/wrapper.rs index 1e699bf..4c8ff14 100644 --- a/rc_database/src/wrapper.rs +++ b/rc_database/src/wrapper.rs @@ -168,6 +168,12 @@ impl Database { } } + pub async fn garage_count(&self) -> Result { + crate::schema::garage::Entity::find() + .count(&self.orm) + .await + } + pub async fn garage_max_slot_by_user_id(&self, user_id: i32) -> Result { let result = crate::schema::garage::Entity::find() .select_only() @@ -318,6 +324,12 @@ impl Database { entity.insert(&self.orm).await } + pub async fn game_count(&self) -> Result { + crate::schema::multiplayer_game::Entity::find() + .count(&self.orm) + .await + } + pub async fn game_by_guid(&self, game_guid: i64) -> Result, sea_orm::DbErr> { crate::schema::multiplayer_game::Entity::find() .filter(crate::schema::multiplayer_game::Column::Guid.eq(game_guid))