fix: memory analysis dark mode stripe, scan speed, and NaN total size

- Dark mode: add --el-fill-color-lighter and --el-table-current-row-bg-color
  to .el-table overrides so striped rows render with proper contrast
- Scan speed: add batchKeyMemoryUsage pipeline (TYPE + MEMORY USAGE in one
  Redis round-trip instead of 2×N sequential IPC calls)
- Scan speed: decouple scan loop from UI via 300ms flush buffer, keeping
  el-table re-render frequency capped at ~3/s
- Scan speed: use shallowRef for entries to skip deep reactive proxies
- NaN fix: handle ioredis stringNumbers:true by converting via Number()
  instead of typeof === 'number'
- formatSize: guard against non-finite input, add TB/PB units
This commit is contained in:
2026-07-12 10:01:30 +08:00
parent 72967c45e9
commit c8eeb7c0b9
6 changed files with 75 additions and 24 deletions
+3
View File
@@ -149,6 +149,9 @@ export function registerIpcHandlers(): void {
ipcMain.handle('redis:memoryUsage', async (_e, id: string, key: string) => {
return redis.memoryUsage(id, key)
})
ipcMain.handle('redis:batchMemoryUsage', async (_e, id: string, keys: string[]) => {
return redis.batchKeyMemoryUsage(id, keys)
})
// Redis - String
ipcMain.handle('redis:getString', async (_e, id: string, key: string) => {
+35
View File
@@ -51,6 +51,41 @@ export async function memoryUsage(id: string, key: string): Promise<number | nul
return client.memory('USAGE', key) as Promise<number | null>
}
export interface KeyMemoryInfo {
key: string
type: string
size: number
}
/**
* Batch-fetch TYPE + MEMORY USAGE for multiple keys via a single ioredis pipeline.
* One Redis round-trip instead of 2×N sequential commands.
*/
export async function batchKeyMemoryUsage(
id: string,
keys: string[]
): Promise<KeyMemoryInfo[]> {
const client = requireClient(id)
if (keys.length === 0) return []
const pipeline = client.pipeline()
for (const key of keys) {
pipeline.type(key)
pipeline.memory('USAGE', key)
}
const results = await pipeline.exec()
const entries: KeyMemoryInfo[] = []
for (let i = 0; i < keys.length; i++) {
const typeRes = results?.[i * 2]
const sizeRes = results?.[i * 2 + 1]
const type = typeRes?.[0] ? 'none' : String(typeRes?.[1] ?? 'none')
const rawSize = sizeRes?.[0] ? null : sizeRes?.[1]
// ioredis stringNumbers:true may return strings like "528" instead of 528
const size = Number.isFinite(Number(rawSize)) ? Number(rawSize) : 0
entries.push({ key: keys[i], type, size })
}
return entries
}
export async function scanKeys(
id: string,
cursor: string,