mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-19 16:16:45 +00:00
fix(desktop): keep timeout inherit flags when saving plugin connections (#9579)
* fix(desktop): keep timeout inherit flags when saving plugin connections * fix(desktop): hide dead query timeout scope from plugin connections query_timeout_secs only feeds the database query pipeline (dataGrid, queryStore); plugin connections such as SSH never consume it, so the generic Advanced-tab radio only suggested a budget the provider cannot honor. Hide the row for plugin connections while keeping hydration and submit untouched, and pin the round-trip contract (explicit inherit flag, preserved scalar) plus the deliberate keep of the connect timeout radio in the regression spec. --------- Co-authored-by: jinpy.he <jinpy.he@kuehne-nagel.com>
This commit is contained in:
@@ -4118,6 +4118,13 @@ function connectionConfigForSubmit(id: string, generatedName = "", validatePlugi
|
||||
config.color = form.value.color;
|
||||
config.transport_layers = form.value.transport_layers || [];
|
||||
config.connect_timeout_secs = form.value.connect_timeout_secs;
|
||||
// buildPluginConnectionConfig rebuilds the config from scratch and drops
|
||||
// the timeout inherit flags, so mirror the Advanced-tab radio state the
|
||||
// same way the built-in branch keeps them via the form spread. Kept ahead
|
||||
// of the resolvedPluginConnectTimeout override below, which intentionally
|
||||
// forces connect inheritance off for providers declaring their own
|
||||
// handshake timeout field.
|
||||
config.connect_timeout_inherit = form.value.connect_timeout_inherit;
|
||||
if (resolvedPluginConnectTimeout !== undefined) {
|
||||
// A provider declaring its own connect_timeout_secs field makes it the
|
||||
// single source of truth (declared default or advanced-form value): the
|
||||
@@ -4129,6 +4136,7 @@ function connectionConfigForSubmit(id: string, generatedName = "", validatePlugi
|
||||
config.connect_timeout_inherit = false;
|
||||
}
|
||||
config.query_timeout_secs = form.value.query_timeout_secs;
|
||||
config.query_timeout_inherit = form.value.query_timeout_inherit;
|
||||
config.idle_timeout_secs = form.value.idle_timeout_secs;
|
||||
config.keepalive_interval_secs = form.value.keepalive_interval_secs;
|
||||
config.read_only = form.value.read_only;
|
||||
@@ -8987,7 +8995,11 @@ function openExternalUrl(url: string) {
|
||||
<p class="text-xs leading-5 text-muted-foreground">{{ t("connection.etcdGrpcMaxInboundHint") }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<!-- query_timeout_secs only feeds the database query pipeline
|
||||
(dataGrid/queryStore); plugin connections like SSH never
|
||||
consume it, so the generic radio would only suggest a
|
||||
budget the provider cannot honor. -->
|
||||
<div v-if="!isPluginConnection" class="grid grid-cols-4 items-center gap-4">
|
||||
<Label :class="connectionLabelSmallClass">{{ t("connection.queryTimeout") }}</Label>
|
||||
<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'">
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
const dialogSource = readFileSync(new URL("../../../components/connection/ConnectionDialog.vue", import.meta.url), "utf8");
|
||||
|
||||
describe("ConnectionDialog plugin connection timeout inheritance", () => {
|
||||
const submitFn = dialogSource.slice(dialogSource.indexOf("function connectionConfigForSubmit"));
|
||||
const pluginBranch = submitFn.slice(0, submitFn.indexOf("} else {"));
|
||||
|
||||
it("keeps the connect timeout inherit flag when submitting plugin connections", () => {
|
||||
// buildPluginConnectionConfig rebuilds the config from scratch and drops
|
||||
// the inherit flags; without this mirror the store normalizes the absent
|
||||
// flag back to the persisted scope and the Advanced-tab radio reverts.
|
||||
expect(pluginBranch).toContain("config.connect_timeout_inherit = form.value.connect_timeout_inherit;");
|
||||
});
|
||||
|
||||
it("keeps the query timeout inherit flag when submitting plugin connections", () => {
|
||||
expect(pluginBranch).toContain("config.query_timeout_inherit = form.value.query_timeout_inherit;");
|
||||
});
|
||||
|
||||
it("still forces connect inheritance off for providers declaring their own handshake timeout field", () => {
|
||||
// The resolvedPluginConnectTimeout override must run after the generic
|
||||
// mirror so a provider-declared connect_timeout_secs stays the single
|
||||
// source of truth and the host RPC deadline cannot inherit the global.
|
||||
const mirrorIndex = pluginBranch.indexOf("config.connect_timeout_inherit = form.value.connect_timeout_inherit;");
|
||||
const overrideIndex = pluginBranch.indexOf("config.connect_timeout_inherit = false;");
|
||||
expect(mirrorIndex).toBeGreaterThan(-1);
|
||||
expect(overrideIndex).toBeGreaterThan(mirrorIndex);
|
||||
});
|
||||
|
||||
it("keeps the per-connection timeout scalars when submitting plugin connections", () => {
|
||||
// Toggling back to "current connection" must preserve the typed value:
|
||||
// the store treats a stored scalar with inherit=false as a local override.
|
||||
expect(pluginBranch).toContain("config.query_timeout_secs = form.value.query_timeout_secs;");
|
||||
expect(pluginBranch).toContain("config.connect_timeout_secs = form.value.connect_timeout_secs;");
|
||||
});
|
||||
});
|
||||
|
||||
describe("ConnectionDialog plugin connection timeout scope UI", () => {
|
||||
const hydrateBlock = dialogSource.slice(dialogSource.indexOf("connect_timeout_inherit: config.connect_timeout_inherit === true"));
|
||||
const queryTimeoutRowStart = dialogSource.lastIndexOf("<div", dialogSource.indexOf('t("connection.queryTimeout")'));
|
||||
const connectTimeoutRowStart = dialogSource.lastIndexOf("<div", dialogSource.indexOf('t("connection.connectTimeout")'));
|
||||
|
||||
it("hydrates the global scope only from an explicit inherit flag", () => {
|
||||
// Round trip with the submit mirror above: only a stored `true` counts as
|
||||
// "global", so a preserved flag reopens as global and a preserved scalar
|
||||
// reopens as a local override.
|
||||
expect(hydrateBlock).toContain("query_timeout_inherit: config.query_timeout_inherit === true,");
|
||||
});
|
||||
|
||||
it("hides the generic query timeout radio from plugin connections", () => {
|
||||
// query_timeout_secs only feeds the database query pipeline, which plugin
|
||||
// connections (SSH, ...) never run, so the control would be dead weight.
|
||||
expect(dialogSource.slice(queryTimeoutRowStart, queryTimeoutRowStart + 220)).toContain('v-if="!isPluginConnection"');
|
||||
});
|
||||
|
||||
it("keeps the generic connect timeout radio visible for plugin connections", () => {
|
||||
// Deliberate scope cut: for providers without their own handshake timeout
|
||||
// field the connect radio is still effective, so it stays rendered.
|
||||
expect(dialogSource.slice(connectTimeoutRowStart, connectTimeoutRowStart + 220)).not.toContain('v-if="!isPluginConnection"');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user