2.5 KiB
2.5 KiB
Архитектура и бизнес-правила (Ticket System)
1. Базовые принципы
- Стек: FastAPI, SQLAlchemy 2.0 (asyncpg), PostgreSQL, Redis, RabbitMQ.
- Модели данных: Описаны в
backend/database/models.py. - Ключевые сущности: User, Tournament, Seat, Ticket.
2. Жизненный цикл билета (State Machine)
Статус билета (TicketStatus в таблице tickets) строго ограничен:
AVAILABLE— место свободно для бронирования.LOCKED— место временно захвачено пользователем (15 минут на оплату).PAID— оплата прошла успешно.SCANNED— билет погашен на входе.REFUNDED— возврат.
3. Сценарий А: Конкурентное бронирование (Критический путь)
Захват места должен исключать "состояние гонки" (race condition).
- При POST-запросе на захват места (
/api/seats/{seat_id}/lock), FastAPI обращается к Redis. - Пытается установить ключ
lock:seat:{seat_id}с помощьюSETNXи TTL 15 минут. - Успех: Если Redis вернул 1, обновляем статус билета в БД на
LOCKEDи привязываемuser_id. Возвращаем HTTP 200. - Отказ: Если ключ уже существует, немедленно возвращаем HTTP 409 Conflict. БД не трогаем.
4. Сценарий Б: Асинхронная выдача билета (Idempotency)
Защита от двойных списаний и зависаний интерфейса при долгой генерации PDF.
- Платежный шлюз присылает Webhook об успешной оплате.
- FastAPI проверяет поле
idempotency_keyв таблицеtickets. Если ключ уже обработан — игнорируем запрос. - Обновляем статус билета на
PAID. - Отправляем событие
ticket_paid(содержитticket_idи данные пользователя) в очередь RabbitMQ. Отвечаем шлюзу HTTP 200. - Фоновый воркер забирает задачу, генерирует PDF (reportlab), грузит в MinIO (boto3) и сохраняет ссылку в БД.