cosmo_backend/app/api/task.py

74 lines
2.1 KiB
Python

"""
Task Management API routes
"""
from fastapi import APIRouter, HTTPException, Depends, Query
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, desc
from app.database import get_db
from app.models.db import Task
from app.services.task_service import task_service
router = APIRouter(prefix="/tasks", tags=["tasks"])
@router.get("")
async def list_tasks(
limit: int = Query(20, ge=1, le=100),
offset: int = Query(0, ge=0),
db: AsyncSession = Depends(get_db)
):
"""
List background tasks
Args:
limit: Maximum number of tasks to return (1-100, default 20)
offset: Number of tasks to skip (default 0)
"""
result = await db.execute(
select(Task).order_by(desc(Task.created_at)).limit(limit).offset(offset)
)
tasks = result.scalars().all()
return tasks
@router.get("/{task_id}")
async def get_task_status(
task_id: int,
db: AsyncSession = Depends(get_db)
):
"""
Get task status and progress
Returns merged data from Redis (real-time progress) and database (persistent record)
"""
# Check Redis first for real-time progress
redis_data = await task_service.get_task_progress_from_redis(task_id)
# Get DB record
task = await task_service.get_task(db, task_id)
if not task:
raise HTTPException(status_code=404, detail="Task not found")
# Merge Redis data if available (Redis has fresher progress)
response = {
"id": task.id,
"task_type": task.task_type,
"status": task.status,
"progress": task.progress,
"description": task.description,
"created_at": task.created_at,
"started_at": task.started_at,
"completed_at": task.completed_at,
"error_message": task.error_message,
"result": task.result
}
if redis_data:
response["status"] = redis_data.get("status", task.status)
response["progress"] = redis_data.get("progress", task.progress)
if "error" in redis_data:
response["error_message"] = redis_data["error"]
return response