Files
loom/backend/app/models/task.py
T
2026-04-24 17:46:03 +08:00

93 lines
3.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""任务 + 任务日志。"""
from __future__ import annotations
from datetime import datetime
from sqlalchemy import (
JSON,
DateTime,
ForeignKey,
Integer,
String,
Text,
UniqueConstraint,
func,
)
from sqlalchemy.orm import Mapped, mapped_column
from app.db.base import Base, TimestampMixin
class Task(Base, TimestampMixin):
__tablename__ = "task"
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
# 任务编号(人类可读),由服务层生成,如 T20260424-0001
task_no: Mapped[str] = mapped_column(String(32), nullable=False, unique=True, index=True)
name: Mapped[str] = mapped_column(String(128), nullable=False)
skill_id: Mapped[int] = mapped_column(
ForeignKey("skill.id", ondelete="RESTRICT"), nullable=False, index=True
)
skill_code: Mapped[str] = mapped_column(String(64), nullable=False)
product_id: Mapped[int | None] = mapped_column(
ForeignKey("product.id", ondelete="SET NULL"), nullable=True, index=True
)
# LOBSTER / SCRIPT
executor_type: Mapped[str] = mapped_column(String(16), nullable=False)
# 用户输入的参数(JSON Schema 校验过)
input_data: Mapped[dict | None] = mapped_column(JSON, nullable=True)
# 经过 param_mapping 翻译后传给执行器的实际参数
resolved_input: Mapped[dict | None] = mapped_column(JSON, nullable=True)
# 执行器返回的结果
result_data: Mapped[dict | None] = mapped_column(JSON, nullable=True)
# PENDING / QUEUED / RUNNING / SUCCEEDED / FAILED / TIMEOUT / CANCELED
status: Mapped[str] = mapped_column(
String(16), nullable=False, default="PENDING", index=True
)
error_message: Mapped[str | None] = mapped_column(Text, nullable=True)
# 外部执行系统返回的参考 ID(龙虾 run_id / celery task id)
external_ref: Mapped[str | None] = mapped_column(String(128), nullable=True, index=True)
# 任务触发来源:wizard / retry / schedule
source: Mapped[str] = mapped_column(String(16), default="wizard", nullable=False)
schedule_id: Mapped[int | None] = mapped_column(
ForeignKey("schedule.id", ondelete="SET NULL"), nullable=True, index=True
)
retry_of_id: Mapped[int | None] = mapped_column(
ForeignKey("task.id", ondelete="SET NULL"), nullable=True
)
operator_id: Mapped[int | None] = mapped_column(
ForeignKey("user.id", ondelete="SET NULL"), nullable=True, index=True
)
operator_name: Mapped[str | None] = mapped_column(String(64), 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)
cost_ms: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
timeout_seconds: Mapped[int] = mapped_column(Integer, default=60, nullable=False)
class TaskLog(Base):
__tablename__ = "task_log"
__table_args__ = (
UniqueConstraint("task_id", "external_event_id", name="uq_task_log_event"),
)
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
task_id: Mapped[int] = mapped_column(
ForeignKey("task.id", ondelete="CASCADE"), nullable=False, index=True
)
# INFO / WARN / ERROR / STATUS
level: Mapped[str] = mapped_column(String(8), default="INFO", nullable=False)
message: Mapped[str] = mapped_column(Text, nullable=False)
# 龙虾回调带的事件 id(同一事件不重复写)
external_event_id: Mapped[str | None] = mapped_column(String(128), nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now(), nullable=False, index=True
)