Files
fquiz/api/app/models/atp_model.py
T
2026-06-09 08:29:10 +08:00

153 lines
6.3 KiB
Python

from __future__ import annotations
from datetime import datetime
from typing import Any
from uuid import uuid4
from sqlalchemy import JSON, DateTime, ForeignKey, Index, Integer, String, Text, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column, relationship
from ..core.database import Base
from .base import utcnow
class AtpModel(Base):
__tablename__ = "atp_model"
__table_args__ = (
UniqueConstraint("code", name="uq_atp_model_code"),
Index("idx_atp_model_status", "status"),
Index("idx_atp_model_source", "source_type"),
)
id: Mapped[str] = mapped_column(
String(32),
primary_key=True,
default=lambda: uuid4().hex,
)
code: Mapped[str] = mapped_column(String(64), nullable=False, index=True)
name: Mapped[str] = mapped_column(String(255), nullable=False)
source_type: Mapped[str] = mapped_column(String(32), default="atpdraw", index=True)
description: Mapped[str] = mapped_column(Text(), default="")
status: Mapped[str] = mapped_column(String(20), default="enabled", index=True)
tags_json: Mapped[list[str]] = mapped_column(JSON, default=list)
latest_version_no: Mapped[int] = mapped_column(Integer, default=0)
active_version_no: Mapped[int | None] = mapped_column(Integer)
create_date: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utcnow, index=True)
create_user: Mapped[str | None] = mapped_column(String(64), index=True)
update_date: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=utcnow,
onupdate=utcnow,
)
update_user: Mapped[str | None] = mapped_column(String(64), index=True)
versions: Mapped[list[AtpModelVersion]] = relationship(
"AtpModelVersion",
back_populates="model",
lazy="selectin",
cascade="all, delete-orphan",
order_by="AtpModelVersion.version_no.desc()",
)
runs: Mapped[list[AtpSimulationRun]] = relationship(
"AtpSimulationRun",
back_populates="model",
lazy="selectin",
cascade="all, delete-orphan",
order_by="AtpSimulationRun.create_date.desc()",
)
class AtpModelVersion(Base):
__tablename__ = "atp_model_version"
__table_args__ = (
UniqueConstraint("model_id", "version_no", name="uq_atp_model_version_model_no"),
Index("idx_atp_model_version_status", "status"),
Index("idx_atp_model_version_model_status", "model_id", "status"),
Index("idx_atp_model_version_content_hash", "content_hash"),
)
id: Mapped[str] = mapped_column(
String(32),
primary_key=True,
default=lambda: uuid4().hex,
)
model_id: Mapped[str] = mapped_column(
String(32),
ForeignKey("atp_model.id", ondelete="CASCADE"),
nullable=False,
index=True,
)
version_no: Mapped[int] = mapped_column(Integer, nullable=False, index=True)
version_tag: Mapped[str | None] = mapped_column(String(64), index=True)
status: Mapped[str] = mapped_column(String(20), default="draft", index=True)
entry_file: Mapped[str | None] = mapped_column(String(255))
change_note: Mapped[str] = mapped_column(Text(), default="")
artifact_manifest_json: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict)
graph_json: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict)
atp_text: Mapped[str] = mapped_column(Text(), default="")
content_hash: Mapped[str] = mapped_column(String(64), index=True)
create_date: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utcnow, index=True)
create_user: Mapped[str | None] = mapped_column(String(64), index=True)
update_date: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=utcnow,
onupdate=utcnow,
)
update_user: Mapped[str | None] = mapped_column(String(64), index=True)
model: Mapped[AtpModel] = relationship("AtpModel", back_populates="versions", lazy="selectin")
runs: Mapped[list[AtpSimulationRun]] = relationship(
"AtpSimulationRun",
back_populates="version",
lazy="selectin",
order_by="AtpSimulationRun.create_date.desc()",
)
class AtpSimulationRun(Base):
__tablename__ = "atp_simulation_run"
__table_args__ = (
Index("idx_atp_simulation_run_status", "status"),
Index("idx_atp_simulation_run_model", "model_id", "create_date"),
)
id: Mapped[str] = mapped_column(
String(32),
primary_key=True,
default=lambda: uuid4().hex,
)
model_id: Mapped[str] = mapped_column(
String(32),
ForeignKey("atp_model.id", ondelete="CASCADE"),
nullable=False,
index=True,
)
version_id: Mapped[str | None] = mapped_column(
String(32),
ForeignKey("atp_model_version.id", ondelete="SET NULL"),
index=True,
)
status: Mapped[str] = mapped_column(String(20), default="pending", index=True)
engine_mode: Mapped[str] = mapped_column(String(20), default="wine", index=True)
task_id: Mapped[str | None] = mapped_column(String(128), index=True)
engine_command: Mapped[str | None] = mapped_column(String(1000))
working_dir: Mapped[str | None] = mapped_column(String(1000))
timeout_seconds: Mapped[int] = mapped_column(Integer, default=600)
exit_code: Mapped[int | None] = mapped_column(Integer)
started_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
finished_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
duration_ms: Mapped[int | None] = mapped_column(Integer)
stdout_text: Mapped[str | None] = mapped_column(Text())
stderr_text: Mapped[str | None] = mapped_column(Text())
error_message: Mapped[str | None] = mapped_column(Text())
create_date: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utcnow, index=True)
create_user: Mapped[str | None] = mapped_column(String(64), index=True)
update_date: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=utcnow,
onupdate=utcnow,
)
update_user: Mapped[str | None] = mapped_column(String(64), index=True)
model: Mapped[AtpModel] = relationship("AtpModel", back_populates="runs", lazy="selectin")
version: Mapped[AtpModelVersion | None] = relationship("AtpModelVersion", back_populates="runs", lazy="selectin")