chore: snapshot workflow migration progress
This commit is contained in:
@@ -10,6 +10,7 @@ from sqlalchemy import select, func
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.database import get_db
|
||||
from app.core.render_paths import resolve_result_path
|
||||
from app.domains.auth.models import User
|
||||
from app.domains.media.models import MediaAsset, MediaAssetType
|
||||
from app.domains.media.schemas import MediaAssetOut, MediaAssetBrowseItem, MediaAssetBrowseResponse
|
||||
@@ -19,6 +20,10 @@ from app.utils.auth import get_current_user
|
||||
router = APIRouter(prefix="/api/media", tags=["media"], redirect_slashes=False)
|
||||
|
||||
|
||||
def _resolve_asset_candidate(key: str):
|
||||
return resolve_result_path(key)
|
||||
|
||||
|
||||
async def _resolve_thumbnails_bulk(db: AsyncSession, assets: list) -> None:
|
||||
"""Resolve thumbnail_url for assets using the same priority as product pages.
|
||||
|
||||
@@ -275,15 +280,8 @@ async def thumbnail_asset(
|
||||
raise HTTPException(404, "Not a previewable asset")
|
||||
|
||||
key = asset.storage_key
|
||||
from app.config import settings
|
||||
candidate = Path(key) if Path(key).is_absolute() else Path(settings.upload_dir) / key
|
||||
if not candidate.exists() and "/shared/renders/" in key:
|
||||
parts = key.split("/")
|
||||
if len(parts) >= 2:
|
||||
remapped = Path(settings.upload_dir) / "renders" / parts[-2] / parts[-1]
|
||||
if remapped.exists():
|
||||
candidate = remapped
|
||||
if candidate.exists():
|
||||
candidate = _resolve_asset_candidate(key)
|
||||
if candidate is not None and candidate.exists():
|
||||
return FileResponse(
|
||||
str(candidate), media_type=mime,
|
||||
headers={"Cache-Control": "max-age=86400, public"},
|
||||
@@ -314,22 +312,8 @@ async def download_asset(
|
||||
mime = asset.mime_type or "application/octet-stream"
|
||||
|
||||
# Local file path (absolute or relative to UPLOAD_DIR)
|
||||
from app.config import settings
|
||||
candidate = Path(key)
|
||||
if not candidate.is_absolute():
|
||||
candidate = Path(settings.upload_dir) / key
|
||||
# Legacy path remapping: /shared/renders/{uuid}/{file} → UPLOAD_DIR/renders/{uuid}/{file}
|
||||
if not candidate.exists() and "/shared/renders/" in key:
|
||||
import logging
|
||||
parts = key.split("/")
|
||||
if len(parts) >= 2:
|
||||
remapped = Path(settings.upload_dir) / "renders" / parts[-2] / parts[-1]
|
||||
if remapped.exists():
|
||||
logging.getLogger(__name__).warning(
|
||||
"Remapped legacy path %s → %s", key, remapped
|
||||
)
|
||||
candidate = remapped
|
||||
if candidate.exists():
|
||||
candidate = _resolve_asset_candidate(key)
|
||||
if candidate is not None and candidate.exists():
|
||||
ext = candidate.suffix.lstrip(".")
|
||||
fname = f"{asset.asset_type.value}_{asset_id}.{ext or 'bin'}"
|
||||
return FileResponse(
|
||||
@@ -395,11 +379,8 @@ async def zip_download(
|
||||
fname = base
|
||||
try:
|
||||
# Check absolute path first (local filesystem)
|
||||
candidate = Path(key)
|
||||
if not candidate.is_absolute():
|
||||
from app.config import settings
|
||||
candidate = Path(settings.upload_dir) / key
|
||||
if candidate.exists():
|
||||
candidate = _resolve_asset_candidate(key)
|
||||
if candidate is not None and candidate.exists():
|
||||
data = candidate.read_bytes()
|
||||
else:
|
||||
data = storage.download_bytes(key)
|
||||
@@ -440,7 +421,7 @@ async def batch_delete_assets(
|
||||
):
|
||||
"""Permanently delete multiple MediaAsset records."""
|
||||
from app.utils.auth import require_global_admin
|
||||
require_global_admin(_user)
|
||||
await require_global_admin(_user)
|
||||
|
||||
deleted = 0
|
||||
for aid in asset_ids:
|
||||
@@ -461,23 +442,15 @@ async def cleanup_orphaned_assets(
|
||||
"""
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from app.config import settings
|
||||
from app.core.storage import get_storage
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
storage = get_storage()
|
||||
|
||||
def _file_exists(key: str) -> bool:
|
||||
candidate = Path(key) if Path(key).is_absolute() else Path(settings.upload_dir) / key
|
||||
if candidate.exists():
|
||||
candidate = _resolve_asset_candidate(key)
|
||||
if candidate is not None and candidate.exists():
|
||||
return True
|
||||
# Legacy path remapping
|
||||
if "/shared/renders/" in key:
|
||||
parts = key.split("/")
|
||||
if len(parts) >= 2:
|
||||
remapped = Path(settings.upload_dir) / "renders" / parts[-2] / parts[-1]
|
||||
if remapped.exists():
|
||||
return True
|
||||
# Check MinIO
|
||||
try:
|
||||
storage.download_bytes(key)
|
||||
|
||||
Reference in New Issue
Block a user