fix(zookeeper): handle large children responses safely

Closes #6200
This commit is contained in:
t8y2 committed 2026-08-14 15:08:02 +08:00
1 parent 9e730fac56
commit f29590b1c6
6 files changed
+149 -6

No files matched your search

@@ -250,6 +250,7 @@ const listRevision = ref<KvInt64 | null>(null);
const listFilteredByAcls = ref(false);
const loading = ref(false);
const loadingMore = ref(false);
const listError = ref("");
const expandedGroupIds = ref<Set<string>>(new Set());
const selectedKey = ref<string | null>(null);
const selectedKeyIdentity = ref<string | null>(null);
@@ -592,6 +593,7 @@ async function loadKeys(reset = true, options: LoadKeysOptions = {}) {
const keyIdentityToRestore = options.preserveSelection ? selectedKeyIdentity.value : null;
if (reset) {
loading.value = true;
listError.value = "";
continuation.value = null;
listRevision.value = null;
listFilteredByAcls.value = false;
@@ -620,6 +622,10 @@ async function loadKeys(reset = true, options: LoadKeysOptions = {}) {
clearSelectedKey();
}
}
} catch (error) {
if (reset && generation === keyLoadGeneration && props.connectionId === connectionId) {
listError.value = error instanceof Error ? error.message : String(error);
}
} finally {
if (generation === keyLoadGeneration && props.connectionId === connectionId) {
loading.value = false;
@@ -642,6 +648,7 @@ async function loadLazyRoot(reset = true, options: LoadKeysOptions = {}) {
};
const previousExpanded = new Set(expandedGroupIds.value);
loading.value = true;
listError.value = "";
loadingMore.value = false;
listFilteredByAcls.value = false;
if (!options.preserveSelection) {
@@ -695,6 +702,10 @@ async function loadLazyRoot(reset = true, options: LoadKeysOptions = {}) {
} else {
expandedGroupIds.value = focusedRootExpansion(rootPath);
}
} catch (error) {
if (lazyLoadContextValid(context)) {
listError.value = error instanceof Error ? error.message : String(error);
}
} finally {
if (lazyLoadContextValid(context)) loading.value = false;
}
@@ -1867,6 +1878,9 @@ defineExpose({
<Loader2 class="mr-2 h-4 w-4 animate-spin" />
{{ labels.loadingKeys }}
</div>
<div v-else-if="listError" class="flex h-full items-center justify-center px-4 text-center text-sm text-destructive">
{{ listError }}
</div>
<div v-else-if="visibleRows.length === 0" class="flex h-full items-center justify-center text-sm text-muted-foreground">
{{ labels.empty }}
</div>
@@ -40,6 +40,12 @@ describe("KvKeyBrowser search and split layout", () => {
expect(browserSource).toContain("keyLoadGeneration++;");
});
it("shows list request errors instead of the empty-state message", () => {
expect(browserSource).toContain('const listError = ref("");');
expect(browserSource.match(/listError\.value = error instanceof Error \? error\.message : String\(error\);/g)).toHaveLength(2);
expect(browserSource.indexOf('v-else-if="listError"')).toBeLessThan(browserSource.indexOf('v-else-if="visibleRows.length === 0"'));
});
it("highlights the matching search query only for the selected search result", () => {
expect(browserSource).toContain("interface KvSearchHighlight");
expect(browserSource).toMatch(/const activeSearchHighlight = computed\(\(\) => \(?props\.searchHighlight\?\.key === selectedKey\.value/);