优化消息渠道的实现代码
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use sea_orm::DatabaseConnection;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::task::JoinHandle;
|
||||
@@ -11,6 +13,40 @@ use crate::db::service::{app_metadata_service, chat_channel_message_log_service}
|
||||
const COMMAND_PREFIX_KEY: &str = "chat_command_prefix";
|
||||
const DEFAULT_COMMAND_PREFIX: &str = "/";
|
||||
const MESSAGE_LANGUAGE_KEY: &str = "chat_message_language";
|
||||
/// How often to refresh cached config from DB.
|
||||
const CONFIG_CACHE_TTL_SECS: u64 = 30;
|
||||
|
||||
struct CommandConfigCache {
|
||||
prefix: String,
|
||||
lang: Lang,
|
||||
last_refresh: Instant,
|
||||
}
|
||||
|
||||
impl CommandConfigCache {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
prefix: DEFAULT_COMMAND_PREFIX.to_string(),
|
||||
lang: Lang::default(),
|
||||
// Force refresh on first use
|
||||
last_refresh: Instant::now() - Duration::from_secs(CONFIG_CACHE_TTL_SECS + 1),
|
||||
}
|
||||
}
|
||||
|
||||
async fn refresh_if_needed(&mut self, db: &DatabaseConnection) {
|
||||
if self.last_refresh.elapsed() < Duration::from_secs(CONFIG_CACHE_TTL_SECS) {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Ok(Some(val)) = app_metadata_service::get_value(db, COMMAND_PREFIX_KEY).await {
|
||||
self.prefix = val;
|
||||
}
|
||||
if let Ok(Some(val)) = app_metadata_service::get_value(db, MESSAGE_LANGUAGE_KEY).await {
|
||||
self.lang = Lang::from_str_lossy(&val);
|
||||
}
|
||||
|
||||
self.last_refresh = Instant::now();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn spawn_command_dispatcher(
|
||||
mut command_rx: mpsc::Receiver<IncomingCommand>,
|
||||
@@ -18,6 +54,8 @@ pub fn spawn_command_dispatcher(
|
||||
db_conn: DatabaseConnection,
|
||||
) -> JoinHandle<()> {
|
||||
tokio::spawn(async move {
|
||||
let mut config = CommandConfigCache::new();
|
||||
|
||||
while let Some(cmd) = command_rx.recv().await {
|
||||
let text = cmd.command_text.trim();
|
||||
|
||||
@@ -33,15 +71,9 @@ pub fn spawn_command_dispatcher(
|
||||
)
|
||||
.await;
|
||||
|
||||
let prefix = app_metadata_service::get_value(&db_conn, COMMAND_PREFIX_KEY)
|
||||
.await
|
||||
.ok()
|
||||
.flatten()
|
||||
.unwrap_or_else(|| DEFAULT_COMMAND_PREFIX.to_string());
|
||||
config.refresh_if_needed(&db_conn).await;
|
||||
|
||||
let lang = load_lang(&db_conn).await;
|
||||
|
||||
let response = dispatch_command(text, &prefix, &db_conn, &manager, lang).await;
|
||||
let response = dispatch_command(text, &config.prefix, &db_conn, &manager, config.lang).await;
|
||||
|
||||
// Send response back via the same channel
|
||||
let send_result = manager.send_to_channel(cmd.channel_id, &response).await;
|
||||
@@ -70,15 +102,6 @@ pub fn spawn_command_dispatcher(
|
||||
})
|
||||
}
|
||||
|
||||
async fn load_lang(db: &DatabaseConnection) -> Lang {
|
||||
app_metadata_service::get_value(db, MESSAGE_LANGUAGE_KEY)
|
||||
.await
|
||||
.ok()
|
||||
.flatten()
|
||||
.map(|v| Lang::from_str_lossy(&v))
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
async fn dispatch_command(
|
||||
text: &str,
|
||||
prefix: &str,
|
||||
@@ -86,13 +109,12 @@ async fn dispatch_command(
|
||||
manager: &ChatChannelManager,
|
||||
lang: Lang,
|
||||
) -> super::types::RichMessage {
|
||||
// Check if text starts with the configured prefix
|
||||
if !text.starts_with(prefix) {
|
||||
return command_handlers::handle_help(prefix, lang);
|
||||
}
|
||||
// Strip prefix; if text doesn't start with it, show help
|
||||
let without_prefix = match text.strip_prefix(prefix) {
|
||||
Some(rest) => rest,
|
||||
None => return command_handlers::handle_help(prefix, lang),
|
||||
};
|
||||
|
||||
// Strip prefix and parse command + args
|
||||
let without_prefix = &text[prefix.len()..];
|
||||
let parts: Vec<&str> = without_prefix.splitn(2, ' ').collect();
|
||||
let command = parts[0].to_lowercase();
|
||||
let args = parts.get(1).map(|s| s.trim()).unwrap_or("");
|
||||
|
||||
Reference in New Issue
Block a user