Spaces:
Runtime error
Runtime error
| """Live generation progress for ``GET /reports/{id}/status`` polling.""" | |
| from __future__ import annotations | |
| from datetime import UTC, datetime | |
| from sqlalchemy import case, func, select | |
| from sqlalchemy.ext.asyncio import AsyncSession | |
| from app.db.models import Report, ReportSection, ReportStatus | |
| async def count_report_section_progress( | |
| db: AsyncSession, | |
| report_id: str, | |
| ) -> tuple[int, int]: | |
| """Return ``(sections_saved, sections_with_text)`` for a report.""" | |
| row = await db.execute( | |
| select( | |
| func.count(ReportSection.id), | |
| func.coalesce( | |
| func.sum( | |
| case( | |
| (func.length(func.trim(ReportSection.text)) > 0, 1), | |
| else_=0, | |
| ) | |
| ), | |
| 0, | |
| ), | |
| ).where(ReportSection.report_id == report_id) | |
| ) | |
| saved, with_text = row.one() | |
| return int(saved or 0), int(with_text or 0) | |
| def generation_elapsed_seconds(report: Report) -> float | None: | |
| """Seconds since ``generation_started_at`` while the job is active.""" | |
| if report.status != ReportStatus.generating or report.generation_started_at is None: | |
| return None | |
| started = report.generation_started_at | |
| if started.tzinfo is None: | |
| started = started.replace(tzinfo=UTC) | |
| return max(0.0, (datetime.now(UTC) - started).total_seconds()) | |
| async def build_status_progress_fields( | |
| db: AsyncSession, | |
| report: Report, | |
| ) -> dict[str, int | float | None]: | |
| """Fields merged into :class:`~app.models.schemas.ReportStatusResponse`.""" | |
| saved, with_text = await count_report_section_progress(db, report.id) | |
| elapsed = generation_elapsed_seconds(report) | |
| return { | |
| "sections_saved": saved, | |
| "sections_with_text": with_text, | |
| "generation_section_total": report.generation_section_total, | |
| "generation_elapsed_seconds": round(elapsed, 1) if elapsed is not None else None, | |
| } | |