feat(redis): limit the sidebar database list

This commit is contained in:
Melody Ruch authored and GitHub committed 2026-09-18 17:33:28 +08:00
1 parent 745c201f06
commit ec356293aa
18 files changed
+265 -22

No files matched your search

@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import { normalizeRedisDatabaseAliases, redisDatabaseAlias, redisDatabaseLabel } from "@/lib/redis/redisDatabaseAlias";
import { limitRedisDatabaseList, normalizeRedisDatabaseAliases, redisDatabaseAlias, redisDatabaseLabel, REDIS_DATABASE_DISPLAY_LIMIT_DEFAULT } from "@/lib/redis/redisDatabaseAlias";
describe("redisDatabaseAlias", () => {
it("normalizes numeric database keys and trims aliases", () => {
@@ -32,4 +32,22 @@ describe("redisDatabaseAlias", () => {
expect(redisDatabaseLabel(0, undefined, 0)).toBe("db0 (0)");
expect(redisDatabaseLabel(2, { "2": "cache" })).toBe("db2 · cache");
});
it("leaves the list untouched when it fits within the limit", () => {
const items = [1, 2, 3];
expect(limitRedisDatabaseList(items, 10)).toEqual({ visible: items, hasMore: false });
});
it("truncates and reports more items are available", () => {
const items = [1, 2, 3, 4, 5];
expect(limitRedisDatabaseList(items, 2)).toEqual({ visible: [1, 2], hasMore: true });
});
it("falls back to the default limit for missing or invalid values (#1236)", () => {
const items = Array.from({ length: REDIS_DATABASE_DISPLAY_LIMIT_DEFAULT + 1 }, (_, i) => i);
expect(limitRedisDatabaseList(items, undefined).hasMore).toBe(true);
expect(limitRedisDatabaseList(items, 0).hasMore).toBe(true);
expect(limitRedisDatabaseList(items, -5).hasMore).toBe(true);
expect(limitRedisDatabaseList(items.slice(0, REDIS_DATABASE_DISPLAY_LIMIT_DEFAULT), undefined).hasMore).toBe(false);
});
});
@@ -28,3 +28,18 @@ export function redisDatabaseLabel(database: string | number, aliases?: RedisDat
const name = alias ? `db${key} · ${alias}` : `db${key}`;
return totalKeyCount == null ? name : `${name} (${totalKeyCount})`;
}
// Default kept large enough that connections with a typical (or even a few
// hundred) configured databases render exactly as before #1236 — only a
// connection with an unusually large `databases` count hits the cap and gets
// a "load more" node instead of a wall of sidebar rows.
export const REDIS_DATABASE_DISPLAY_LIMIT_DEFAULT = 1000;
export const REDIS_DATABASE_DISPLAY_LIMIT_MIN = 10;
export const REDIS_DATABASE_DISPLAY_LIMIT_MAX = 100_000;
export const REDIS_DATABASE_DISPLAY_LIMIT_OPTIONS = [50, 100, 200, 500, 1000, 2000, 5000] as const;
export function limitRedisDatabaseList<T>(items: T[], limit: number | undefined): { visible: T[]; hasMore: boolean } {
const effectiveLimit = typeof limit === "number" && Number.isFinite(limit) && limit > 0 ? Math.floor(limit) : REDIS_DATABASE_DISPLAY_LIMIT_DEFAULT;
if (items.length <= effectiveLimit) return { visible: items, hasMore: false };
return { visible: items.slice(0, effectiveLimit), hasMore: true };
}
@@ -101,6 +101,7 @@ export const EDITOR_SETTINGS_DRAFT_KEYS = [
"sidebarCopyTableNameSeparator",
"sidebarCopyTableNameIncludeSchema",
"redisKeyTemplates",
"redisDatabaseDisplayLimit",
"exportBatchSize",
"csvQuoteMode",
"exportRowLimitEnabled",
@@ -164,6 +164,7 @@ const SETTINGS_TRANSFER_CATEGORY_KEYS: Record<SettingsTransferCategoryId, readon
"autoCalculateTotalRows",
"tableColumnTemplateFields",
"redisKeyTemplates",
"redisDatabaseDisplayLimit",
"exportBatchSize",
"csvQuoteMode",
"exportRowLimitEnabled",