refresh api and tests
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# Создание FastAPI-приложения и настройка его жизненного цикла.
|
||||
# FastAPI-приложение и его жизненный цикл.
|
||||
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
@@ -11,8 +11,7 @@ from .routes import cars, health, tasks
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
# Жизненный цикл.
|
||||
# Таблицы создаются через Alembic-миграции (сервис migrate).
|
||||
# Таблицы создаются миграциями Alembic.
|
||||
yield
|
||||
|
||||
|
||||
@@ -36,5 +35,5 @@ def create_app(settings: Settings | None = None) -> FastAPI:
|
||||
return app
|
||||
|
||||
|
||||
# Экземпляр приложения для запуска через uvicorn.
|
||||
# Точка входа для uvicorn.
|
||||
app = create_app()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Вспомогательные зависимости для FastAPI-роутов.
|
||||
# Зависимости FastAPI.
|
||||
|
||||
from fastapi import Request
|
||||
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
"""API route package.
|
||||
|
||||
Routers are defined in dedicated modules (`cars`, `health`, `tasks`). This
|
||||
package intentionally does not create routes to avoid duplicate task endpoints
|
||||
and accidental imports of legacy parser channels during FastAPI startup.
|
||||
"""
|
||||
# Пакет роутов API.
|
||||
# Здесь только импорт модулей роутов без побочных эффектов.
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Роуты для просмотра автомобилей и агрегированной статистики.
|
||||
# Роуты для авто и статистики.
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy import func, select
|
||||
@@ -22,7 +22,7 @@ def list_cars(
|
||||
is_sold: bool | None = None,
|
||||
persistence: PersistenceService = Depends(get_persistence),
|
||||
):
|
||||
# Список автомобилей с пагинацией и фильтрами
|
||||
# Список авто с фильтрами.
|
||||
with persistence.session_scope() as session:
|
||||
query = select(Car)
|
||||
|
||||
@@ -59,7 +59,7 @@ def get_car(
|
||||
car_id: int,
|
||||
persistence: PersistenceService = Depends(get_persistence),
|
||||
):
|
||||
# Детальная информация об автомобиле с изображениями
|
||||
# Карточка авто с фото.
|
||||
with persistence.session_scope() as session:
|
||||
car = session.get(Car, car_id)
|
||||
if car is None:
|
||||
@@ -72,7 +72,7 @@ def get_car_by_origin(
|
||||
origin_id: str,
|
||||
persistence: PersistenceService = Depends(get_persistence),
|
||||
):
|
||||
# Поиск автомобиля по origin_id
|
||||
# Поиск по origin_id.
|
||||
with persistence.session_scope() as session:
|
||||
car = session.execute(
|
||||
select(Car).where(Car.origin_id == origin_id)
|
||||
@@ -84,7 +84,7 @@ def get_car_by_origin(
|
||||
|
||||
@router.get("/stats")
|
||||
def get_stats(persistence: PersistenceService = Depends(get_persistence)):
|
||||
# Общая статистика по БД
|
||||
# Общая статистика.
|
||||
with persistence.session_scope() as session:
|
||||
total_cars = session.execute(select(func.count(Car.id))).scalar() or 0
|
||||
total_images = session.execute(select(func.count(Image.id))).scalar() or 0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Роут проверки доступности сервиса и соединения с БД.
|
||||
# Проверка API и БД.
|
||||
|
||||
import logging
|
||||
|
||||
@@ -14,7 +14,7 @@ logger = logging.getLogger("MOBILEDE_scraper.api.health")
|
||||
|
||||
@router.get("/health")
|
||||
def health_check(persistence: PersistenceService = Depends(get_persistence)):
|
||||
# Проверка API и БД
|
||||
# Проверяем доступность БД.
|
||||
db_ok = False
|
||||
try:
|
||||
with persistence.session_scope() as session:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Роуты запуска задач синхронизации и просмотра истории sync-runs.
|
||||
# Роуты запуска задач и истории sync-run.
|
||||
|
||||
import json
|
||||
|
||||
@@ -11,8 +11,14 @@ from ...core.config import Settings
|
||||
from ..deps import get_persistence
|
||||
from ...storage.db import PersistenceService
|
||||
from ...storage.models import SyncRun
|
||||
from ...worker.celery_app import MOBILEDE_SYNC_QUEUE, celery_app
|
||||
from ...worker.tasks import mobilede_sync_detail_task, mobilede_sync_runtime_segments_task, mobilede_sync_search_task
|
||||
from ...worker.celery_app import celery_app
|
||||
from ...worker.constants import MOBILEDE_SYNC_QUEUE
|
||||
from ...worker.tasks import (
|
||||
mobilede_enrich_images_batch_task,
|
||||
mobilede_sync_detail_task,
|
||||
mobilede_sync_runtime_segments_task,
|
||||
mobilede_sync_search_task,
|
||||
)
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@@ -38,6 +44,13 @@ class MobileDeSyncDetailRequest(BaseModel):
|
||||
lane: str = "mobile_de_cars"
|
||||
|
||||
|
||||
class MobileDeEnrichImagesRequest(BaseModel):
|
||||
limit: int = 50
|
||||
lane: str = "mobile_de_cars"
|
||||
max_existing_images: int = 1
|
||||
delay_seconds: float = 1.0
|
||||
|
||||
|
||||
class MobileDeRuntimeSegmentsRequest(BaseModel):
|
||||
lane: str = "mobile_de_cars"
|
||||
delay_seconds: float = 0.7
|
||||
@@ -72,6 +85,19 @@ def start_mobilede_sync_detail(body: MobileDeSyncDetailRequest):
|
||||
}
|
||||
|
||||
|
||||
@router.post("/mobilede/tasks/enrich-images")
|
||||
def start_mobilede_enrich_images(body: MobileDeEnrichImagesRequest):
|
||||
result = mobilede_enrich_images_batch_task.apply_async(
|
||||
kwargs=body.model_dump(),
|
||||
queue=MOBILEDE_SYNC_QUEUE,
|
||||
)
|
||||
return {
|
||||
"task_id": result.id,
|
||||
"status": "queued",
|
||||
"queue": MOBILEDE_SYNC_QUEUE,
|
||||
}
|
||||
|
||||
|
||||
@router.post("/mobilede/tasks/sync-runtime-segments")
|
||||
def start_mobilede_runtime_segments(body: MobileDeRuntimeSegmentsRequest):
|
||||
result = mobilede_sync_runtime_segments_task.apply_async(
|
||||
@@ -141,7 +167,7 @@ def list_sync_runs(
|
||||
per_page: int = Query(20, ge=1, le=100),
|
||||
persistence: PersistenceService = Depends(get_persistence),
|
||||
):
|
||||
# История запусков синхронизации
|
||||
# История запусков.
|
||||
with persistence.session_scope() as session:
|
||||
total = session.execute(select(func.count(SyncRun.id))).scalar() or 0
|
||||
offset = (page - 1) * per_page
|
||||
|
||||
Reference in New Issue
Block a user