cleanup
This commit is contained in:
@@ -44,18 +44,34 @@ async def get_queue_status(
|
||||
queue_status = await download_service.get_queue_status()
|
||||
queue_stats = await download_service.get_queue_stats()
|
||||
|
||||
# Preserve the legacy response contract expected by the original CLI
|
||||
# client and existing integration tests. Those consumers rely on the
|
||||
# field names ``active``/``pending``/``completed``/``failed`` and raw
|
||||
# dict payloads rather than Pydantic models, so we emit JSON-friendly
|
||||
# dictionaries that mirror the historic structure.
|
||||
# Preserve the legacy response contract expected by the original CLI
|
||||
# client and existing integration tests. Those consumers still parse
|
||||
# the bare dictionaries that the pre-FastAPI implementation emitted,
|
||||
# so we keep the canonical field names (``active``/``pending``/
|
||||
# ``completed``/``failed``) and dump each Pydantic object to plain
|
||||
# JSON-compatible dicts instead of returning the richer
|
||||
# ``QueueStatusResponse`` shape directly. This guarantees both the
|
||||
# CLI and older dashboard widgets do not need schema migrations while
|
||||
# the new web UI can continue to evolve independently.
|
||||
status_payload = {
|
||||
"is_running": queue_status.is_running,
|
||||
"is_paused": queue_status.is_paused,
|
||||
"active": [it.model_dump(mode="json") for it in queue_status.active_downloads],
|
||||
"pending": [it.model_dump(mode="json") for it in queue_status.pending_queue],
|
||||
"completed": [it.model_dump(mode="json") for it in queue_status.completed_downloads],
|
||||
"failed": [it.model_dump(mode="json") for it in queue_status.failed_downloads],
|
||||
"active": [
|
||||
it.model_dump(mode="json")
|
||||
for it in queue_status.active_downloads
|
||||
],
|
||||
"pending": [
|
||||
it.model_dump(mode="json")
|
||||
for it in queue_status.pending_queue
|
||||
],
|
||||
"completed": [
|
||||
it.model_dump(mode="json")
|
||||
for it in queue_status.completed_downloads
|
||||
],
|
||||
"failed": [
|
||||
it.model_dump(mode="json")
|
||||
for it in queue_status.failed_downloads
|
||||
],
|
||||
}
|
||||
|
||||
# Add the derived ``success_rate`` metric so dashboards built against
|
||||
@@ -71,7 +87,10 @@ async def get_queue_status(
|
||||
stats_payload["success_rate"] = success_rate
|
||||
|
||||
return JSONResponse(
|
||||
content={"status": status_payload, "statistics": stats_payload}
|
||||
content={
|
||||
"status": status_payload,
|
||||
"statistics": stats_payload,
|
||||
}
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
@@ -133,7 +152,10 @@ async def add_to_queue(
|
||||
"failed_items": [],
|
||||
}
|
||||
|
||||
return JSONResponse(content=payload, status_code=status.HTTP_201_CREATED)
|
||||
return JSONResponse(
|
||||
content=payload,
|
||||
status_code=status.HTTP_201_CREATED,
|
||||
)
|
||||
|
||||
except DownloadServiceError as e:
|
||||
raise HTTPException(
|
||||
@@ -509,7 +531,10 @@ async def reorder_queue(
|
||||
if not success:
|
||||
# Provide an appropriate 404 message depending on request shape
|
||||
if "item_order" in request:
|
||||
detail = "One or more items in item_order were not found in pending queue"
|
||||
detail = (
|
||||
"One or more items in item_order were not "
|
||||
"found in pending queue"
|
||||
)
|
||||
else:
|
||||
detail = f"Item {req.item_id} not found in pending queue"
|
||||
|
||||
|
||||
@@ -77,18 +77,27 @@ app.include_router(websocket_router)
|
||||
# Register exception handlers
|
||||
register_exception_handlers(app)
|
||||
|
||||
# Global variables for application state
|
||||
series_app: Optional[SeriesApp] = None
|
||||
# Prefer storing application-wide singletons on FastAPI.state instead of
|
||||
# module-level globals. This makes testing and multi-instance hosting safer.
|
||||
|
||||
|
||||
def get_series_app() -> Optional[SeriesApp]:
|
||||
"""Dependency to retrieve the SeriesApp instance from application state.
|
||||
|
||||
Returns None when the application wasn't configured with an anime
|
||||
directory (for example during certain test runs).
|
||||
"""
|
||||
return getattr(app.state, "series_app", None)
|
||||
|
||||
|
||||
@app.on_event("startup")
|
||||
async def startup_event():
|
||||
"""Initialize application on startup."""
|
||||
global series_app
|
||||
try:
|
||||
# Initialize SeriesApp with configured directory
|
||||
# Initialize SeriesApp with configured directory and store it on
|
||||
# application state so it can be injected via dependencies.
|
||||
if settings.anime_directory:
|
||||
series_app = SeriesApp(settings.anime_directory)
|
||||
app.state.series_app = SeriesApp(settings.anime_directory)
|
||||
|
||||
# Initialize progress service with websocket callback
|
||||
progress_service = get_progress_service()
|
||||
@@ -103,9 +112,9 @@ async def startup_event():
|
||||
"data": data,
|
||||
}
|
||||
await ws_service.manager.broadcast_to_room(message, room)
|
||||
|
||||
|
||||
progress_service.set_broadcast_callback(broadcast_callback)
|
||||
|
||||
|
||||
print("FastAPI application started successfully")
|
||||
except Exception as e:
|
||||
print(f"Error during startup: {e}")
|
||||
|
||||
@@ -312,10 +312,15 @@ def get_anime_service() -> "AnimeService":
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
running_tests = (
|
||||
"PYTEST_CURRENT_TEST" in os.environ
|
||||
or "pytest" in sys.modules
|
||||
)
|
||||
# Prefer explicit test mode opt-in via ANIWORLD_TESTING=1; fall back
|
||||
# to legacy heuristics for backwards compatibility with CI.
|
||||
running_tests = os.getenv("ANIWORLD_TESTING") == "1"
|
||||
if not running_tests:
|
||||
running_tests = (
|
||||
"PYTEST_CURRENT_TEST" in os.environ
|
||||
or "pytest" in sys.modules
|
||||
)
|
||||
|
||||
if running_tests:
|
||||
settings.anime_directory = tempfile.gettempdir()
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user