first add

This commit is contained in:
2025-10-13 21:05:00 +08:00
parent c7744836e9
commit d71163df00
29 changed files with 144656 additions and 37 deletions

View File

@@ -1,3 +1,187 @@
"""任务模型(使用 SQLModel"""
from typing import Optional, List
from datetime import datetime
from enum import Enum
from sqlmodel import SQLModel, Field, Relationship, Column
from sqlalchemy import JSON
from .base import TimestampModel, generate_uuid
class JobStatus(str, Enum):
"""任务状态"""
PENDING = "pending"
RUNNING = "running"
COMPLETED = "completed"
FAILED = "failed"
CANCELLED = "cancelled"
class StepStatus(str, Enum):
"""步骤状态"""
PENDING = "pending"
RUNNING = "running"
COMPLETED = "completed"
FAILED = "failed"
SKIPPED = "skipped"
class JobBase(SQLModel):
"""Job 基础字段"""
name: str = Field(max_length=255)
description: Optional[str] = None
sequence_type: str = Field(default="nucl", max_length=20)
scaf_suffix: str = Field(default=".fna", max_length=50)
threads: int = Field(default=4, ge=1, le=32)
update_db: bool = Field(default=False)
class Job(JobBase, TimestampModel, table=True):
"""Job 数据库模型"""
__tablename__ = "jobs"
id: str = Field(
default_factory=generate_uuid,
primary_key=True,
index=True,
)
user_id: Optional[str] = Field(default=None, index=True)
status: JobStatus = Field(
default=JobStatus.PENDING,
sa_column_kwargs={"index": True},
)
input_files: List[dict] = Field(default_factory=list, sa_column=Column(JSON))
workspace_path: Optional[str] = Field(default=None, max_length=500)
result_url: Optional[str] = Field(default=None, max_length=1000)
celery_task_id: Optional[str] = Field(default=None, max_length=100, index=True)
current_step: Optional[str] = Field(default=None, max_length=100)
progress: int = Field(default=0, ge=0, le=100)
error_message: Optional[str] = None
started_at: Optional[datetime] = None
completed_at: Optional[datetime] = None
steps: List["Step"] = Relationship(
back_populates="job",
sa_relationship_kwargs={"cascade": "all, delete-orphan"},
)
logs: List["JobLog"] = Relationship(
back_populates="job",
sa_relationship_kwargs={"cascade": "all, delete-orphan"},
)
class JobCreate(JobBase):
"""创建 Job 时的请求模型"""
pass
class JobRead(JobBase):
"""读取 Job 时的响应模型"""
id: str
user_id: Optional[str]
status: JobStatus
workspace_path: Optional[str]
result_url: Optional[str]
celery_task_id: Optional[str]
current_step: Optional[str]
progress: int
error_message: Optional[str]
started_at: Optional[datetime]
completed_at: Optional[datetime]
created_at: datetime
updated_at: datetime
class JobUpdate(SQLModel):
"""更新 Job 时的请求模型"""
status: Optional[JobStatus] = None
current_step: Optional[str] = None
progress: Optional[int] = None
error_message: Optional[str] = None
started_at: Optional[datetime] = None
completed_at: Optional[datetime] = None
class StepBase(SQLModel):
"""Step 基础字段"""
step_name: str = Field(max_length=100)
step_order: int
class Step(StepBase, table=True):
"""Step 数据库模型"""
__tablename__ = "steps"
id: Optional[int] = Field(default=None, primary_key=True)
job_id: str = Field(foreign_key="jobs.id", index=True)
status: StepStatus = Field(default=StepStatus.PENDING)
celery_task_id: Optional[str] = Field(default=None, max_length=100)
log_file: Optional[str] = Field(default=None, max_length=500)
result_data: Optional[dict] = Field(default=None, sa_column=Column(JSON))
error_message: Optional[str] = None
started_at: Optional[datetime] = None
completed_at: Optional[datetime] = None
duration_seconds: Optional[int] = None
job: "Job" = Relationship(back_populates="steps")
class StepRead(StepBase):
"""读取 Step 时的响应模型"""
id: int
job_id: str
status: StepStatus
celery_task_id: Optional[str]
log_file: Optional[str]
result_data: Optional[dict]
error_message: Optional[str]
started_at: Optional[datetime]
completed_at: Optional[datetime]
duration_seconds: Optional[int]
class JobLogBase(SQLModel):
"""JobLog 基础字段"""
level: str = Field(max_length=20)
message: str
step_name: Optional[str] = Field(default=None, max_length=100)
class JobLog(JobLogBase, table=True):
"""JobLog 数据库模型"""
__tablename__ = "job_logs"
id: Optional[int] = Field(default=None, primary_key=True)
job_id: str = Field(foreign_key="jobs.id", index=True)
metadata: Optional[dict] = Field(default=None, sa_column=Column(JSON))
timestamp: datetime = Field(
default_factory=datetime.utcnow,
sa_column_kwargs={"index": True},
)
job: "Job" = Relationship(back_populates="logs")
class JobLogRead(JobLogBase):
"""读取 JobLog 时的响应模型"""
id: int
job_id: str
metadata: Optional[dict]
timestamp: datetime
"""任务模型"""
from sqlalchemy import Column, String, Integer, DateTime, JSON, Enum, Text
from sqlalchemy.sql import func