Files
dbx/crates/dbx-core/src/query_cancel.rs
T
t8y2 f456ddd979 perf: full-stack performance and security hardening
Frontend performance:
- Debounce DataGrid search (150ms) and replace O(n) row wrapping with index array
- Replace QueryStore deep watcher with targeted field-level persistence snapshot
- Extract shared nodeConfig computed in TreeItem (eliminates 15x redundant getConfig calls)
- Clear tab result data on close to free memory
- Add LRU eviction for completion caches (50 entry cap)
- Replace savedSql version string join with numeric counter

Memory leak fixes:
- Store Tauri event unlisten handles and clean up on unmount
- Clean up DataGrid search timer on unmount

Backend security & resource management:
- Add 50MB request body size limit
- Reject file uploads >100MB and SQL files >200MB
- Clean up SSE channels after transfer/import completes
- Recover from poisoned mutex instead of panicking
- Delete temporary upload files after preview
- Validate SQL file paths to prevent directory traversal
2026-05-11 00:18:09 +08:00

81 lines
2.1 KiB
Rust

use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use tokio_util::sync::CancellationToken;
#[derive(Clone, Default)]
pub struct RunningQueries {
inner: Arc<Mutex<HashMap<String, CancellationToken>>>,
}
impl RunningQueries {
pub fn register(&self, execution_id: String) -> RegisteredQuery {
let token = CancellationToken::new();
self.inner.lock().unwrap_or_else(|e| e.into_inner()).insert(execution_id.clone(), token.clone());
RegisteredQuery { execution_id, token, running_queries: self.clone() }
}
pub fn cancel(&self, execution_id: &str) -> bool {
let token = self.inner.lock().unwrap_or_else(|e| e.into_inner()).get(execution_id).cloned();
if let Some(token) = token {
token.cancel();
true
} else {
false
}
}
#[cfg(test)]
pub fn has(&self, execution_id: &str) -> bool {
self.inner.lock().unwrap_or_else(|e| e.into_inner()).contains_key(execution_id)
}
fn remove(&self, execution_id: &str) {
self.inner.lock().unwrap_or_else(|e| e.into_inner()).remove(execution_id);
}
}
pub struct RegisteredQuery {
execution_id: String,
token: CancellationToken,
running_queries: RunningQueries,
}
impl RegisteredQuery {
pub fn token(&self) -> CancellationToken {
self.token.clone()
}
}
impl Drop for RegisteredQuery {
fn drop(&mut self) {
self.running_queries.remove(&self.execution_id);
}
}
#[cfg(test)]
mod tests {
use super::RunningQueries;
#[test]
fn cancel_marks_registered_query_as_cancelled() {
let running = RunningQueries::default();
let registered = running.register("exec-1".to_string());
assert!(running.cancel("exec-1"));
assert!(registered.token().is_cancelled());
}
#[test]
fn dropping_registration_removes_running_query() {
let running = RunningQueries::default();
let registered = running.register("exec-1".to_string());
assert!(running.has("exec-1"));
drop(registered);
assert!(!running.has("exec-1"));
}
}