120 lines
4.9 KiB
Python
Raw Permalink Normal View History

2025-12-10 12:02:17 +08:00
from __future__ import annotations
from datetime import datetime
from enum import Enum
from typing import Optional
from sqlalchemy import DateTime, Enum as SAEnum, ForeignKey, Index, JSON, String, UniqueConstraint, text
from sqlalchemy.dialects.mysql import BIGINT, INTEGER, TINYINT
from sqlalchemy.orm import Mapped, mapped_column, relationship
from backend.db.base import Base
class JobType(str, Enum):
SYNC_INSTANCES = "SYNC_INSTANCES"
START_INSTANCES = "START_INSTANCES"
STOP_INSTANCES = "STOP_INSTANCES"
REBOOT_INSTANCES = "REBOOT_INSTANCES"
TERMINATE_INSTANCES = "TERMINATE_INSTANCES"
CREATE_INSTANCES = "CREATE_INSTANCES"
class JobStatus(str, Enum):
PENDING = "PENDING"
RUNNING = "RUNNING"
SUCCESS = "SUCCESS"
FAILED = "FAILED"
class JobItemResourceType(str, Enum):
INSTANCE = "INSTANCE"
OTHER = "OTHER"
class JobItemAction(str, Enum):
CREATE = "CREATE"
START = "START"
STOP = "STOP"
REBOOT = "REBOOT"
TERMINATE = "TERMINATE"
SYNC = "SYNC"
class JobItemStatus(str, Enum):
PENDING = "PENDING"
RUNNING = "RUNNING"
SUCCESS = "SUCCESS"
FAILED = "FAILED"
SKIPPED = "SKIPPED"
class Job(Base):
__tablename__ = "jobs"
__table_args__ = (
UniqueConstraint("job_uuid", name="uniq_job_uuid"),
Index("idx_jobs_type", "job_type"),
Index("idx_jobs_status", "status"),
Index("idx_jobs_created_at", "created_at"),
)
id: Mapped[int] = mapped_column(BIGINT(unsigned=True), primary_key=True, autoincrement=True)
job_uuid: Mapped[str] = mapped_column(String(32), nullable=False)
job_type: Mapped[JobType] = mapped_column(SAEnum(JobType), nullable=False)
status: Mapped[JobStatus] = mapped_column(SAEnum(JobStatus), nullable=False, server_default=text("'PENDING'"))
progress: Mapped[int] = mapped_column(TINYINT(unsigned=True), nullable=False, server_default=text("0"))
total_count: Mapped[Optional[int]] = mapped_column(INTEGER(unsigned=True), server_default=text("0"))
success_count: Mapped[Optional[int]] = mapped_column(INTEGER(unsigned=True), server_default=text("0"))
fail_count: Mapped[Optional[int]] = mapped_column(INTEGER(unsigned=True), server_default=text("0"))
skipped_count: Mapped[Optional[int]] = mapped_column(INTEGER(unsigned=True), server_default=text("0"))
payload: Mapped[Optional[dict]] = mapped_column(JSON)
error_message: Mapped[Optional[str]] = mapped_column(String(512))
created_by_user_id: Mapped[Optional[int]] = mapped_column(
ForeignKey("users.id", ondelete="SET NULL", onupdate="CASCADE")
)
created_for_customer: Mapped[Optional[int]] = mapped_column(
ForeignKey("customers.id", ondelete="SET NULL", onupdate="CASCADE")
)
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=text("CURRENT_TIMESTAMP"), nullable=False)
started_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
finished_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
updated_at: Mapped[datetime] = mapped_column(
DateTime, server_default=text("CURRENT_TIMESTAMP"), onupdate=text("CURRENT_TIMESTAMP"), nullable=False
)
items: Mapped[list["JobItem"]] = relationship("JobItem", back_populates="job")
class JobItem(Base):
__tablename__ = "job_items"
__table_args__ = (
Index("idx_job_items_job", "job_id"),
Index("idx_job_items_instance", "resource_id"),
Index("idx_job_items_status", "status"),
)
id: Mapped[int] = mapped_column(BIGINT(unsigned=True), primary_key=True, autoincrement=True)
job_id: Mapped[int] = mapped_column(ForeignKey("jobs.id", ondelete="CASCADE", onupdate="CASCADE"), nullable=False)
resource_type: Mapped[JobItemResourceType] = mapped_column(
SAEnum(JobItemResourceType), nullable=False, server_default=text("'INSTANCE'")
)
resource_id: Mapped[Optional[int]] = mapped_column(
ForeignKey("instances.id", ondelete="SET NULL", onupdate="CASCADE")
)
account_id: Mapped[Optional[str]] = mapped_column(String(32))
region: Mapped[Optional[str]] = mapped_column(String(32))
instance_id: Mapped[Optional[str]] = mapped_column(String(32))
action: Mapped[JobItemAction] = mapped_column(SAEnum(JobItemAction), nullable=False)
status: Mapped[JobItemStatus] = mapped_column(
SAEnum(JobItemStatus), nullable=False, server_default=text("'PENDING'")
)
error_message: Mapped[Optional[str]] = mapped_column(String(512))
extra: Mapped[Optional[dict]] = mapped_column(JSON)
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=text("CURRENT_TIMESTAMP"), nullable=False)
updated_at: Mapped[datetime] = mapped_column(
DateTime, server_default=text("CURRENT_TIMESTAMP"), onupdate=text("CURRENT_TIMESTAMP"), nullable=False
)
job: Mapped["Job"] = relationship("Job", back_populates="items")
instance: Mapped[Optional["Instance"]] = relationship("Instance", back_populates="job_items")