- Docker Deployment Fixes: - Switch base images to docker.m.daocloud.io to resolve registry 401 errors - Add Postgres and Redis services to docker-compose.traefik.yml - Fix frontend build: replace missing icons (Globe->Location, Chart->TrendCharts) - Fix frontend build: resolve pnpm CI/TTY issues and frozen lockfile errors - Add missing backend dependencies (sqlalchemy, psycopg2, redis-py, celery, docker-py) in pixi.toml - Ensure database tables are created on startup (lifespan event) - Backend Internationalization (i18n): - Add backend/app/core/i18n.py for locale handling - Update API endpoints (jobs, tasks, uploads, results) to return localized messages - Support 'Accept-Language' header (en/zh) - Documentation: - Update DOCKER_DEPLOYMENT.md with new architecture and troubleshooting - Update AGENTS.md with latest stack details and deployment steps - Update @fix_plan.md status Co-Authored-By: Claude <noreply@anthropic.com>
93 lines
2.9 KiB
Python
93 lines
2.9 KiB
Python
"""任务模型"""
|
|
from sqlalchemy import Column, String, Integer, DateTime, JSON, Enum, Text
|
|
from sqlalchemy.sql import func
|
|
import enum
|
|
|
|
from ..database import Base
|
|
|
|
|
|
class JobStatus(str, enum.Enum):
|
|
"""任务状态"""
|
|
PENDING = "pending" # 等待进入队列
|
|
QUEUED = "queued" # 已排队,等待执行
|
|
RUNNING = "running" # 正在执行
|
|
COMPLETED = "completed" # 执行完成
|
|
FAILED = "failed" # 执行失败
|
|
|
|
|
|
class StepStatus(str, enum.Enum):
|
|
"""步骤状态"""
|
|
PENDING = "PENDING"
|
|
RUNNING = "RUNNING"
|
|
SUCCESS = "SUCCESS"
|
|
FAILED = "FAILED"
|
|
SKIPPED = "SKIPPED"
|
|
|
|
|
|
class Job(Base):
|
|
__tablename__ = "jobs"
|
|
|
|
id = Column(String, primary_key=True, index=True)
|
|
celery_task_id = Column(String, nullable=True, index=True)
|
|
status = Column(Enum(JobStatus), default=JobStatus.PENDING, index=True)
|
|
|
|
input_files = Column(JSON)
|
|
sequence_type = Column(String, default="nucl")
|
|
scaf_suffix = Column(String, default=".fna")
|
|
threads = Column(Integer, default=4)
|
|
|
|
# 分析参数
|
|
min_identity = Column(Integer, default=80) # 存储为百分比 (0-100)
|
|
min_coverage = Column(Integer, default=60)
|
|
allow_unknown_families = Column(Integer, default=0) # 0 = False, 1 = True
|
|
require_index_hit = Column(Integer, default=1)
|
|
|
|
result_url = Column(String, nullable=True)
|
|
logs = Column(Text, nullable=True)
|
|
error_message = Column(Text, nullable=True)
|
|
|
|
# 队列位置
|
|
queue_position = Column(Integer, nullable=True)
|
|
|
|
# 进度信息
|
|
current_stage = Column(String, nullable=True) # digger, shoter, plots, bundle
|
|
progress_percent = Column(Integer, default=0)
|
|
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now(), index=True)
|
|
started_at = Column(DateTime(timezone=True), nullable=True)
|
|
completed_at = Column(DateTime(timezone=True), nullable=True)
|
|
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
|
|
|
|
|
class Step(Base):
|
|
"""任务步骤"""
|
|
__tablename__ = "job_steps"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
job_id = Column(String, index=True) # ForeignKey("jobs.id") - simplified for SQLite/No-Relation
|
|
step_id = Column(String) # digger, shoter, etc.
|
|
name = Column(String)
|
|
status = Column(Enum(StepStatus), default=StepStatus.PENDING)
|
|
|
|
start_at = Column(DateTime(timezone=True), nullable=True)
|
|
end_at = Column(DateTime(timezone=True), nullable=True)
|
|
duration_ms = Column(Integer, nullable=True)
|
|
|
|
summary = Column(Text, nullable=True)
|
|
error = Column(Text, nullable=True)
|
|
|
|
|
|
class JobLog(Base):
|
|
"""任务日志"""
|
|
__tablename__ = "job_logs"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
job_id = Column(String, index=True)
|
|
step_id = Column(String, nullable=True)
|
|
|
|
level = Column(String, default="INFO")
|
|
message = Column(Text)
|
|
timestamp = Column(DateTime(timezone=True), server_default=func.now())
|
|
seq = Column(Integer, default=0)
|
|
|