fix(health): утечка ioredis-клиента в /health при недоступном Redis [T0.2] #483

Closed
opened 2026-07-11 01:51:26 +03:00 by agent_vscode · 1 comment
Collaborator

Суть. apps/server/src/integrations/health/redis.health.ts (pingCheck): new Redis(...) на каждый вызов; redis.disconnect() только на success-пути. При недоступном Redis каждый вызов /health навсегда добавляет реконнектящийся клиент (maxRetriesPerRequest: 15 не останавливает реконнекты самого соединения).

Сценарий отказа. Redis упал → docker/k8s-проба долбит /health каждые N секунд → сотни живых клиентов с таймерами реконнекта → рост памяти/CPU, лавина попыток соединений усугубляет инцидент.

Правка.

  1. Минимум: try/finally с disconnect().
  2. Правильно: один долгоживущий клиент для health-проб (lazyConnect, maxRetriesPerRequest: 1).
  3. Системно: единая фабрика Redis-подключений с регистрацией в shutdown-хуке — закрывает класс, который уже чинили точечно (#254, #256).

Тест. Интеграционный — N вызовов pingCheck при лежащем Redis не увеличивают число живых хэндлов (наблюдаемое свойство, не мок).

Зависимости. Нет — независимый мелкий PR.

**Суть.** `apps/server/src/integrations/health/redis.health.ts` (`pingCheck`): `new Redis(...)` на каждый вызов; `redis.disconnect()` только на success-пути. При недоступном Redis каждый вызов `/health` навсегда добавляет реконнектящийся клиент (`maxRetriesPerRequest: 15` не останавливает реконнекты самого соединения). **Сценарий отказа.** Redis упал → docker/k8s-проба долбит `/health` каждые N секунд → сотни живых клиентов с таймерами реконнекта → рост памяти/CPU, лавина попыток соединений усугубляет инцидент. **Правка.** 1. Минимум: `try/finally` с `disconnect()`. 2. Правильно: один долгоживущий клиент для health-проб (`lazyConnect`, `maxRetriesPerRequest: 1`). 3. Системно: единая фабрика Redis-подключений с регистрацией в shutdown-хуке — закрывает класс, который уже чинили точечно (#254, #256). **Тест.** Интеграционный — N вызовов pingCheck при лежащем Redis не увеличивают число живых хэндлов (наблюдаемое свойство, не мок). **Зависимости.** Нет — независимый мелкий PR.
Author
Collaborator

Заменено итерационным ишью #486 (коммит 2). Закрыто как дубль.

Заменено итерационным ишью #486 (коммит 2). Закрыто как дубль.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: vvzvlad/gitmost#483