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
This commit is contained in:
t8y2
2026-05-11 00:18:09 +08:00
parent 741783445d
commit f456ddd979
13 changed files with 230 additions and 87 deletions
+2 -1
View File
@@ -128,7 +128,7 @@ const { getDatabaseOptions } = useDatabaseOptions();
const { openLineageTarget, openDatabaseSearchTarget, onStructureEditorSaved, openTableTarget } =
useNavigationTargets(dialogs);
const { onExecuteSql, onReloadData, onPaginate, onSort } = useDataGridActions(activeTab);
const { setupTauriListeners } = useTauriEvents({ openTableTarget });
const { setupTauriListeners, cleanupTauriListeners } = useTauriEvents({ openTableTarget });
const appVersion = ref("");
const isClassicLayout = computed(() => settingsStore.editorSettings.appLayout === "classic");
@@ -494,6 +494,7 @@ onMounted(async () => {
});
onUnmounted(() => {
cleanupTauriListeners();
window.removeEventListener("keydown", handleKeydown, true);
document.removeEventListener("contextmenu", handleContextMenu);
});