130 lines
5.0 KiB
Python
130 lines
5.0 KiB
Python
"""
|
|
Database models for scheduled downloads.
|
|
"""
|
|
|
|
from sqlalchemy import Column, String, Integer, Boolean, DateTime, Time, ForeignKey, Text
|
|
from sqlalchemy.orm import relationship
|
|
from datetime import datetime, time as time_type
|
|
import uuid
|
|
import pytz
|
|
|
|
from .database import Base
|
|
|
|
|
|
def generate_uuid():
|
|
"""Generate a UUID string"""
|
|
return str(uuid.uuid4())
|
|
|
|
|
|
class ScheduledTask(Base):
|
|
"""
|
|
Represents a scheduled download task.
|
|
Tasks run at a specified time each day.
|
|
"""
|
|
__tablename__ = "scheduled_tasks"
|
|
|
|
# Primary key
|
|
id = Column(String(36), primary_key=True, default=generate_uuid)
|
|
|
|
# Task identification
|
|
name = Column(String(255), nullable=False, index=True)
|
|
enabled = Column(Boolean, default=True, nullable=False, index=True)
|
|
|
|
# Download configuration
|
|
source_type = Column(String(20), nullable=False) # "subreddit" or "user"
|
|
source_name = Column(String(255), nullable=False, index=True)
|
|
download_mode = Column(String(20), nullable=False) # "download", "archive", "clone"
|
|
|
|
# Filter options
|
|
limit = Column(Integer, default=25, nullable=False)
|
|
sort = Column(String(20), default="hot", nullable=False)
|
|
time_filter = Column(String(20), default="day", nullable=False) # Always "day" for daily tasks
|
|
min_score = Column(Integer, nullable=True)
|
|
no_dupes = Column(Boolean, default=True, nullable=False) # Always true for scheduled
|
|
simple_check = Column(Boolean, default=False, nullable=False)
|
|
|
|
# Scheduling
|
|
schedule_frequency = Column(String(20), default="daily", nullable=False)
|
|
run_time = Column(Time, nullable=False) # Time of day to run
|
|
timezone = Column(String(50), default="UTC", nullable=False)
|
|
|
|
# Metadata
|
|
created_at = Column(DateTime, default=lambda: datetime.now(pytz.UTC), nullable=False)
|
|
updated_at = Column(DateTime, default=lambda: datetime.now(pytz.UTC), onupdate=lambda: datetime.now(pytz.UTC), nullable=False)
|
|
last_run_at = Column(DateTime, nullable=True, index=True)
|
|
next_run_at = Column(DateTime, nullable=True, index=True)
|
|
|
|
# Authentication
|
|
auth_state = Column(String(255), nullable=True)
|
|
|
|
# Relationships
|
|
executions = relationship("TaskExecutionHistory", back_populates="task", cascade="all, delete-orphan")
|
|
|
|
def to_dict(self):
|
|
"""Convert to dictionary for JSON serialization"""
|
|
return {
|
|
"id": self.id,
|
|
"name": self.name,
|
|
"enabled": self.enabled,
|
|
"source_type": self.source_type,
|
|
"source_name": self.source_name,
|
|
"download_mode": self.download_mode,
|
|
"limit": self.limit,
|
|
"sort": self.sort,
|
|
"time_filter": self.time_filter,
|
|
"min_score": self.min_score,
|
|
"no_dupes": self.no_dupes,
|
|
"simple_check": self.simple_check,
|
|
"schedule_frequency": self.schedule_frequency,
|
|
"run_time": self.run_time.isoformat() if self.run_time else None,
|
|
"timezone": self.timezone,
|
|
"created_at": self.created_at.isoformat() if self.created_at else None,
|
|
"updated_at": self.updated_at.isoformat() if self.updated_at else None,
|
|
"last_run_at": self.last_run_at.isoformat() if self.last_run_at else None,
|
|
"next_run_at": self.next_run_at.isoformat() if self.next_run_at else None,
|
|
"auth_state": self.auth_state
|
|
}
|
|
|
|
|
|
class TaskExecutionHistory(Base):
|
|
"""
|
|
Records each execution of a scheduled task.
|
|
Tracks success/failure and metrics.
|
|
"""
|
|
__tablename__ = "task_execution_history"
|
|
|
|
# Primary key
|
|
id = Column(String(36), primary_key=True, default=generate_uuid)
|
|
|
|
# Foreign key to task
|
|
task_id = Column(String(36), ForeignKey("scheduled_tasks.id", ondelete="CASCADE"), nullable=False, index=True)
|
|
|
|
# Execution details
|
|
started_at = Column(DateTime, default=lambda: datetime.now(pytz.UTC), nullable=False, index=True)
|
|
completed_at = Column(DateTime, nullable=True)
|
|
status = Column(String(20), default="queued", nullable=False, index=True) # queued, running, success, failed, skipped
|
|
|
|
# Results
|
|
items_found = Column(Integer, default=0, nullable=False)
|
|
items_downloaded = Column(Integer, default=0, nullable=False)
|
|
error_message = Column(Text, nullable=True)
|
|
|
|
# Link to download
|
|
download_id = Column(String(255), nullable=True, index=True)
|
|
|
|
# Relationships
|
|
task = relationship("ScheduledTask", back_populates="executions")
|
|
|
|
def to_dict(self):
|
|
"""Convert to dictionary for JSON serialization"""
|
|
return {
|
|
"id": self.id,
|
|
"task_id": self.task_id,
|
|
"started_at": self.started_at.isoformat() if self.started_at else None,
|
|
"completed_at": self.completed_at.isoformat() if self.completed_at else None,
|
|
"status": self.status,
|
|
"items_found": self.items_found,
|
|
"items_downloaded": self.items_downloaded,
|
|
"error_message": self.error_message,
|
|
"download_id": self.download_id
|
|
} |