Refactor TALK keyword to use try_send
Remove unnecessary async spawn in TALK handling and use `try_send` on the WebSocket channel. Acquire `response_channels` with `try_lock` and spawn an async task only when falling back to the web adapter. Clean up debug logs and add missing `env` import. Also delete an extra blank line in the announcement start script.
This commit is contained in:
parent
648e7f48f9
commit
1fdf76b530
2 changed files with 52 additions and 42 deletions
|
|
@ -2,6 +2,7 @@ use crate::shared::models::{BotResponse, UserSession};
|
|||
use crate::shared::state::AppState;
|
||||
use log::{debug, error, info};
|
||||
use rhai::{Dynamic, Engine, EvalAltResult};
|
||||
use std::env;
|
||||
use std::sync::Arc;
|
||||
use uuid::Uuid;
|
||||
|
||||
|
|
@ -66,60 +67,70 @@ pub fn talk_keyword(state: Arc<AppState>, user: UserSession, engine: &mut Engine
|
|||
|
||||
engine
|
||||
.register_custom_syntax(&["TALK", "$expr$"], true, move |context, inputs| {
|
||||
// Evaluate the expression that produces the message text.
|
||||
let message = context.eval_expression_tree(&inputs[0])?.to_string();
|
||||
|
||||
info!("TALK command executed: {}", message);
|
||||
debug!("TALK: Sending message: {}", message);
|
||||
|
||||
let state_for_spawn = Arc::clone(&state_clone);
|
||||
let user_clone_spawn = user_clone.clone();
|
||||
let message_clone = message.clone();
|
||||
// Build the bot response that will be sent back to the client.
|
||||
let bot_id = env::var("BOT_GUID").unwrap_or_else(|_| "default_bot".to_string());
|
||||
let response = BotResponse {
|
||||
bot_id,
|
||||
user_id: user_clone.user_id.to_string(),
|
||||
session_id: user_clone.id.to_string(),
|
||||
channel: "web".to_string(),
|
||||
content: message,
|
||||
message_type: 1,
|
||||
stream_token: None,
|
||||
is_complete: true,
|
||||
};
|
||||
|
||||
tokio::spawn(async move {
|
||||
debug!("TALK: Sending message via WebSocket: {}", message_clone);
|
||||
let user_id = user_clone.id.to_string();
|
||||
|
||||
let bot_id =
|
||||
std::env::var("BOT_GUID").unwrap_or_else(|_| "default_bot".to_string());
|
||||
|
||||
let response = BotResponse {
|
||||
bot_id: bot_id,
|
||||
user_id: user_clone_spawn.user_id.to_string(),
|
||||
session_id: user_clone_spawn.id.to_string(),
|
||||
channel: "web".to_string(),
|
||||
content: message_clone,
|
||||
message_type: 1,
|
||||
stream_token: None,
|
||||
is_complete: true,
|
||||
};
|
||||
|
||||
let response_channels = state_for_spawn.response_channels.lock().await;
|
||||
if let Some(tx) = response_channels.get(&user_clone_spawn.id.to_string()) {
|
||||
if let Err(e) = tx.send(response).await {
|
||||
error!("Failed to send TALK message via WebSocket: {}", e);
|
||||
// Try to acquire the lock on the response_channels map. The map is protected
|
||||
// by an async `tokio::sync::Mutex`, so we use `try_lock` to avoid awaiting
|
||||
// inside this non‑async closure.
|
||||
match state_clone.response_channels.try_lock() {
|
||||
Ok(mut response_channels) => {
|
||||
if let Some(tx) = response_channels.get(&user_id) {
|
||||
// Use `try_send` to avoid blocking the runtime.
|
||||
if let Err(e) = tx.try_send(response.clone()) {
|
||||
error!("Failed to send TALK message via WebSocket: {}", e);
|
||||
} else {
|
||||
debug!("TALK message sent successfully via WebSocket");
|
||||
}
|
||||
} else {
|
||||
debug!("TALK message sent successfully via WebSocket");
|
||||
}
|
||||
} else {
|
||||
debug!(
|
||||
"No WebSocket connection found for session {}, sending via web adapter",
|
||||
user_clone_spawn.id
|
||||
);
|
||||
|
||||
if let Err(e) = state_for_spawn
|
||||
.web_adapter
|
||||
.send_message_to_session(&user_clone_spawn.id.to_string(), response)
|
||||
.await
|
||||
{
|
||||
error!("Failed to send TALK message via web adapter: {}", e);
|
||||
} else {
|
||||
debug!("TALK message sent successfully via web adapter");
|
||||
debug!(
|
||||
"No WebSocket connection found for session {}, sending via web adapter",
|
||||
user_id
|
||||
);
|
||||
// The web adapter method is async (`send_message_to_session`), so we
|
||||
// spawn a detached task to perform the send without blocking.
|
||||
let web_adapter = Arc::clone(&state_clone.web_adapter);
|
||||
let resp_clone = response.clone();
|
||||
let sess_id = user_id.clone();
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = web_adapter
|
||||
.send_message_to_session(&sess_id, resp_clone)
|
||||
.await
|
||||
{
|
||||
error!("Failed to send TALK message via web adapter: {}", e);
|
||||
} else {
|
||||
debug!("TALK message sent successfully via web adapter");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
Err(_) => {
|
||||
error!("Failed to acquire lock on response_channels for TALK command");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Dynamic::UNIT)
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn set_user_keyword(state: Arc<AppState>, user: UserSession, engine: &mut Engine) {
|
||||
let state_clone = Arc::clone(&state);
|
||||
let user_clone = user.clone();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
TALK "Olá, pode me perguntar sobre qualquer coisa..."
|
||||
|
||||
let text = GET "default.gbdrive/default.pdf"
|
||||
let resume = LLM "Say Hello and present a a resume from " + text
|
||||
TALK resume
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue