"""processing_queue 테이블 ORM (비동기 가공 큐)""" from datetime import datetime from sqlalchemy import BigInteger, DateTime, Enum, ForeignKey, SmallInteger, Text, text from sqlalchemy.dialects.postgresql import insert as pg_insert from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import Mapped, mapped_column from core.database import Base class ProcessingQueue(Base): __tablename__ = "processing_queue" id: Mapped[int] = mapped_column(BigInteger, primary_key=True) document_id: Mapped[int] = mapped_column(BigInteger, ForeignKey("documents.id"), nullable=False) stage: Mapped[str] = mapped_column( # 'stt' (audio): migration 150 / 'thumbnail' (video): queue_consumer 가 enqueue. # DB enum 변경은 마이그레이션이 처리하므로 create_type=False. Enum( "extract", "classify", "summarize", "embed", "chunk", "preview", "stt", "thumbnail", name="process_stage", create_type=False, ), nullable=False, ) status: Mapped[str] = mapped_column( Enum("pending", "processing", "completed", "failed", name="process_status"), default="pending" ) attempts: Mapped[int] = mapped_column(SmallInteger, default=0) max_attempts: Mapped[int] = mapped_column(SmallInteger, default=3) error_message: Mapped[str | None] = mapped_column(Text) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=datetime.now ) started_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True)) completed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True)) # DB 제약은 partial unique index uq_queue_active로 관리 (migration 117) async def enqueue_stage( session: AsyncSession, document_id: int, stage: str, *, status: str = "pending", ) -> bool: """ProcessingQueue에 행 추가 (DB 레벨 중복 방어). 같은 (document_id, stage)에 활성 행(pending/processing)이 이미 있으면 아무것도 하지 않고 False 반환. """ stmt = ( pg_insert(ProcessingQueue) .values(document_id=document_id, stage=stage, status=status) .on_conflict_do_nothing( index_elements=["document_id", "stage"], index_where=text("status IN ('pending', 'processing')"), ) ) result = await session.execute(stmt) return result.rowcount > 0