fix(redis): разбирать INFO по разделителю, а не по фиксированному смещению

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
This commit is contained in:
dev
2026-09-27 12:46:41 +03:00
parent 3ecf87146a
commit 4d3df1de37
+43 -11
View File
@@ -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,
};
}
},