Files
prod-end-2026/backend/app/models/execution.py
T
2026-03-17 18:32:44 +03:00

160 lines
4.3 KiB
Python

from __future__ import annotations
import enum
import uuid
from datetime import datetime
from typing import Any
from sqlalchemy import DateTime, Enum, ForeignKey, Integer, String, Text
from sqlalchemy.dialects.postgresql import JSON, UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.models.base import Base, TimestampMixin
class ExecutionRunStatus(str, enum.Enum):
QUEUED = "QUEUED"
RUNNING = "RUNNING"
SUCCEEDED = "SUCCEEDED"
FAILED = "FAILED"
PARTIAL_FAILED = "PARTIAL_FAILED"
class ExecutionStepStatus(str, enum.Enum):
PENDING = "PENDING"
RUNNING = "RUNNING"
SUCCEEDED = "SUCCEEDED"
FAILED = "FAILED"
SKIPPED = "SKIPPED"
class ExecutionRun(TimestampMixin, Base):
__tablename__ = "execution_runs"
id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
primary_key=True,
default=uuid.uuid4,
)
pipeline_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
ForeignKey("pipelines.id", ondelete="CASCADE"),
nullable=False,
index=True,
)
initiated_by: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True),
ForeignKey("users.id", ondelete="SET NULL"),
nullable=True,
index=True,
)
status: Mapped[ExecutionRunStatus] = mapped_column(
Enum(ExecutionRunStatus, name="execution_run_status"),
nullable=False,
default=ExecutionRunStatus.QUEUED,
server_default=ExecutionRunStatus.QUEUED.value,
index=True,
)
inputs: Mapped[dict[str, Any]] = mapped_column(
JSON,
nullable=False,
default=dict,
server_default="{}",
)
summary: Mapped[dict[str, Any] | None] = mapped_column(
JSON,
nullable=True,
)
error: Mapped[str | None] = mapped_column(
Text,
nullable=True,
)
started_at: Mapped[datetime | None] = mapped_column(
DateTime(timezone=True),
nullable=True,
)
finished_at: Mapped[datetime | None] = mapped_column(
DateTime(timezone=True),
nullable=True,
)
pipeline = relationship("Pipeline", lazy="select")
step_runs = relationship(
"ExecutionStepRun",
back_populates="run",
cascade="all, delete-orphan",
lazy="selectin",
)
class ExecutionStepRun(TimestampMixin, Base):
__tablename__ = "execution_step_runs"
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("execution_runs.id", ondelete="CASCADE"),
nullable=False,
index=True,
)
step: Mapped[int] = mapped_column(
Integer,
nullable=False,
index=True,
)
name: Mapped[str | None] = mapped_column(
String(512),
nullable=True,
)
capability_id: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True),
nullable=True,
index=True,
)
action_id: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True),
nullable=True,
index=True,
)
status: Mapped[ExecutionStepStatus] = mapped_column(
Enum(ExecutionStepStatus, name="execution_step_status"),
nullable=False,
default=ExecutionStepStatus.PENDING,
server_default=ExecutionStepStatus.PENDING.value,
index=True,
)
resolved_inputs: Mapped[dict[str, Any] | None] = mapped_column(
JSON,
nullable=True,
)
request_snapshot: Mapped[dict[str, Any] | None] = mapped_column(
JSON,
nullable=True,
)
response_snapshot: Mapped[dict[str, Any] | None] = mapped_column(
JSON,
nullable=True,
)
error: Mapped[str | None] = mapped_column(
Text,
nullable=True,
)
started_at: Mapped[datetime | None] = mapped_column(
DateTime(timezone=True),
nullable=True,
)
finished_at: Mapped[datetime | None] = mapped_column(
DateTime(timezone=True),
nullable=True,
)
duration_ms: Mapped[int | None] = mapped_column(
Integer,
nullable=True,
)
run = relationship("ExecutionRun", back_populates="step_runs", lazy="select")