feat(redis): support MONITOR live command log

This commit is contained in:
zipg authored and GitHub committed 2026-09-10 19:23:18 +08:00
1 parent 7b7ed6f7b1
commit 77323715e7
25 files changed
+439 -7

No files matched your search

+57 -1
View File
@@ -13,6 +13,8 @@ use crate::state::WebState;
#[serde(rename_all = "camelCase")]
pub struct PubSubWsParams {
pub connection_id: String,
#[serde(default)]
monitor: bool,
}
pub async fn ws_handler(
@@ -21,7 +23,61 @@ pub async fn ws_handler(
State(state): State<Arc<WebState>>,
) -> impl IntoResponse {
let connection_id = params.connection_id;
ws.on_upgrade(move |socket| handle_pubsub_socket(socket, state, connection_id))
let owner = dbx_core::session_credentials::current_credential_owner();
ws.on_upgrade(move |socket| async move {
if params.monitor {
dbx_core::session_credentials::with_credential_owner(
owner,
handle_monitor_socket(socket, state, connection_id),
)
.await;
} else {
handle_pubsub_socket(socket, state, connection_id).await;
}
})
}
async fn handle_monitor_socket(mut socket: WebSocket, state: Arc<WebState>, connection_id: String) {
let monitor = tokio::select! {
result = dbx_core::redis_ops::redis_create_monitor_core(&state.app, &connection_id) => result,
_ = socket.recv() => return,
};
let monitor = match monitor {
Ok(monitor) => monitor,
Err(error) => {
let _ = socket.send(Message::Text(serde_json::json!({ "error": error }).to_string().into())).await;
return;
}
};
if socket.send(Message::Text(serde_json::json!({ "ready": true }).to_string().into())).await.is_err() {
return;
}
let mut messages = monitor.into_on_message::<String>();
let (mut sender, mut receiver) = socket.split();
loop {
tokio::select! {
incoming = receiver.next() => {
match incoming {
Some(Ok(Message::Ping(payload))) => {
if sender.send(Message::Pong(payload)).await.is_err() { break; }
}
Some(Ok(Message::Pong(_))) => {}
_ => break,
}
}
message = messages.next() => {
let Some(message) = message else {
let _ = sender.send(Message::Text(serde_json::json!({ "error": "Redis MONITOR connection closed" }).to_string().into())).await;
break;
};
let event = Message::Text(serde_json::json!({ "message": message }).to_string().into());
match tokio::time::timeout(std::time::Duration::from_secs(5), sender.send(event)).await {
Ok(Ok(())) => {}
_ => break,
}
}
}
}
}
async fn handle_pubsub_socket(socket: WebSocket, state: Arc<WebState>, connection_id: String) {