"""SQLAlchemy ORM table definitions for activity-core. These are the persistence-layer counterparts to the Pydantic domain models in models.py. Alembic reads Base.metadata (imported via db.py) for autogenerate. """ from __future__ import annotations import uuid from datetime import datetime from sqlalchemy import ( Boolean, DateTime, ForeignKey, Integer, Text, func, ) from sqlalchemy.dialects.postgresql import JSONB, UUID from sqlalchemy.orm import Mapped, mapped_column from activity_core.db import Base class ActivityDefinition(Base): __tablename__ = "activity_definitions" id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), primary_key=True, default=uuid.uuid4 ) name: Mapped[str] = mapped_column(Text, nullable=False) enabled: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True) trigger_type: Mapped[str] = mapped_column(Text, nullable=False) trigger_config: Mapped[dict] = mapped_column(JSONB, nullable=False) context_sources: Mapped[list] = mapped_column(JSONB, nullable=False, default=list) task_templates: Mapped[list] = mapped_column(JSONB, nullable=False, default=list) dedupe_key_strategy: Mapped[str] = mapped_column( Text, nullable=False, default="skip" ) version: Mapped[int] = mapped_column(Integer, nullable=False, default=1) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, server_default=func.now() ) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, server_default=func.now(), onupdate=func.now(), ) class ActivityRun(Base): __tablename__ = "activity_runs" run_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), primary_key=True, default=uuid.uuid4 ) activity_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("activity_definitions.id", ondelete="RESTRICT"), nullable=False, index=True, ) scheduled_for: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True ) fired_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, server_default=func.now() ) context_snapshot: Mapped[dict] = mapped_column( JSONB, nullable=False, default=dict ) tasks_spawned: Mapped[int] = mapped_column(Integer, nullable=False, default=0) version_used: Mapped[int] = mapped_column(Integer, nullable=False) class TaskInstance(Base): __tablename__ = "task_instances" id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), primary_key=True, default=uuid.uuid4 ) run_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("activity_runs.run_id", ondelete="CASCADE"), nullable=False, index=True, ) type: Mapped[str] = mapped_column(Text, nullable=False) params: Mapped[dict] = mapped_column(JSONB, nullable=False, default=dict) status: Mapped[str] = mapped_column(Text, nullable=False, default="pending") created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, server_default=func.now() )