from fastapi import FastAPI, HTTPException, Depends from sqlalchemy.orm import Session from sqlalchemy.exc import IntegrityError from database import engine, SessionLocal, Base import models import schemas from sqlalchemy import select, update from sqlalchemy.orm import aliased app = FastAPI( title="Сервис Счетчиков", description="Сервис для инкрементирования, получения и сброса счетчиков с поддержкой namespaces, приложений и версий.", version="1.0.0" ) # Создаем таблицы в базе данных Base.metadata.create_all(bind=engine) # Зависимость для получения сессии базы данных def get_db(): db = SessionLocal() try: yield db finally: db.close() @app.post("/{namespace}/{application}/{version}", response_model=schemas.CounterResponse, summary="Инкрементировать счетчик и получить новое значение") def increment_counter(namespace: str, application: str, version: str, db: Session = Depends(get_db)): try: # Попытка найти существующий счетчик counter = db.query(models.Counter).filter_by( namespace=namespace, application=application, version=version ).with_for_update().first() if counter: counter.value += 1 else: # Если счетчик не существует, создать новый с value=1 counter = models.Counter( namespace=namespace, application=application, version=version, value=1 ) db.add(counter) db.commit() db.refresh(counter) return counter except IntegrityError: db.rollback() raise HTTPException(status_code=500, detail="Ошибка при доступе к базе данных.") @app.get("/{namespace}/{application}/{version}", response_model=schemas.CounterResponse, summary="Получить текущее значение счетчика") def get_counter(namespace: str, application: str, version: str, db: Session = Depends(get_db)): counter = db.query(models.Counter).filter_by( namespace=namespace, application=application, version=version ).first() if not counter: # Если счетчик не найден, вернуть значение 0 return schemas.CounterResponse( namespace=namespace, application=application, version=version, value=0 ) return counter @app.delete("/{namespace}/{application}/{version}", response_model=schemas.CounterResponse, summary="Сбросить счетчик до 0") def reset_counter(namespace: str, application: str, version: str, db: Session = Depends(get_db)): counter = db.query(models.Counter).filter_by( namespace=namespace, application=application, version=version ).with_for_update().first() if counter: counter.value = 0 else: # Если счетчик не существует, создать его с value=0 counter = models.Counter( namespace=namespace, application=application, version=version, value=0 ) db.add(counter) db.commit() db.refresh(counter) return counter