Files
backup-tool/backend/app/models.py
T
alex 13488f7b21 feat: add database models and alembic setup
- SQLAlchemy async models for sources, jobs, schedules, executions, backups, settings
- Alembic migration configuration
2026-05-11 20:43:23 +02:00

83 lines
3.6 KiB
Python

from sqlalchemy import Column, Integer, String, DateTime, Boolean, Text, ForeignKey, JSON
from sqlalchemy.orm import relationship
from datetime import datetime
from .database import Base
class Source(Base):
__tablename__ = "sources"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, nullable=False)
type = Column(String, nullable=False) # local, ssh, database
config = Column(JSON, default=dict)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
jobs = relationship("Job", back_populates="source", cascade="all, delete-orphan")
class Job(Base):
__tablename__ = "jobs"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, nullable=False)
source_id = Column(Integer, ForeignKey("sources.id"), nullable=False)
strategy = Column(String, nullable=False, default="full") # full, incremental
destination_path = Column(String, nullable=False)
exclude_patterns = Column(JSON, default=list)
enabled = Column(Boolean, default=True)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
source = relationship("Source", back_populates="jobs")
schedule = relationship("Schedule", back_populates="job", uselist=False, cascade="all, delete-orphan")
executions = relationship("JobExecution", back_populates="job", cascade="all, delete-orphan")
class Schedule(Base):
__tablename__ = "schedules"
id = Column(Integer, primary_key=True, index=True)
job_id = Column(Integer, ForeignKey("jobs.id"), unique=True, nullable=False)
cron_expression = Column(String, nullable=False)
enabled = Column(Boolean, default=True)
created_at = Column(DateTime, default=datetime.utcnow)
job = relationship("Job", back_populates="schedule")
class JobExecution(Base):
__tablename__ = "job_executions"
id = Column(Integer, primary_key=True, index=True)
job_id = Column(Integer, ForeignKey("jobs.id"), nullable=False)
status = Column(String, nullable=False, default="pending") # pending, running, success, failed, cancelled
started_at = Column(DateTime, nullable=True)
completed_at = Column(DateTime, nullable=True)
bytes_processed = Column(Integer, default=0)
bytes_backed_up = Column(Integer, default=0)
error_message = Column(Text, nullable=True)
triggered_by = Column(String, nullable=False) # manual, schedule
job = relationship("Job", back_populates="executions")
backups = relationship("Backup", back_populates="execution", cascade="all, delete-orphan")
class Backup(Base):
__tablename__ = "backups"
id = Column(Integer, primary_key=True, index=True)
execution_id = Column(Integer, ForeignKey("job_executions.id"), nullable=False)
storage_path = Column(String, nullable=False)
size_bytes = Column(Integer, default=0)
checksum = Column(String, nullable=True)
type = Column(String, nullable=False) # full, incremental
parent_backup_id = Column(Integer, ForeignKey("backups.id"), nullable=True)
created_at = Column(DateTime, default=datetime.utcnow)
execution = relationship("JobExecution", back_populates="backups")
parent_backup = relationship("Backup", remote_side=[id])
class Setting(Base):
__tablename__ = "settings"
key = Column(String, primary_key=True)
value = Column(Text, nullable=True)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)