feat(redis): кэш, rate limit, баны IP и pub/sub через Redis
Добавлен сервис redis:7-alpine (AOF, requirepass, maxmemory + allkeys-lru, healthcheck, том redis-data, порт только на 127.0.0.1) и абстракция redis.js по образцу storage.js. Переведено на Redis: - кэш ответов API и настроек (было Map в памяти), инвалидация по префиксу через SCAN + DEL; - rate limit для api/entry/file — общие счётчики вместо MemoryStore; - баны IP и счётчики неудачных входа — с TTL, вместо опроса БД каждую минуту; - кэш сессий (30 с) с invalidateSessions() на каждой мутации users/sessions/ user_branches, иначе деактивированный пользователь сохранил бы доступ; - pub/sub для SSE-событий и мгновенного пробуждения фоновых воркеров вместо ожидания цикла опроса БД. Отказоустойчивость: при недоступном Redis все операции уходят в in-memory backend с той же семантикой, приложение стартует и работает без Redis и возвращается в Redis автоматически. Первое подключение ограничено по времени (REDIS_CONNECT_TIMEOUT_MS, 5 с) — node-redis не отклоняет connect() при недоступном сервере, а повторяет попытки бесконечно. Добавлены тесты: redis.selftest.js (в т.ч. поведение при недоступном сервере) и api.smoketest.js (сквозная проверка API, включая инвалидацию кэша и мгновенную смерть сессии после logout).
This commit is contained in:
@@ -18,6 +18,38 @@ services:
|
||||
timeout: 3s
|
||||
retries: 10
|
||||
|
||||
# Redis: кэш запросов, rate limit, баны IP, кэш сессий, pub/sub для SSE и воркеров.
|
||||
# Приложение не падает, если Redis недоступен — автоматически работает
|
||||
# на in-memory кэше (см. redis.js).
|
||||
# Отладка: docker compose exec redis redis-cli -a "$REDIS_PASSWORD" INFO
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: whatido-redis
|
||||
restart: unless-stopped
|
||||
command: >
|
||||
redis-server
|
||||
--requirepass ${REDIS_PASSWORD}
|
||||
--appendonly yes
|
||||
--appendfsync everysec
|
||||
--maxmemory ${REDIS_MAXMEMORY:-256mb}
|
||||
--maxmemory-policy allkeys-lru
|
||||
--save ""
|
||||
environment:
|
||||
TZ: Europe/Moscow
|
||||
REDIS_PASSWORD: ${REDIS_PASSWORD}
|
||||
expose:
|
||||
- "6379"
|
||||
ports:
|
||||
- "127.0.0.1:6379:6379"
|
||||
volumes:
|
||||
- redis-data:/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "redis-cli -a \"$$REDIS_PASSWORD\" ping | grep -q PONG"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 10
|
||||
start_period: 5s
|
||||
|
||||
app:
|
||||
build:
|
||||
context: .
|
||||
@@ -36,6 +68,8 @@ services:
|
||||
- "3443:3443"
|
||||
environment:
|
||||
DATABASE_URL: postgres://app:${DB_PASSWORD}@db:5432/whereldo
|
||||
REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379
|
||||
REDIS_PREFIX: ${REDIS_PREFIX:-whatido}
|
||||
ADMIN_PASSWORD: ${ADMIN_PASSWORD}
|
||||
ADMIN_USERNAME: ${ADMIN_USERNAME:-admin}
|
||||
BACKUP_UPLOAD_LIMIT_MB: ${BACKUP_UPLOAD_LIMIT_MB:-500}
|
||||
@@ -59,6 +93,8 @@ services:
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- ./uploads:/app/uploads
|
||||
|
||||
@@ -170,4 +206,5 @@ services:
|
||||
volumes:
|
||||
pgdata:
|
||||
photo-ai-models:
|
||||
redis-data:
|
||||
s3-data:
|
||||
|
||||
Reference in New Issue
Block a user