fix(query): recover expired manual transaction sessions

This commit is contained in:
t8y2 committed 2026-08-24 12:19:27 +08:00
1 parent 0047d79974
commit e03cc2d269
15 files changed
+252 -24

No files matched your search

+19 -2
View File
@@ -70,7 +70,7 @@ import { useSavedSqlStore } from "@/stores/savedSqlStore";
import { useExportTracker } from "@/composables/useExportTracker";
import { recordQueryCancellationLatency, resourceLifecycleDiagnostics } from "@/lib/diagnostics/resourceLifecycleDiagnostics";
import { appendDebugLog } from "@/lib/backend/debugLog";
import { BackendErrorException, formatError, normalizeBackendError, type BackendError } from "@/lib/backend/errorUtils";
import { BackendErrorException, formatError, isManualTransactionSessionExpired, normalizeBackendError, type BackendError } from "@/lib/backend/errorUtils";
import { createSavedSqlEditorPosition, initSavedSqlEditorPositions, restoreSavedSqlEditorPosition, saveSavedSqlEditorPosition } from "@/lib/app/savedSqlEditorPosition";
import { ensureSqlExtension } from "@/lib/savedSql/savedSqlFileName";
import { resolveSavedSqlExecutionTarget, savedSqlExecutionTargetFromTab, type SavedSqlExecutionTarget, type SavedSqlOpenTargetMode } from "@/lib/savedSql/savedSqlExecutionTarget";
@@ -5109,7 +5109,24 @@ export const useQueryStore = defineStore("query", () => {
}
queryExecutionLog("info", "execute-in-txn:invoke", { traceId, txnSessionId: tab.txnSessionId, elapsed: elapsed() });
executionDispatched = true;
executionPromise = api.executeInManualTransaction(tab.txnSessionId, sqlToExecute, executionDatabase, executionSchema, pageLimit ?? agentProtocolQueryResultMaxRows(queryResultMaxRows), useOracleLobPreview);
let manualTransactionRecoveryAttempted = false;
executionPromise = (async () => {
const txnSessionId = tab.txnSessionId;
if (!txnSessionId) throw new Error("Manual transaction session was not initialized");
try {
return await api.executeInManualTransaction(txnSessionId, sqlToExecute, executionDatabase, executionSchema, pageLimit ?? agentProtocolQueryResultMaxRows(queryResultMaxRows), useOracleLobPreview);
} catch (error) {
if (manualTransactionRecoveryAttempted || !isManualTransactionSessionExpired(error)) throw error;
manualTransactionRecoveryAttempted = true;
tab.txnSessionId = undefined;
tab.txnAutoRolledBack = true;
queryExecutionLog("info", "manual-txn:expired-recover", { traceId, elapsed: elapsed() });
const refreshedSessionId = await api.beginManualTransaction(executionConnectionId, executionDatabase, executionSchema, executionCatalog);
tab.txnSessionId = refreshedSessionId;
queryExecutionLog("info", "manual-txn:restarted", { traceId, txnSessionId: refreshedSessionId, elapsed: elapsed() });
return api.executeInManualTransaction(refreshedSessionId, sqlToExecute, executionDatabase, executionSchema, pageLimit ?? agentProtocolQueryResultMaxRows(queryResultMaxRows), useOracleLobPreview);
}
})();
} else {
queryExecutionLog("info", "execute-multi:start", { traceId, elapsed: elapsed() });
// Query and data tabs use a tab-scoped pool so repeated executions keep