fix(browser): ensure connection before mount loads
This commit is contained in:
1 parent
ded6e002b5
commit
8094f4901d
9 files changed
+89
-9
No files matched your search
@@ -13,6 +13,7 @@ import ErrorBanner from "@/components/ui/ErrorBanner.vue";
|
||||
import DataGrid from "@/components/grid/DataGrid.vue";
|
||||
import QueryLoadingState from "@/components/common/QueryLoadingState.vue";
|
||||
import * as api from "@/lib/api";
|
||||
import { useConnectionStore } from "@/stores/connectionStore";
|
||||
import { clampSearchSplitWidth } from "@/lib/dataGridSearchSplit";
|
||||
import { documentViewerFontStyle } from "@/lib/documentViewerFontStyle";
|
||||
import { buildDocumentFilterCondition, combineDocumentFilterConditions, currentDocumentFilterJson, defaultDocumentFilterRule, documentFilterModeNeedsValue, documentFilterModeOptions, documentStoreProviderFor, type DocumentFilterMode, type DocumentFilterRule } from "@/lib/documentStoreProvider";
|
||||
@@ -28,6 +29,7 @@ import "splitpanes/dist/splitpanes.css";
|
||||
|
||||
const { t } = useI18n();
|
||||
const settingsStore = useSettingsStore();
|
||||
const connectionStore = useConnectionStore();
|
||||
|
||||
const props = defineProps<{
|
||||
connectionId: string;
|
||||
@@ -714,7 +716,14 @@ function highlightedJson(json: string): string {
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(load);
|
||||
onMounted(async () => {
|
||||
try {
|
||||
await connectionStore.ensureConnected(props.connectionId);
|
||||
} catch (e) {
|
||||
console.warn("[DBX] ensureConnected failed for", props.connectionId, e);
|
||||
}
|
||||
load();
|
||||
});
|
||||
onBeforeUnmount(() => {
|
||||
if (documentLoadExecutionId.value) void api.cancelQuery(documentLoadExecutionId.value);
|
||||
stopDocumentLoadingTimer();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive, ref, watch } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useConnectionStore } from "@/stores/connectionStore";
|
||||
import { ChevronDown, ChevronRight, FolderClosed, FolderOpen, KeyRound, Loader2, Plus, RefreshCw, Search, Trash2 } from "@lucide/vue";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
@@ -84,6 +85,7 @@ const props = withDefaults(
|
||||
|
||||
const { t } = useI18n();
|
||||
const { toast } = useToast();
|
||||
const connectionStore = useConnectionStore();
|
||||
const searchInputRef = ref<HTMLInputElement>();
|
||||
const prefix = ref("");
|
||||
const keys = ref<KvKeySummary[]>([]);
|
||||
@@ -539,7 +541,14 @@ function refresh(): boolean {
|
||||
|
||||
watch(
|
||||
() => props.connectionId,
|
||||
() => void loadKeys(true),
|
||||
async () => {
|
||||
try {
|
||||
await connectionStore.ensureConnected(props.connectionId);
|
||||
} catch {
|
||||
// Connection failed — loadKeys will show the error state
|
||||
}
|
||||
void loadKeys(true);
|
||||
},
|
||||
);
|
||||
|
||||
watch(
|
||||
@@ -552,7 +561,14 @@ watch(
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
onMounted(() => void loadKeys(true));
|
||||
onMounted(async () => {
|
||||
try {
|
||||
await connectionStore.ensureConnected(props.connectionId);
|
||||
} catch (e) {
|
||||
console.warn("[DBX] ensureConnected failed for", props.connectionId, e);
|
||||
}
|
||||
void loadKeys(true);
|
||||
});
|
||||
defineExpose({ focusSearch, refresh });
|
||||
</script>
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { formatError } from "@/lib/errorUtils";
|
||||
import { ref, computed, onMounted, watch } from "vue";
|
||||
import type { MqClusterInfo, TopicInfo } from "@/types/mq";
|
||||
import { mqTestConnection } from "@/lib/api";
|
||||
import { useConnectionStore } from "@/stores/connectionStore";
|
||||
import { mqClusterOptionsFromExtra } from "@/lib/mqTenantForm";
|
||||
import TenantsPanel from "./TenantsPanel.vue";
|
||||
import NamespacesPanel from "./NamespacesPanel.vue";
|
||||
@@ -21,6 +22,7 @@ interface Props {
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
const connectionStore = useConnectionStore();
|
||||
|
||||
type MqTab = "tenants" | "namespaces" | "topics" | "subscriptions" | "monitoring" | "clients" | "policies" | "permissions" | "raw";
|
||||
|
||||
@@ -168,7 +170,12 @@ watch(
|
||||
);
|
||||
|
||||
// Lifecycle
|
||||
onMounted(() => {
|
||||
onMounted(async () => {
|
||||
try {
|
||||
await connectionStore.ensureConnected(props.connectionId);
|
||||
} catch (e) {
|
||||
console.warn("[DBX] ensureConnected failed for", props.connectionId, e);
|
||||
}
|
||||
loadClusterInfo();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -13,6 +13,7 @@ import EditorSearchPanel from "@/components/editor/EditorSearchPanel.vue";
|
||||
import NacosConfigDiffDialog from "@/components/nacos/NacosConfigDiffDialog.vue";
|
||||
import NacosConfigHistoryDialog from "@/components/nacos/NacosConfigHistoryDialog.vue";
|
||||
import { useToast } from "@/composables/useToast";
|
||||
import { useConnectionStore } from "@/stores/connectionStore";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import * as api from "@/lib/api";
|
||||
import { buildNacosConfigDeleteConfirm, buildNacosConfigExportFileName, buildNacosConfigHistoryRollbackConfirm, buildNacosInstanceConfirm, createNacosSaveAsCopy, resolveNacosConfigCopyText } from "@/lib/nacosAdmin";
|
||||
@@ -39,6 +40,7 @@ type AdminTab = "configs" | "services";
|
||||
const { toast } = useToast();
|
||||
const { t } = useI18n();
|
||||
const settingsStore = useSettingsStore();
|
||||
const connectionStore = useConnectionStore();
|
||||
const { isDark } = useTheme();
|
||||
const activeTab = ref<AdminTab>("configs");
|
||||
const connectionInfo = ref<NacosConnectionInfo | null>(null);
|
||||
@@ -839,12 +841,22 @@ watch(
|
||||
originalConfigContent.value = "";
|
||||
destroyConfigEditor();
|
||||
selectedService.value = null;
|
||||
try {
|
||||
await connectionStore.ensureConnected(props.connectionId);
|
||||
} catch (e) {
|
||||
console.warn("[DBX] ensureConnected failed for", props.connectionId, e);
|
||||
}
|
||||
await loadInfo();
|
||||
await Promise.all([loadConfigsWithRetry(1), loadServicesWithRetry(1)]);
|
||||
},
|
||||
);
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
await connectionStore.ensureConnected(props.connectionId);
|
||||
} catch (e) {
|
||||
console.warn("[DBX] ensureConnected failed for", props.connectionId, e);
|
||||
}
|
||||
await loadInfo();
|
||||
await Promise.all([loadConfigsWithRetry(1), loadServicesWithRetry(1)]);
|
||||
});
|
||||
|
||||
@@ -1236,11 +1236,16 @@ onBeforeUnmount(() => {
|
||||
|
||||
watch(
|
||||
() => [props.connection.id, props.database, props.schema] as const,
|
||||
() => {
|
||||
async () => {
|
||||
selectedSchema.value = props.schema;
|
||||
userHasSelectedFilter.value = false;
|
||||
objectFilter.value = "all";
|
||||
clearTableSelection();
|
||||
try {
|
||||
await connectionStore.ensureConnected(props.connection.id);
|
||||
} catch (e) {
|
||||
console.warn("[DBX] ensureConnected failed for", props.connection.id, e);
|
||||
}
|
||||
void reload();
|
||||
},
|
||||
{ immediate: true },
|
||||
|
||||
@@ -255,6 +255,11 @@ watch(autoRefreshInterval, () => {
|
||||
// Lifecycle
|
||||
// ---------------------------------------------------------------------------
|
||||
onMounted(async () => {
|
||||
try {
|
||||
await connectionStore.ensureConnected(props.connectionId);
|
||||
} catch (e) {
|
||||
console.warn("[DBX] ensureConnected failed for", props.connectionId, e);
|
||||
}
|
||||
await fetchClusterNodes();
|
||||
await fetchInfo();
|
||||
});
|
||||
|
||||
@@ -921,12 +921,29 @@ function onCommandInputKeydown(event: KeyboardEvent) {
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
onMounted(async () => {
|
||||
resumeRedisBrowserBackgroundWork();
|
||||
try {
|
||||
await connectionStore.ensureConnected(props.connectionId);
|
||||
} catch (e) {
|
||||
console.warn("[DBX] ensureConnected failed for", props.connectionId, e);
|
||||
}
|
||||
void loadKeys();
|
||||
});
|
||||
|
||||
onActivated(resumeRedisBrowserBackgroundWork);
|
||||
onActivated(async () => {
|
||||
resumeRedisBrowserBackgroundWork();
|
||||
// Ensure the connection is still alive after reactivation (e.g. tab switch).
|
||||
// If keys failed to load previously (empty list), retry loading.
|
||||
try {
|
||||
await connectionStore.ensureConnected(props.connectionId);
|
||||
} catch (e) {
|
||||
console.warn("[DBX] ensureConnected failed for", props.connectionId, e);
|
||||
}
|
||||
if (flatKeys.value.length === 0 && !loading.value) {
|
||||
void loadKeys();
|
||||
}
|
||||
});
|
||||
|
||||
onDeactivated(pauseRedisBrowserBackgroundWork);
|
||||
|
||||
|
||||
@@ -59,9 +59,10 @@ const showClientColumns = computed(() => {
|
||||
onMounted(async () => {
|
||||
if (connectionMode.value === "cluster") {
|
||||
try {
|
||||
await connectionStore.ensureConnected(props.connectionId);
|
||||
nodes.value = await api.redisClusterMasterNodes(props.connectionId);
|
||||
} catch {
|
||||
// Silently fail — nodes list is best-effort
|
||||
} catch (e) {
|
||||
console.warn("[DBX] ensureConnected failed for", props.connectionId, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -494,30 +494,38 @@ async function toggle() {
|
||||
await connectionStore.loadDatabases(node.connectionId);
|
||||
}
|
||||
} else if (node.type === "redis-db" && node.connectionId && node.database) {
|
||||
await connectionStore.ensureConnected(node.connectionId);
|
||||
const tabTitle = `${connectionStore.getConfig(node.connectionId)?.name || "Redis"}:db${node.database}`;
|
||||
queryStore.createTab(node.connectionId, node.database, tabTitle, "redis");
|
||||
} else if (node.type === "mq-tenant" && node.connectionId) {
|
||||
await connectionStore.ensureConnected(node.connectionId);
|
||||
queryStore.openMqAdmin(node.connectionId, { tenant: node.mqTenant || node.label });
|
||||
} else if (node.type === "nacos-namespace" && node.connectionId) {
|
||||
await connectionStore.ensureConnected(node.connectionId);
|
||||
queryStore.openNacosAdmin(node.connectionId, { namespace: node.nacosNamespace || "", namespaceName: node.nacosNamespaceName || node.label });
|
||||
} else if (node.type === "etcd-root" && node.connectionId) {
|
||||
await connectionStore.ensureConnected(node.connectionId);
|
||||
const tabTitle = `${connectionStore.getConfig(node.connectionId)?.name || "etcd"}:keys`;
|
||||
queryStore.createTab(node.connectionId, "", tabTitle, "etcd");
|
||||
refreshActiveKvBrowserAfterOpen("etcd", node.connectionId);
|
||||
} else if (node.type === "zookeeper-root" && node.connectionId) {
|
||||
await connectionStore.ensureConnected(node.connectionId);
|
||||
const tabTitle = `${connectionStore.getConfig(node.connectionId)?.name || "ZooKeeper"}:keys`;
|
||||
queryStore.createTab(node.connectionId, "", tabTitle, "zookeeper");
|
||||
refreshActiveKvBrowserAfterOpen("zookeeper", node.connectionId);
|
||||
} else if (node.type === "user-admin" && node.connectionId) {
|
||||
await connectionStore.ensureConnected(node.connectionId);
|
||||
queryStore.openUserAdmin(node.connectionId);
|
||||
} else if (node.type === "mongo-db" && node.connectionId && node.database) {
|
||||
await connectionStore.loadMongoCollections(node.connectionId, node.database);
|
||||
} else if (node.type === "mongo-collection" && node.connectionId && node.database) {
|
||||
await connectionStore.loadTableGroups(node.connectionId, node.database, node.label, node.schema, node.id);
|
||||
} else if (node.type === "elasticsearch-index" && node.connectionId) {
|
||||
await connectionStore.ensureConnected(node.connectionId);
|
||||
const tab = queryStore.createTab(node.connectionId, node.database || "default", node.label, "mongo");
|
||||
queryStore.updateSql(tab, node.label);
|
||||
} else if (node.type === "vector-collection" && node.connectionId) {
|
||||
await connectionStore.ensureConnected(node.connectionId);
|
||||
const collectionRef = node.id.includes("__vector_collection:") ? node.id.split("__vector_collection:").pop() || node.label : node.label;
|
||||
const tab = queryStore.createTab(node.connectionId, node.database || "default", node.label, "vector");
|
||||
queryStore.updateSql(tab, collectionRef);
|
||||
|
||||
Reference in new issue
Block a user