Merge pull request #1586 from onceMisery/feat/opt-connections

fix: handle connection loss state for new queries
This commit is contained in:
skyler authored and GitHub committed 2026-06-22 22:32:02 +08:00
commit ee29694776
14 files changed
+280 -56

No files matched your search

@@ -49,6 +49,7 @@ describe("connectionStore MQ sidebar tree", () => {
vi.doMock("@/lib/tauriRuntime", () => ({ isTauriRuntime: () => false }));
vi.doMock("@/lib/api", () => ({
checkConnectionHealth: vi.fn().mockResolvedValue(undefined),
deleteSchemaCachePrefix: vi.fn().mockResolvedValue(undefined),
listDatabases: vi.fn().mockResolvedValue([]),
loadSchemaCache: vi.fn().mockResolvedValue(null),
+28 -4
View File
@@ -260,11 +260,23 @@ export const useConnectionStore = defineStore("connection", () => {
return message;
}
function recordMetadataLoadError(connectionId: string, error: unknown) {
function markConnectionLost(connectionId: string, error: unknown) {
connectedIds.value.delete(connectionId);
if (activeConnectionId.value === connectionId) activeConnectionId.value = null;
recordConnectionError(connectionId, error);
}
function recordConnectionLostError(connectionId: string, error: unknown): boolean {
if (shouldMarkDisconnected(error)) {
connectedIds.value.delete(connectionId);
if (activeConnectionId.value === connectionId) activeConnectionId.value = null;
markConnectionLost(connectionId, error);
return true;
}
return false;
}
// Metadata loaders keep this internal: match connection-loss errors before recording generic errors.
function recordMetadataLoadError(connectionId: string, error: unknown) {
if (recordConnectionLostError(connectionId, error)) return;
recordConnectionError(connectionId, error);
}
@@ -902,7 +914,17 @@ export const useConnectionStore = defineStore("connection", () => {
}
async function ensureConnected(connectionId: string) {
if (connectedIds.value.has(connectionId)) return;
if (connectedIds.value.has(connectionId)) {
// Optimistic: verify backend pool is actually healthy
try {
await api.checkConnectionHealth(connectionId);
return;
} catch {
// Backend pool is dead — remove from connectedIds and reconnect
connectedIds.value.delete(connectionId);
if (activeConnectionId.value === connectionId) activeConnectionId.value = null;
}
}
let config = getConfig(connectionId);
if (!config) {
await initFromDisk();
@@ -3039,6 +3061,8 @@ export const useConnectionStore = defineStore("connection", () => {
setConnectionError,
clearConnectionError,
recordConnectionError,
markConnectionLost,
recordConnectionLostError,
sidebarLayout,
getConfig,
isTreeNodePinned,
+8 -1
View File
@@ -1684,6 +1684,8 @@ export const useQueryStore = defineStore("query", () => {
}
} catch (e: any) {
console.error("[DBX][executeTabSql:error]", { traceId, elapsed: elapsed(), error: e });
// Sync connection state if the error indicates a lost connection
useConnectionStore().recordConnectionLostError(tab.connectionId, e);
const current = tabs.value.find((t) => t.id === id);
if (current?.executionId === executionId) {
current.result = toErrorResult(e);
@@ -1836,6 +1838,8 @@ export const useQueryStore = defineStore("query", () => {
}
return canceled;
} catch (e: any) {
// Sync connection state if the error indicates a lost connection
if (tab) useConnectionStore().recordConnectionLostError(tab.connectionId, e);
const current = tabs.value.find((t) => t.id === id);
if (current && current.executionId === executionId) {
current.isCancelling = false;
@@ -1882,12 +1886,15 @@ export const useQueryStore = defineStore("query", () => {
function notifyConnectionMayBeLost() {
const stuck = tabs.value.filter((t) => t.isExecuting);
if (stuck.length > 0) {
const connStore = useConnectionStore();
stuck.forEach((tab) => {
tab.isExecuting = false;
tab.isCancelling = false;
tab.queryExecutionStartedAt = undefined;
tab.executionId = undefined;
tab.result = toErrorResult(new Error(t("editor.connectionMayBeLost")));
const error = new Error(t("editor.connectionMayBeLost"));
tab.result = toErrorResult(error);
connStore.markConnectionLost(tab.connectionId, error);
});
}
}