feat(timeout): support global connection and query timeout settings
This commit is contained in:
26 files changed
+588
-29
No files matched your search
@@ -26,7 +26,7 @@ import { detachTunnelProfileLayer, tunnelProfileReferenceLayer, tunnelProfileSum
|
||||
import { applySshConfigHostAliasPrefill as prefillSshConfigHostAlias } from "@/lib/connection/sshConfigHosts";
|
||||
import { canPersistConnectionTestResult, connectionEditDraftSyncAction } from "./connectionEditDraftSync";
|
||||
import { REDIS_SCAN_PAGE_SIZE_DEFAULT, REDIS_SCAN_PAGE_SIZE_MIN, REDIS_SCAN_PAGE_SIZE_MAX, REDIS_SCAN_PAGE_SIZE_OPTIONS } from "@/lib/redis/redisKeyPattern";
|
||||
import { useSettingsStore } from "@/stores/settingsStore";
|
||||
import { normalizeGlobalConnectTimeoutSecs, normalizeGlobalQueryTimeoutSecs, useSettingsStore } from "@/stores/settingsStore";
|
||||
import { useToast } from "@/composables/useToast";
|
||||
import DatabaseIcon from "@/components/icons/DatabaseIcon.vue";
|
||||
import * as api from "@/lib/backend/api";
|
||||
@@ -184,6 +184,8 @@ type ConnectionTestState = ConnectionTestResult & { ok: boolean };
|
||||
const { t } = useI18n();
|
||||
const { toast } = useToast();
|
||||
const settingsStore = useSettingsStore();
|
||||
const editGlobalConnectTimeoutSecs = ref(settingsStore.editorSettings.globalConnectTimeoutSecs);
|
||||
const editGlobalQueryTimeoutSecs = ref(settingsStore.editorSettings.globalQueryTimeoutSecs);
|
||||
const open = defineModel<boolean>("open", { default: false });
|
||||
const isDesktop = isTauriRuntime();
|
||||
|
||||
@@ -271,8 +273,10 @@ const defaultForm = (): ConnectionForm => ({
|
||||
database: undefined,
|
||||
color: "",
|
||||
transport_layers: [],
|
||||
connect_timeout_secs: 10,
|
||||
query_timeout_secs: 30,
|
||||
connect_timeout_secs: settingsStore.editorSettings.globalConnectTimeoutSecs,
|
||||
connect_timeout_inherit: true,
|
||||
query_timeout_secs: settingsStore.editorSettings.globalQueryTimeoutSecs,
|
||||
query_timeout_inherit: true,
|
||||
idle_timeout_secs: 60,
|
||||
keepalive_interval_secs: 30,
|
||||
ssl: false,
|
||||
@@ -2291,6 +2295,8 @@ watch(
|
||||
([config, isOpen]) => {
|
||||
const syncAction = connectionEditDraftSyncAction(config?.id ?? null, isOpen, editingId.value);
|
||||
if (syncAction === "preserve") return;
|
||||
editGlobalConnectTimeoutSecs.value = settingsStore.editorSettings.globalConnectTimeoutSecs;
|
||||
editGlobalQueryTimeoutSecs.value = settingsStore.editorSettings.globalQueryTimeoutSecs;
|
||||
if (syncAction === "hydrate" && config) {
|
||||
clearSavedDatabaseInfo();
|
||||
const legacyConfig = config as LegacyConnectionConfig;
|
||||
@@ -2314,8 +2320,10 @@ watch(
|
||||
database: config.database,
|
||||
color: config.color || "",
|
||||
transport_layers: transportLayersForConfig(legacyConfig),
|
||||
connect_timeout_secs: config.connect_timeout_secs || 10,
|
||||
query_timeout_secs: config.query_timeout_secs ?? 30,
|
||||
connect_timeout_secs: config.connect_timeout_inherit === true ? settingsStore.editorSettings.globalConnectTimeoutSecs : config.connect_timeout_secs || 10,
|
||||
connect_timeout_inherit: config.connect_timeout_inherit === true,
|
||||
query_timeout_secs: config.query_timeout_inherit === true ? settingsStore.editorSettings.globalQueryTimeoutSecs : (config.query_timeout_secs ?? 30),
|
||||
query_timeout_inherit: config.query_timeout_inherit === true,
|
||||
idle_timeout_secs: config.idle_timeout_secs ?? 60,
|
||||
keepalive_interval_secs: config.keepalive_interval_secs ?? 30,
|
||||
ssl: config.ssl || false,
|
||||
@@ -3551,9 +3559,9 @@ function connectionConfigForSubmit(id: string, generatedName = ""): ConnectionCo
|
||||
config.connection_string = undefined;
|
||||
}
|
||||
const connectTimeout = Number(config.connect_timeout_secs);
|
||||
config.connect_timeout_secs = Number.isFinite(connectTimeout) && connectTimeout > 0 ? connectTimeout : 10;
|
||||
config.connect_timeout_secs = config.connect_timeout_inherit === true ? normalizeGlobalConnectTimeoutSecs(editGlobalConnectTimeoutSecs.value) : Number.isFinite(connectTimeout) && connectTimeout > 0 ? connectTimeout : 10;
|
||||
const queryTimeout = Number(config.query_timeout_secs);
|
||||
config.query_timeout_secs = Number.isFinite(queryTimeout) && queryTimeout >= 0 ? queryTimeout : 30;
|
||||
config.query_timeout_secs = config.query_timeout_inherit === true ? normalizeGlobalQueryTimeoutSecs(editGlobalQueryTimeoutSecs.value) : Number.isFinite(queryTimeout) && queryTimeout >= 0 ? queryTimeout : 30;
|
||||
const idleTimeout = Number(config.idle_timeout_secs);
|
||||
config.idle_timeout_secs = Number.isFinite(idleTimeout) && idleTimeout >= 0 ? idleTimeout : 60;
|
||||
const keepaliveInterval = Number(config.keepalive_interval_secs);
|
||||
@@ -4501,6 +4509,8 @@ function openJdbcDriverManagerFromError() {
|
||||
function resetForm() {
|
||||
editingId.value = null;
|
||||
form.value = defaultForm();
|
||||
editGlobalConnectTimeoutSecs.value = settingsStore.editorSettings.globalConnectTimeoutSecs;
|
||||
editGlobalQueryTimeoutSecs.value = settingsStore.editorSettings.globalQueryTimeoutSecs;
|
||||
selectedTransportLayerId.value = null;
|
||||
draggedTransportLayerId.value = null;
|
||||
selectedType.value = "mysql";
|
||||
@@ -4815,6 +4825,25 @@ function validateTransportLayers(config: LegacyConnectionConfig) {
|
||||
});
|
||||
}
|
||||
|
||||
async function persistGlobalTimeoutDrafts() {
|
||||
const nextConnect = normalizeGlobalConnectTimeoutSecs(editGlobalConnectTimeoutSecs.value);
|
||||
const nextQuery = normalizeGlobalQueryTimeoutSecs(editGlobalQueryTimeoutSecs.value);
|
||||
editGlobalConnectTimeoutSecs.value = nextConnect;
|
||||
editGlobalQueryTimeoutSecs.value = nextQuery;
|
||||
const connectChanged = nextConnect !== settingsStore.editorSettings.globalConnectTimeoutSecs;
|
||||
const queryChanged = nextQuery !== settingsStore.editorSettings.globalQueryTimeoutSecs;
|
||||
if (!connectChanged && !queryChanged) return;
|
||||
settingsStore.updateEditorSettings({
|
||||
globalConnectTimeoutSecs: nextConnect,
|
||||
globalQueryTimeoutSecs: nextQuery,
|
||||
});
|
||||
await settingsStore.persistEditorSettings();
|
||||
await store.applyGlobalTimeouts({
|
||||
connectTimeoutSecs: connectChanged ? nextConnect : undefined,
|
||||
queryTimeoutSecs: queryChanged ? nextQuery : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
async function save() {
|
||||
if (!ensureConnectionHostResolvedFromUrl()) return;
|
||||
if (isSaving.value) return;
|
||||
@@ -4825,12 +4854,14 @@ async function save() {
|
||||
const updated = withSavedDatabaseInfo(connectionConfigForSubmit(editingId.value), databaseInfoForSave);
|
||||
await ensureRequiredAgentDriverInstalled(updated);
|
||||
await ensureRequiredGaussdbMJdbcRuntime(updated);
|
||||
await persistGlobalTimeoutDrafts();
|
||||
await store.updateConnection(updated);
|
||||
store.stopEditing();
|
||||
} else {
|
||||
const config = withSavedDatabaseInfo(connectionConfigForSubmit(draftTestConnectionId.value), databaseInfoForSave);
|
||||
await ensureRequiredAgentDriverInstalled(config);
|
||||
await ensureRequiredGaussdbMJdbcRuntime(config);
|
||||
await persistGlobalTimeoutDrafts();
|
||||
await store.addConnection(config);
|
||||
draftTestConnectionId.value = uuid();
|
||||
if (config.db_type === "jdbc") {
|
||||
@@ -7402,11 +7433,33 @@ function openExternalUrl(url: string) {
|
||||
</div>
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label :class="connectionLabelSmallClass">{{ t("connection.connectTimeout") }}</Label>
|
||||
<Input v-model.number="form.connect_timeout_secs" type="number" min="1" max="300" step="1" class="col-span-3" />
|
||||
<div class="col-span-3 grid grid-cols-2 gap-2">
|
||||
<div class="grid min-w-0 grid-cols-[auto_minmax(0,1fr)] items-center gap-x-2 gap-y-1 rounded border px-2 py-1.5 sm:flex" :class="form.connect_timeout_inherit === true ? 'border-primary/60 bg-background' : 'border-border bg-muted/30 text-muted-foreground'">
|
||||
<input id="connect-timeout-global" v-model="form.connect_timeout_inherit" type="radio" name="connect-timeout-scope" :value="true" class="h-3.5 w-3.5 shrink-0 accent-primary" />
|
||||
<label for="connect-timeout-global" class="min-w-0 flex-1 cursor-pointer truncate text-xs" :title="t('connection.useGlobalQueryTimeout')">{{ t("connection.useGlobalQueryTimeout") }}</label>
|
||||
<Input v-model.number="editGlobalConnectTimeoutSecs" type="number" min="1" max="300" step="1" class="col-span-2 h-7 w-full shrink-0 sm:col-span-1 sm:w-20" :disabled="form.connect_timeout_inherit !== true" />
|
||||
</div>
|
||||
<div class="grid min-w-0 grid-cols-[auto_minmax(0,1fr)] items-center gap-x-2 gap-y-1 rounded border px-2 py-1.5 sm:flex" :class="form.connect_timeout_inherit !== true ? 'border-primary/60 bg-background' : 'border-border bg-muted/30 text-muted-foreground'">
|
||||
<input id="connect-timeout-connection" v-model="form.connect_timeout_inherit" type="radio" name="connect-timeout-scope" :value="false" class="h-3.5 w-3.5 shrink-0 accent-primary" />
|
||||
<label for="connect-timeout-connection" class="min-w-0 flex-1 cursor-pointer truncate text-xs" :title="t('connection.useConnectionQueryTimeout')">{{ t("connection.useConnectionQueryTimeout") }}</label>
|
||||
<Input v-model.number="form.connect_timeout_secs" type="number" min="1" max="300" step="1" class="col-span-2 h-7 w-full shrink-0 sm:col-span-1 sm:w-20" :disabled="form.connect_timeout_inherit === true" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label :class="connectionLabelSmallClass">{{ t("connection.queryTimeout") }}</Label>
|
||||
<Input v-model.number="form.query_timeout_secs" type="number" min="0" max="300" step="1" class="col-span-3" />
|
||||
<div class="col-span-3 grid grid-cols-2 gap-2">
|
||||
<div class="grid min-w-0 grid-cols-[auto_minmax(0,1fr)] items-center gap-x-2 gap-y-1 rounded border px-2 py-1.5 sm:flex" :class="form.query_timeout_inherit === true ? 'border-primary/60 bg-background' : 'border-border bg-muted/30 text-muted-foreground'">
|
||||
<input id="query-timeout-global" v-model="form.query_timeout_inherit" type="radio" name="query-timeout-scope" :value="true" class="h-3.5 w-3.5 shrink-0 accent-primary" />
|
||||
<label for="query-timeout-global" class="min-w-0 flex-1 cursor-pointer truncate text-xs" :title="t('connection.useGlobalQueryTimeout')">{{ t("connection.useGlobalQueryTimeout") }}</label>
|
||||
<Input v-model.number="editGlobalQueryTimeoutSecs" type="number" min="0" max="300" step="1" class="col-span-2 h-7 w-full shrink-0 sm:col-span-1 sm:w-20" :disabled="form.query_timeout_inherit !== true" />
|
||||
</div>
|
||||
<div class="grid min-w-0 grid-cols-[auto_minmax(0,1fr)] items-center gap-x-2 gap-y-1 rounded border px-2 py-1.5 sm:flex" :class="form.query_timeout_inherit !== true ? 'border-primary/60 bg-background' : 'border-border bg-muted/30 text-muted-foreground'">
|
||||
<input id="query-timeout-connection" v-model="form.query_timeout_inherit" type="radio" name="query-timeout-scope" :value="false" class="h-3.5 w-3.5 shrink-0 accent-primary" />
|
||||
<label for="query-timeout-connection" class="min-w-0 flex-1 cursor-pointer truncate text-xs" :title="t('connection.useConnectionQueryTimeout')">{{ t("connection.useConnectionQueryTimeout") }}</label>
|
||||
<Input v-model.number="form.query_timeout_secs" type="number" min="0" max="300" step="1" class="col-span-2 h-7 w-full shrink-0 sm:col-span-1 sm:w-20" :disabled="form.query_timeout_inherit === true" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="form.db_type === 'mongodb'" class="grid grid-cols-4 items-center gap-4">
|
||||
<Label :class="connectionLabelSmallClass">{{ t("connection.idleTimeout") }}</Label>
|
||||
|
||||
Reference in new issue
Block a user