"""Task model for orchestration jobs.""" import uuid from enum import Enum from typing import TYPE_CHECKING, Any from sqlalchemy import ForeignKey, String from sqlalchemy.dialects.postgresql import JSONB from sqlalchemy.orm import Mapped, mapped_column, relationship from app.models.base import Base, TimestampMixin, UUIDMixin if TYPE_CHECKING: from app.models.agent import Agent from app.models.event import Event from app.models.tenant import Tenant class TaskStatus(str, Enum): """Task execution status.""" PENDING = "pending" RUNNING = "running" COMPLETED = "completed" FAILED = "failed" class Task(UUIDMixin, TimestampMixin, Base): """ Task model representing an orchestration job. Tasks are assigned to agents and track execution state. Payload and result use JSONB for flexible, queryable storage. """ __tablename__ = "tasks" tenant_id: Mapped[uuid.UUID] = mapped_column( ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False, index=True, ) agent_id: Mapped[uuid.UUID | None] = mapped_column( ForeignKey("agents.id", ondelete="SET NULL"), nullable=True, index=True, ) type: Mapped[str] = mapped_column( String(100), nullable=False, index=True, ) payload: Mapped[dict[str, Any]] = mapped_column( JSONB, nullable=False, default=dict, ) status: Mapped[str] = mapped_column( String(50), default=TaskStatus.PENDING.value, nullable=False, index=True, ) result: Mapped[dict[str, Any] | None] = mapped_column( JSONB, nullable=True, ) # Relationships tenant: Mapped["Tenant"] = relationship( back_populates="tasks", ) agent: Mapped["Agent | None"] = relationship( back_populates="tasks", ) events: Mapped[list["Event"]] = relationship( back_populates="task", lazy="selectin", ) def __repr__(self) -> str: return f""