from __future__ import annotations import enum from datetime import datetime from typing import TYPE_CHECKING from sqlalchemy import TIMESTAMP, Enum, ForeignKey, Integer, String from sqlalchemy.orm import Mapped, mapped_column, relationship from models.base import BaseModel if TYPE_CHECKING: from models.device import Device from models.user import User class SyncSessionStatus(enum.StrEnum): PENDING = "PENDING" IN_PROGRESS = "IN_PROGRESS" COMPLETED = "COMPLETED" FAILED = "FAILED" CANCELLED = "CANCELLED" class SyncSession(BaseModel): __tablename__ = "sync_sessions" __table_args__ = {"extend_existing": True} id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) device_id: Mapped[str] = mapped_column( String(255), ForeignKey("devices.id", ondelete="CASCADE"), index=True ) user_id: Mapped[int] = mapped_column( ForeignKey("users.id", ondelete="CASCADE"), index=True ) status: Mapped[SyncSessionStatus] = mapped_column( Enum(SyncSessionStatus), default=SyncSessionStatus.PENDING, index=True, ) initiated_at: Mapped[datetime] = mapped_column(TIMESTAMP(timezone=True)) completed_at: Mapped[datetime | None] = mapped_column( TIMESTAMP(timezone=True), nullable=True ) operations_planned: Mapped[int] = mapped_column(Integer, default=0) operations_completed: Mapped[int] = mapped_column(Integer, default=0) operations_failed: Mapped[int] = mapped_column(Integer, default=0) error_message: Mapped[str | None] = mapped_column(String(1000), nullable=True) device: Mapped[Device] = relationship(lazy="joined") user: Mapped[User] = relationship(lazy="joined")