feat(redis): implement pagination for Redis key scanning and enhance UI for loading more keys
This commit is contained in:
1 parent
753b72ebe4
commit
5c546f68af
9 files changed
+137
-40
No files matched your search
@@ -2,7 +2,7 @@ use std::sync::Arc;
|
||||
use tauri::State;
|
||||
|
||||
use crate::commands::connection::{AppState, PoolKind};
|
||||
use crate::db::redis_driver::{self, RedisKeyInfo, RedisValue};
|
||||
use crate::db::redis_driver::{self, RedisScanResult, RedisValue};
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn redis_list_databases(
|
||||
@@ -25,16 +25,17 @@ pub async fn redis_scan_keys(
|
||||
state: State<'_, Arc<AppState>>,
|
||||
connection_id: String,
|
||||
db: u32,
|
||||
cursor: u64,
|
||||
pattern: String,
|
||||
count: usize,
|
||||
) -> Result<Vec<RedisKeyInfo>, String> {
|
||||
) -> Result<RedisScanResult, String> {
|
||||
let connections = state.connections.lock().await;
|
||||
let pool = connections.get(&connection_id).ok_or("Connection not found")?;
|
||||
match pool {
|
||||
PoolKind::Redis(con) => {
|
||||
let mut con = con.lock().await;
|
||||
redis_driver::select_db(&mut con, db).await?;
|
||||
redis_driver::scan_keys(&mut con, &pattern, count).await
|
||||
redis_driver::scan_keys_page(&mut con, cursor, &pattern, count).await
|
||||
}
|
||||
_ => Err("Not a Redis connection".to_string()),
|
||||
}
|
||||
|
||||
@@ -8,6 +8,12 @@ pub struct RedisKeyInfo {
|
||||
pub ttl: i64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct RedisScanResult {
|
||||
pub cursor: u64,
|
||||
pub keys: Vec<RedisKeyInfo>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct RedisValue {
|
||||
pub key: String,
|
||||
@@ -18,13 +24,20 @@ pub struct RedisValue {
|
||||
|
||||
pub async fn connect(url: &str) -> Result<redis::aio::MultiplexedConnection, String> {
|
||||
let client = redis::Client::open(url).map_err(|e| format!("Redis connection failed: {e}"))?;
|
||||
tokio::time::timeout(
|
||||
let mut con = tokio::time::timeout(
|
||||
std::time::Duration::from_secs(10),
|
||||
client.get_multiplexed_async_connection(),
|
||||
)
|
||||
.await
|
||||
.map_err(|_| "Redis connection timed out (10s)".to_string())?
|
||||
.map_err(|e| format!("Redis connection failed: {e}"))
|
||||
.map_err(|e| format!("Redis connection failed: {e}"))?;
|
||||
|
||||
redis::cmd("PING")
|
||||
.query_async::<String>(&mut con)
|
||||
.await
|
||||
.map_err(|e| format!("Redis authentication failed or command rejected: {e}"))?;
|
||||
|
||||
Ok(con)
|
||||
}
|
||||
|
||||
pub async fn list_databases(con: &mut redis::aio::MultiplexedConnection) -> Result<Vec<u32>, String> {
|
||||
@@ -58,33 +71,24 @@ pub async fn select_db(con: &mut redis::aio::MultiplexedConnection, db: u32) ->
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
pub async fn scan_keys(
|
||||
pub async fn scan_keys_page(
|
||||
con: &mut redis::aio::MultiplexedConnection,
|
||||
cursor: u64,
|
||||
pattern: &str,
|
||||
count: usize,
|
||||
) -> Result<Vec<RedisKeyInfo>, String> {
|
||||
let mut cursor: u64 = 0;
|
||||
let mut all_keys: Vec<String> = Vec::new();
|
||||
loop {
|
||||
let (new_cursor, keys): (u64, Vec<String>) = redis::cmd("SCAN")
|
||||
.arg(cursor)
|
||||
.arg("MATCH")
|
||||
.arg(pattern)
|
||||
.arg("COUNT")
|
||||
.arg(100)
|
||||
.query_async(con)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
all_keys.extend(keys);
|
||||
cursor = new_cursor;
|
||||
if cursor == 0 || all_keys.len() >= count {
|
||||
break;
|
||||
}
|
||||
}
|
||||
all_keys.truncate(count);
|
||||
) -> Result<RedisScanResult, String> {
|
||||
let (next_cursor, keys): (u64, Vec<String>) = redis::cmd("SCAN")
|
||||
.arg(cursor)
|
||||
.arg("MATCH")
|
||||
.arg(pattern)
|
||||
.arg("COUNT")
|
||||
.arg(count)
|
||||
.query_async(con)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
let mut result = Vec::new();
|
||||
for key in &all_keys {
|
||||
for key in &keys {
|
||||
let key_type: String = redis::cmd("TYPE")
|
||||
.arg(key.as_str())
|
||||
.query_async(con)
|
||||
@@ -99,7 +103,10 @@ pub async fn scan_keys(
|
||||
ttl,
|
||||
});
|
||||
}
|
||||
Ok(result)
|
||||
Ok(RedisScanResult {
|
||||
cursor: next_cursor,
|
||||
keys: result,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn get_value(
|
||||
|
||||
Reference in new issue
Block a user