Initial import
This commit is contained in:
45
backend/main.py
Normal file
45
backend/main.py
Normal file
@@ -0,0 +1,45 @@
|
||||
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
|
||||
|
||||
app = FastAPI(title="Ticketing System API")
|
||||
|
||||
app.include_router(auth_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, "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")
|
||||
Reference in New Issue
Block a user