7031439364
'대기만 보이고 성공은 안 보인다' 피드백 반영: - overview 에 stages[] 노출 (stage 별 done_today + oldest_pending_age, SQL 1필드 추가) - 게이지 의미 전환: 단계 간 대기량 비교(amber) → 단계 내 오늘 진척(완료=green 비율, 가득 찬 초록 = 다 끝남) + 처리 중 pulse dot - 움직임 없는 단계는 행 제거, 하단 '비어 있음: ...' 한 줄로 - 라벨 누수 fix: details 가 구 STAGE_LABEL 을 쓰던 것 → queueStageLabel 통일 (deep_summary/markdown/summarize/chunk/fulltext 한글화) - 헤더: 오늘 N 완료(성공 가시화) · 실패(error) · 대기. 데이터 소스 = overview 단일화 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
91 lines
2.4 KiB
Python
91 lines
2.4 KiB
Python
"""처리 머신 보드 API — GET /api/queue/overview (plan ds-processing-ui-6an).
|
|
|
|
홈 stage 평면 테이블을 "머신 관점 보드(누가 일하나)"로 — 집계 로직은
|
|
services/queue_overview.py (순수 판정부 분리). 응답 스키마는 FE 와 계약 고정.
|
|
응답에 raw 모델명 노출 금지 — 머신 label 만.
|
|
"""
|
|
|
|
from typing import Annotated, Literal
|
|
|
|
from fastapi import APIRouter, Depends
|
|
from pydantic import BaseModel
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from core.auth import get_current_user
|
|
from core.database import get_session
|
|
from models.user import User
|
|
from services.queue_overview import build_overview
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
class CurrentItem(BaseModel):
|
|
"""머신이 지금 처리 중인 문서 (최대 2건)."""
|
|
document_id: int
|
|
title: str
|
|
stage: str
|
|
|
|
|
|
class MachineCard(BaseModel):
|
|
"""머신 카드 — stage 귀속 합산 + 완료 실적(summarize 는 풀 분리) + state."""
|
|
key: Literal["gpu", "macmini", "macbook"]
|
|
label: str
|
|
state: Literal["active", "deferred", "idle"]
|
|
stages: list[str]
|
|
pending: int
|
|
processing: int
|
|
failed: int
|
|
done_1h: int
|
|
done_today: int
|
|
deferred_pending: int
|
|
current: list[CurrentItem]
|
|
|
|
|
|
class SummarizeEta(BaseModel):
|
|
"""summarize 풀 ETA — done > inflow 일 때만 eta_minutes 산출."""
|
|
pending: int
|
|
done_rate_1h: int
|
|
inflow_rate_1h: int
|
|
eta_minutes: int | None
|
|
|
|
|
|
class TrendBucket(BaseModel):
|
|
"""summarize 24h 추이 버킷 — hour 는 KST "HH:00" 라벨."""
|
|
hour: str
|
|
inflow: int
|
|
done: int
|
|
|
|
|
|
class Totals(BaseModel):
|
|
"""전 stage 합계."""
|
|
pending: int
|
|
processing: int
|
|
failed: int
|
|
|
|
|
|
class StageRow(BaseModel):
|
|
"""단계별 현황 행 — '단계 상세' 패널용 (완료 가시화)."""
|
|
stage: str
|
|
pending: int
|
|
processing: int
|
|
failed: int
|
|
done_today: int
|
|
oldest_pending_age_sec: int | None
|
|
|
|
|
|
class QueueOverviewResponse(BaseModel):
|
|
machines: list[MachineCard]
|
|
stages: list[StageRow]
|
|
summarize_eta: SummarizeEta
|
|
trend_24h: list[TrendBucket]
|
|
totals: Totals
|
|
|
|
|
|
@router.get("/overview", response_model=QueueOverviewResponse)
|
|
async def get_queue_overview(
|
|
user: Annotated[User, Depends(get_current_user)],
|
|
session: Annotated[AsyncSession, Depends(get_session)],
|
|
):
|
|
"""머신 관점 처리 보드 + summarize ETA 집계 (라이브 계산, 신규 테이블 0)"""
|
|
return QueueOverviewResponse.model_validate(await build_overview(session))
|