fix: Use spawn_blocking for Redis cache connection to prevent freezing
All checks were successful
BotServer CI / build (push) Successful in 8m38s
All checks were successful
BotServer CI / build (push) Successful in 8m38s
The init_redis() function was using synchronous blocking calls (redis::Client::get_connection()) inside an async function, which blocked the entire tokio runtime and caused botserver to freeze. Changes: - Wrap Redis connection calls in tokio::task::spawn_blocking() - Runs blocking operations in separate thread pool - Prevents tokio runtime from freezing during cache connection This fixes the issue where botserver would hang indefinitely when connecting to Valkey/Redis cache. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
fc34461b2f
commit
cf7bd7ffa2
1 changed files with 46 additions and 37 deletions
|
|
@ -289,54 +289,63 @@ pub async fn init_redis() -> Option<Arc<redis::Client>> {
|
||||||
loop {
|
loop {
|
||||||
attempt += 1;
|
attempt += 1;
|
||||||
|
|
||||||
match redis::Client::open(cache_url.as_str()) {
|
// Use spawn_blocking to avoid freezing the tokio runtime
|
||||||
Ok(client) => {
|
let cache_url_clone = cache_url.clone();
|
||||||
// Verify the connection actually works
|
let result = tokio::task::spawn_blocking(move || {
|
||||||
match client.get_connection() {
|
match redis::Client::open(cache_url_clone.as_str()) {
|
||||||
Ok(mut conn) => {
|
Ok(client) => {
|
||||||
// Test with PING
|
// Verify the connection actually works
|
||||||
match redis::cmd("PING").query::<String>(&mut conn) {
|
match client.get_connection() {
|
||||||
Ok(response) if response == "PONG" => {
|
Ok(mut conn) => {
|
||||||
info!("Cache connection verified: PONG");
|
// Test with PING
|
||||||
return Some(Arc::new(client));
|
match redis::cmd("PING").query::<String>(&mut conn) {
|
||||||
}
|
Ok(response) if response == "PONG" => {
|
||||||
Ok(response) => {
|
log::info!("Cache connection verified: PONG");
|
||||||
warn!("Cache PING returned unexpected response: {}", response);
|
Ok(Some(Arc::new(client)))
|
||||||
return Some(Arc::new(client));
|
}
|
||||||
}
|
Ok(response) => {
|
||||||
Err(e) => {
|
log::warn!("Cache PING returned unexpected response: {}", response);
|
||||||
if attempt < max_attempts {
|
Ok(Some(Arc::new(client)))
|
||||||
info!("Cache PING failed (attempt {}/{}): {}. Retrying in 5s...", attempt, max_attempts, e);
|
}
|
||||||
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
|
Err(e) => {
|
||||||
continue;
|
Err(format!("Cache PING failed: {}", e))
|
||||||
} else {
|
|
||||||
warn!("Cache PING failed after {} attempts: {}. Cache functions will be disabled.", max_attempts, e);
|
|
||||||
warn!("Suggestions and other cache-dependent features will not work.");
|
|
||||||
return None;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
Err(e) => {
|
||||||
Err(e) => {
|
Err(format!("Failed to establish cache connection: {}", e))
|
||||||
if attempt < max_attempts {
|
|
||||||
info!("Failed to establish cache connection (attempt {}/{}): {}. Retrying in 5s...", attempt, max_attempts, e);
|
|
||||||
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
warn!("Failed to establish cache connection after {} attempts: {}. Cache functions will be disabled.", max_attempts, e);
|
|
||||||
warn!("Suggestions and other cache-dependent features will not work.");
|
|
||||||
return None;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(e) => {
|
||||||
|
Err(format!("Failed to create cache client: {}", e))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(Ok(Some(client))) => return Some(client),
|
||||||
|
Ok(Ok(None)) => return None,
|
||||||
|
Ok(Err(e)) => {
|
||||||
if attempt < max_attempts {
|
if attempt < max_attempts {
|
||||||
info!("Failed to create cache client (attempt {}/{}): {}. Retrying in 5s...", attempt, max_attempts, e);
|
info!("Cache connection attempt {}/{} failed: {}. Retrying in 5s...", attempt, max_attempts, e);
|
||||||
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
|
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
log::warn!("Failed to create cache client after {} attempts: {}. Cache functions will be disabled.", max_attempts, e);
|
warn!("Cache connection failed after {} attempts: {}. Cache functions will be disabled.", max_attempts, e);
|
||||||
|
warn!("Suggestions and other cache-dependent features will not work.");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
// spawn_blocking itself failed
|
||||||
|
if attempt < max_attempts {
|
||||||
|
info!("Cache connection attempt {}/{} failed with task error: {}. Retrying in 5s...", attempt, max_attempts, e);
|
||||||
|
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
warn!("Cache connection failed after {} attempts with task error: {}. Cache functions will be disabled.", max_attempts, e);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue