SES-009: add (Cron)

Техническое задание / Спецификация требований Настроить автоматическую очистку (Cron) устаревших и отозванных токенов

Author

Системный аналитик

Published

May 28, 2026

NoteКраткая карточка задачи

1. Бизнес-контекст и цель (Business Context)

В ходе работы методов выдачи (/auth/login), ротации (/auth/refresh) и принудительного отзыва сессий (/auth/logout), в таблице refresh_tokens непрерывно накапливаются исторические данные. Токены, у которых истек срок действия (expires_at), либо которые уже были явно отозваны (is_revoked = true), более не имеют технической ценности.

Накопление миллионов мертвых записей приводит к деградации производительности базы данных, раздуванию индексов (B-Tree Bloat) и увеличению времени выполнения поисковых запросов при валидации сессий.

Цель задачи: Настроить фоновую периодическую задачу (Cron-скрипт / CronJob), которая раз в сутки автоматически и безвозвратно удаляет из базы данных Postgres устаревшие и невалидные токены.

2. Пользовательские истории (User Stories)

Как Системный администратор / DevOps-инженер платформы,
Я хочу чтобы база данных автоматически очищалась от невалидных сессионных данных по расписанию,
Чтобы поддерживать стабильно высокую скорость выполнения SQL-запросов и оптимизировать использование дискового пространства.


3. Системные требования и логика базы данных (Technical Requirements)

3.1. Критерии удаления записей (Бизнес-правила)

Запись из таблицы refresh_tokens подлежит гарантированному удалению, если она соответствует любому из следующих условий: 1. Токен просрочен: Текущее время сервера превышает срок действия токена (NOW() > expires_at). 2. Токен отозван: Флаг is_revoked переведен в состояние true (пользователь выполнил логаут), И с момента его создания/истечения прошло более 24 часов (для гарантированного отлова потенциальных Replay Attack в течение суток).

3.2. Оптимизированный SQL-запрос (DML)

Для минимизации нагрузки на базу данных и исключения блокировок живых сессий (Row Lock), удаление должно выполняться одним компактным запросом:

DELETE FROM refresh_tokens
WHERE expires_at < NOW() 
   OR (is_revoked = true AND expires_at < NOW() - INTERVAL '1 day');
WarningВажно для DBA / DevOps

Если в таблице на момент первого запуска накопилось более 10 000 000 записей, прямой DELETE может вызвать всплеск нагрузки на CPU и диск (I/O Spike). Для первого запуска в продакшене рекомендуется выполнять удаление пачками (Batches) по 50 000 строк через LIMIT в цикле.


4. Требования к инфраструктуре и расписанию (DevOps / Deployment)

4.1. Настройка расписания (Cron Schedule)

Очистка должна запускаться ежедневно в период минимальной активности пользователей платформы (например, в 03:30 ночи по часовому поясу сервера).

  • Выражение Cron: 30 3 * * *

4.2. Способ реализации (на выбор инженера)

В зависимости от текущей архитектуры деплоя микросервисов выбрать один из вариантов: * Вариант А (Если монолит/VPS): Вызов bash-скрипта через системный crontab демона Linux OS, выполняющий psql -c "DELETE...". * Вариант Б (Если Docker/Kubernetes): Запуск изолированного пода Kubernetes CronJob с образом Postgres-клиента и настроенными Environment Variables для доступа к Auth DB.

4.3. Логирование результатов

Скрипт очистки обязан логировать результаты выполнения в системный журнал (stdout / Loki):

[2026-05-29 03:30:01] [INFO] Starting SES-009: Refresh token table cleanup.
[2026-05-29 03:30:04] [INFO] Cleanup finished successfully. Removed rows: 142,503.

5. Критерии приемки и сценарии тестирования (QA Acceptance Criteria)

Сценарий 1: Проверка удаления просроченного токена

  • Дано: В таблице refresh_tokens есть запись ID=101, где expires_at равен вчерашнему дню, а is_revoked = false.
  • Когда: Наступает время 03:30 и срабатывает Cron-задача.
  • Тогда:
    • Запись ID=101 полностью удаляется из таблицы.
    • Индексы пересчитываются автоматически.

Сценарий 2: Сохранение активных сессий (Негативный тест)

  • Дано: В таблице есть запись ID=102, где токен активен (is_revoked = false) и будет действовать еще 30 дней.
  • Когда: Срабатывает ежедневный скрипт очистки.
  • Тогда: Запись ID=102 остается в базе данных без изменений. Пользовательская сессия в приложении AgroLaborApp не прерывается.