feat: settings panel + thumbnail pipeline fixes
- photos.py: stop crashing in FileResponse when a thumb hasn't been generated; return a clean 404 with Retry-After so the frontend can back off. - thumbs.py: fix process_video_thumbnail (overwrite_output, robust duration probe across stream/format, eager frame load + temp cleanup) so videos stop ending up as the gray placeholder. - library.py: new /maintenance/* endpoints — thumbnail-stats, regenerate-thumbnails (with media_type / only_failed filters), and a manual data-integrity cleanup trigger. - Frontend Settings panel (gear in TopBar) surfacing those endpoints plus a re-scan button and live thumbnail status counts. - PhotoThumbnail: stretch the auto-retry schedule for slow RAW jobs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -322,12 +322,14 @@ async def get_thumbnail(
|
||||
thumb_path = f"{thumb_dir}/{size}.webp"
|
||||
|
||||
if not os.path.exists(thumb_path):
|
||||
# Generate thumbnail on demand
|
||||
# Queue background generation (handles RAW/HEIC/video properly)
|
||||
from app.tasks.thumbs import generate_thumbnails
|
||||
generate_thumbnails.delay(photo_id)
|
||||
|
||||
# For now, return a placeholder or the original with reduced quality
|
||||
if os.path.exists(photo.filepath):
|
||||
|
||||
# Best-effort inline fallback for standard images so the first
|
||||
# request doesn't have to wait for the worker. RAW/HEIC/video
|
||||
# and missing source files fall through to a clean 404 below.
|
||||
if photo.filepath and os.path.exists(photo.filepath):
|
||||
from PIL import Image
|
||||
try:
|
||||
os.makedirs(thumb_dir, exist_ok=True)
|
||||
@@ -359,10 +361,23 @@ async def get_thumbnail(
|
||||
# Save as WebP
|
||||
img.save(thumb_path, 'WEBP', quality=85, optimize=True)
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Error generating thumbnail: {e}")
|
||||
raise HTTPException(status_code=404, detail="Could not generate thumbnail")
|
||||
|
||||
logger.warning(
|
||||
f"Inline thumbnail fallback failed for {photo_id} ({size}); "
|
||||
f"waiting on worker: {e}"
|
||||
)
|
||||
|
||||
# If the inline fallback didn't (or couldn't) produce the file,
|
||||
# tell the client to retry instead of crashing in FileResponse/nginx.
|
||||
if not os.path.exists(thumb_path):
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Thumbnail not ready",
|
||||
headers={"Retry-After": "2"},
|
||||
)
|
||||
|
||||
# Check if we're behind Nginx
|
||||
if os.environ.get('USE_X_ACCEL_REDIRECT'):
|
||||
# Use Nginx X-Accel-Redirect for better performance
|
||||
|
||||
Reference in New Issue
Block a user