Files
ticket-system/backend/main.py
2026-03-06 17:31:13 +00:00

62 lines
2.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from fastapi import FastAPI, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from database.session import get_db
from database.models import Ticket, TicketStatus
from core.redis import acquire_seat_lock, release_seat_lock
from api.routers.auth import router as auth_router
from api.routers.webhooks import router as webhooks_router
from api.routers.tickets import router as tickets_router
from api.routers.tournaments import router as tournaments_router
app = FastAPI(title="Ticketing System API")
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Для локальной песочницы оставляем открытым
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(auth_router)
app.include_router(webhooks_router)
app.include_router(tickets_router)
app.include_router(tournaments_router)
@app.post("/api/seats/{seat_id}/lock", status_code=status.HTTP_200_OK)
async def lock_seat(seat_id: int, user_id: int, db: AsyncSession = Depends(get_db)):
# 1. Проверяем статус в БД (грязное чтение, чтобы отсеять уже выкупленные билеты)
query = select(Ticket).where(Ticket.seat_id == seat_id)
result = await db.execute(query)
ticket = result.scalar_one_or_none()
if ticket and ticket.status != TicketStatus.AVAILABLE:
raise HTTPException(status_code=409, detail="Seat is already booked or locked in DB")
# 2. Пытаемся захватить распределенную блокировку в Redis (15 минут по ТЗ)
locked = await acquire_seat_lock(seat_id=seat_id, user_id=user_id)
if not locked:
raise HTTPException(status_code=409, detail="Seat is currently locked by another user")
# 3. Лок наш. Пишем статус в PostgreSQL
try:
if not ticket:
ticket = Ticket(seat_id=seat_id, user_id=user_id, status=TicketStatus.LOCKED)
db.add(ticket)
else:
ticket.status = TicketStatus.LOCKED
ticket.user_id = user_id
await db.commit()
return {"message": "Seat locked successfully", "seat_id": seat_id, "ticket_id": ticket.id, "status": "LOCKED"}
except Exception as e:
# Критически важно: если БД отвалилась, снимаем лок в Redis, иначе место зависнет на 15 минут
await release_seat_lock(seat_id)
await db.rollback()
raise HTTPException(status_code=500, detail="Database transaction failed")