import json from pathlib import Path from uuid import uuid4 from app.core.config import Settings from app.models.schemas import ChannelProfile, JobSnapshot, utc_now class JobStore: def __init__(self, settings: Settings) -> None: self.settings = settings self.root = settings.storage_dir self.jobs_root = self.root / "jobs" self.jobs_root.mkdir(parents=True, exist_ok=True) def create_job(self, profile: ChannelProfile, source: dict) -> JobSnapshot: job_id = uuid4().hex job_dir = self.job_dir(job_id) job_dir.mkdir(parents=True, exist_ok=True) snapshot = JobSnapshot( id=job_id, status="queued", progress=0, message="Queued", source=source, profile=profile, ) self.save_job(snapshot) return snapshot def job_dir(self, job_id: str) -> Path: return self.jobs_root / job_id def media_url(self, job_id: str, filename: str) -> str: return f"/media/jobs/{job_id}/{filename}" def save_job(self, snapshot: JobSnapshot) -> JobSnapshot: snapshot.updated_at = utc_now() path = self.job_dir(snapshot.id) / "job.json" path.write_text(snapshot.model_dump_json(indent=2), encoding="utf-8") return snapshot def get_job(self, job_id: str) -> JobSnapshot: path = self.job_dir(job_id) / "job.json" if not path.exists(): raise FileNotFoundError(job_id) data = json.loads(path.read_text(encoding="utf-8")) return JobSnapshot.model_validate(data) def update_job(self, job_id: str, **updates) -> JobSnapshot: snapshot = self.get_job(job_id) updated = snapshot.model_copy(update=updates) return self.save_job(updated) def write_json(self, job_id: str, filename: str, payload: object) -> Path: path = self.job_dir(job_id) / filename path.write_text(json.dumps(payload, indent=2, ensure_ascii=False), encoding="utf-8") return path