From 4d3df1de3759dda10d42890da074f56e31bc0168 Mon Sep 17 00:00:00 2001 From: dev Date: Sun, 27 Sep 2026 12:46:41 +0300 Subject: [PATCH] =?UTF-8?q?fix(redis):=20=D1=80=D0=B0=D0=B7=D0=B1=D0=B8?= =?UTF-8?q?=D1=80=D0=B0=D1=82=D1=8C=20INFO=20=D0=BF=D0=BE=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B7=D0=B4=D0=B5=D0=BB=D0=B8=D1=82=D0=B5=D0=BB=D1=8E,=20?= =?UTF-8?q?=D0=B0=20=D0=BD=D0=B5=20=D0=BF=D0=BE=20=D1=84=D0=B8=D0=BA=D1=81?= =?UTF-8?q?=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D0=BE=D0=BC=D1=83=20?= =?UTF-8?q?=D1=81=D0=BC=D0=B5=D1=89=D0=B5=D0=BD=D0=B8=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit used_memory и used_memory_human вырезались на символ длиннее нужного, поэтому первая цифра терялась: 1024 превращалось в 24, а "1.34M" — в ".34M". Значение памяти Redis в /api/system-info и в self-тестах было занижено на порядок. - parseInfoSections(): разбор INFO по indexOf(':'), пропуск заголовков # и пустых строк, работа с любой секцией - info(): добавлены redis_version и uptime_in_seconds (секция server), в том числе в ветках memory и ошибки — с null --- redis.js | 54 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/redis.js b/redis.js index 4c1079d..8dd8a29 100644 --- a/redis.js +++ b/redis.js @@ -17,6 +17,20 @@ return hits const SCAN_BATCH = 200; +function parseInfoSections(chunks) { + const out = new Map(); + for (const chunk of chunks) { + for (const line of String(chunk || '').split('\n')) { + const trimmed = line.trim(); + if (!trimmed || trimmed.startsWith('#')) continue; + const sep = trimmed.indexOf(':'); + if (sep < 1) continue; + out.set(trimmed.slice(0, sep).trim(), trimmed.slice(sep + 1).trim()); + } + } + return out; +} + function createMemoryBackend() { const store = new Map(); const listeners = new Map(); @@ -184,25 +198,43 @@ function createRedis({ url, prefix } = {}) { async info() { const base = { ...stats, enabled: enabled(), ready: ready(), namespace }; - if (!ready()) return { ...base, driver: 'memory', used_memory_bytes: null, used_memory_human: null, keys: null }; + const offline = { + ...base, + driver: 'memory', + version: null, + server_uptime_s: null, + used_memory_bytes: null, + used_memory_human: null, + keys: null, + }; + if (!ready()) return offline; try { - const [raw, dbsize] = await Promise.all([client.info('memory'), client.dbSize()]); - let used = null; - let human = null; - for (const line of String(raw || '').split('\n')) { - if (line.startsWith('used_memory:')) used = parseInt(line.slice(13).trim(), 10) || null; - else if (line.startsWith('used_memory_human:')) human = line.slice(19).trim(); - } + const [raw, dbsize, server] = await Promise.all([ + client.info('memory'), + client.dbSize(), + client.info('server'), + ]); + const fields = parseInfoSections([raw, server]); return { ...base, driver: 'redis', - used_memory_bytes: used, - used_memory_human: human, + version: fields.get('redis_version') || null, + server_uptime_s: fields.has('uptime_in_seconds') ? Number(fields.get('uptime_in_seconds')) || null : null, + used_memory_bytes: fields.has('used_memory') ? Number(fields.get('used_memory')) || null : null, + used_memory_human: fields.get('used_memory_human') || null, keys: Number(dbsize) || 0, }; } catch (e) { noteError('info', e); - return { ...base, driver: 'redis', used_memory_bytes: null, used_memory_human: null, keys: null }; + return { + ...base, + driver: 'redis', + version: null, + server_uptime_s: null, + used_memory_bytes: null, + used_memory_human: null, + keys: null, + }; } },