From 4e68bdf9203afd4e3ed461fc046724820489a4ce Mon Sep 17 00:00:00 2001 From: npeter83 Date: Sat, 11 Jul 2026 19:44:53 +0200 Subject: [PATCH] fix(config): honor DB-overridable download layout + retention (env-vs-DB drift) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit download_layout and download_retention_days are registered ConfigSpec keys (admin-editable on the Configuration page), but worker.py read them from settings.* (env) at download/edit finalize time — so an admin's edit was a silent no-op (files kept the old layout; TTL stayed at the env default). Read them via sysconfig (_download_settings), which falls back to the env default when there's no DB override. Same class as the Downloads B3 fix. ruff clean, localdev boots, re-review clean. --- backend/app/worker.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/backend/app/worker.py b/backend/app/worker.py index ab06b3f..b35d6f1 100644 --- a/backend/app/worker.py +++ b/backend/app/worker.py @@ -26,6 +26,7 @@ from pathlib import Path import yt_dlp from sqlalchemy import text +from app import sysconfig from app.config import settings from app.db import SessionLocal from app.downloads import edit as editmod @@ -371,6 +372,16 @@ def _extract_with_fallback(job_id: int, asset_id: int, url: str, spec: dict, sta raise last_exc # unreachable (loop either returns or raises) +def _download_settings() -> tuple[str, int]: + """Layout + retention days from the DB config (admin-overridable on the Configuration page), + falling back to the env defaults. Read here, not from `settings`, so an admin edit takes effect.""" + with SessionLocal() as db: + return ( + sysconfig.get_str(db, "download_layout"), + sysconfig.get_int(db, "download_retention_days"), + ) + + def _download(job_id: int, asset_id: int, source_kind: str, source_ref: str, spec: dict) -> None: staging = _staging_dir(asset_id) try: @@ -402,14 +413,15 @@ def _download(job_id: int, asset_id: int, source_kind: str, source_ref: str, spe thumbnail_url=info.get("thumbnail"), ) - rel = storage.rel_path(meta, ext, settings.download_layout) + layout, retention_days = _download_settings() + rel = storage.rel_path(meta, ext, layout) thumb = _find_thumbnail(staging, produced) storage.place_file(produced, settings.download_root, rel) nfo_ok = storage.write_sidecars(settings.download_root, rel, meta, thumb) final = storage.abs_path(settings.download_root, rel) size = final.stat().st_size if final.exists() else None - expires = datetime.now(timezone.utc) + timedelta(days=settings.download_retention_days) + expires = datetime.now(timezone.utc) + timedelta(days=retention_days) with SessionLocal() as db: asset = db.get(MediaAsset, asset_id) @@ -554,7 +566,8 @@ def _process_edit(job_id: int, asset_id: int) -> None: storage.place_file(dest_staging, settings.download_root, rel) final = storage.abs_path(settings.download_root, rel) size = final.stat().st_size if final.exists() else None - expires = datetime.now(timezone.utc) + timedelta(days=settings.download_retention_days) + _, retention_days = _download_settings() + expires = datetime.now(timezone.utc) + timedelta(days=retention_days) with SessionLocal() as db: asset = db.get(MediaAsset, asset_id)