changes to mobile styling in modal view, complete reword of backend worker system
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
# app/tasks/thumbnail.py
|
||||
"""
|
||||
Thumbnail generation tasks.
|
||||
|
||||
Handles generating thumbnails for images and videos,
|
||||
both individually and in bulk.
|
||||
"""
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
from app.celery_app import celery
|
||||
from app import db
|
||||
from app.models import ImageRecord, ImportTask
|
||||
|
||||
log = logging.getLogger('celery.tasks.thumbnail')
|
||||
|
||||
|
||||
@celery.task(bind=True, name='app.tasks.thumbnail.generate_thumbnail_task',
|
||||
max_retries=2, default_retry_delay=30)
|
||||
def generate_thumbnail_task(self, image_id: int, overwrite: bool = False):
|
||||
"""
|
||||
Generate thumbnail for a single image/video.
|
||||
|
||||
Args:
|
||||
image_id: ID of the ImageRecord
|
||||
overwrite: Whether to overwrite existing thumbnail
|
||||
|
||||
Returns:
|
||||
dict with status and thumbnail path
|
||||
"""
|
||||
from app.utils.image_importer import generate_thumbnail, generate_video_thumbnail_mirrored
|
||||
|
||||
record = ImageRecord.query.get(image_id)
|
||||
if not record:
|
||||
log.warning(f"Image {image_id} not found")
|
||||
return {'error': 'Image not found'}
|
||||
|
||||
try:
|
||||
filepath = record.filepath
|
||||
if not filepath:
|
||||
return {'error': 'No filepath'}
|
||||
|
||||
# Check if thumbnail already exists and we're not overwriting
|
||||
if record.thumb_path and not overwrite:
|
||||
import os
|
||||
if os.path.exists(record.thumb_path):
|
||||
return {'status': 'exists', 'thumb_path': record.thumb_path}
|
||||
|
||||
log.debug(f"Generating thumbnail for: {filepath}")
|
||||
|
||||
is_video = filepath.lower().endswith(('.mp4', '.mov', '.webm', '.avi', '.mkv'))
|
||||
|
||||
if is_video:
|
||||
thumb_path = generate_video_thumbnail_mirrored(filepath)
|
||||
else:
|
||||
thumb_path = generate_thumbnail(filepath, overwrite=overwrite)
|
||||
|
||||
if thumb_path:
|
||||
record.thumb_path = thumb_path
|
||||
db.session.commit()
|
||||
log.info(f"Generated thumbnail: {thumb_path}")
|
||||
return {'status': 'success', 'thumb_path': thumb_path}
|
||||
else:
|
||||
return {'status': 'failed', 'error': 'Thumbnail generation returned None'}
|
||||
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
log.error(f"Thumbnail generation failed for {image_id}: {e}", exc_info=True)
|
||||
raise self.retry(exc=e)
|
||||
|
||||
|
||||
@celery.task(name='app.tasks.thumbnail.regenerate_all_thumbnails')
|
||||
def regenerate_all_thumbnails(batch_size: int = 100, overwrite: bool = True):
|
||||
"""
|
||||
Queue thumbnail regeneration for all images.
|
||||
|
||||
Processes images in batches to avoid memory issues.
|
||||
|
||||
Args:
|
||||
batch_size: Number of images to process per batch
|
||||
overwrite: Whether to overwrite existing thumbnails
|
||||
|
||||
Returns:
|
||||
dict with count of queued tasks
|
||||
"""
|
||||
log.info("Starting bulk thumbnail regeneration")
|
||||
|
||||
count = 0
|
||||
last_id = 0
|
||||
|
||||
while True:
|
||||
records = ImageRecord.query.filter(
|
||||
ImageRecord.id > last_id,
|
||||
ImageRecord.filepath.isnot(None)
|
||||
).order_by(ImageRecord.id.asc()).limit(batch_size).all()
|
||||
|
||||
if not records:
|
||||
break
|
||||
|
||||
for record in records:
|
||||
generate_thumbnail_task.delay(record.id, overwrite=overwrite)
|
||||
count += 1
|
||||
|
||||
last_id = records[-1].id
|
||||
log.info(f"Queued {count} thumbnail tasks so far...")
|
||||
|
||||
log.info(f"Thumbnail regeneration complete: queued {count} tasks")
|
||||
return {'queued': count}
|
||||
|
||||
|
||||
@celery.task(name='app.tasks.thumbnail.regenerate_missing_thumbnails')
|
||||
def regenerate_missing_thumbnails(batch_size: int = 100):
|
||||
"""
|
||||
Generate thumbnails only for images that don't have them.
|
||||
|
||||
Args:
|
||||
batch_size: Number of images to process per batch
|
||||
|
||||
Returns:
|
||||
dict with count of queued tasks
|
||||
"""
|
||||
import os
|
||||
|
||||
log.info("Checking for missing thumbnails")
|
||||
|
||||
count = 0
|
||||
last_id = 0
|
||||
|
||||
while True:
|
||||
records = ImageRecord.query.filter(
|
||||
ImageRecord.id > last_id,
|
||||
ImageRecord.filepath.isnot(None)
|
||||
).order_by(ImageRecord.id.asc()).limit(batch_size).all()
|
||||
|
||||
if not records:
|
||||
break
|
||||
|
||||
for record in records:
|
||||
# Check if thumbnail is missing
|
||||
needs_thumb = False
|
||||
if not record.thumb_path:
|
||||
needs_thumb = True
|
||||
elif not os.path.exists(record.thumb_path):
|
||||
needs_thumb = True
|
||||
|
||||
if needs_thumb:
|
||||
generate_thumbnail_task.delay(record.id, overwrite=False)
|
||||
count += 1
|
||||
|
||||
last_id = records[-1].id
|
||||
|
||||
log.info(f"Missing thumbnail check complete: queued {count} tasks")
|
||||
return {'queued': count}
|
||||
Reference in New Issue
Block a user