diff --git a/tubesync/sync/tasks.py b/tubesync/sync/tasks.py index 3b02e029..73789caa 100644 --- a/tubesync/sync/tasks.py +++ b/tubesync/sync/tasks.py @@ -16,7 +16,7 @@ from PIL import Image from django.conf import settings from django.core.files.base import ContentFile from django.core.files.uploadedfile import SimpleUploadedFile -from django.db import DatabaseError, IntegrityError +from django.db import connection, DatabaseError, IntegrityError from django.db.transaction import atomic from django.utils import timezone from django.utils.translation import gettext_lazy as _ @@ -200,6 +200,16 @@ def migrate_queues(): return qs.update(queue=Val(TaskQueue.NET)) +def save_model(instance): + if 'sqlite' == connection.vendor: + # a transaction here causes too many + # database is locked errors + instance.save() + else: + with atomic(): + instance.save() + + def schedule_media_servers_update(): with atomic(): # Schedule a task to update media servers @@ -261,7 +271,7 @@ def index_source_task(source_id): # Reset any errors # TODO: determine if this affects anything source.has_failed = False - source.save() + save_model(source) # Index the source videos = source.index_media() if not videos: @@ -272,7 +282,7 @@ def index_source_task(source_id): f'is reachable') # Got some media, update the last crawl timestamp source.last_crawl = timezone.now() - source.save() + save_model(source) num_videos = len(videos) log.info(f'Found {num_videos} media items for source: {source}') fields = lambda f, m: m.get_metadata_field(f) @@ -303,7 +313,7 @@ def index_source_task(source_id): if published_dt is not None: media.published = published_dt try: - media.save() + save_model(media) except IntegrityError as e: log.error(f'Index media failed: {source} / {media} with "{e}"') else: @@ -477,7 +487,7 @@ def download_media_metadata(media_id): media.duration = media.metadata_duration # Don't filter media here, the post_save signal will handle that - media.save() + save_model(media) log.info(f'Saved {len(media.metadata)} bytes of metadata for: ' f'{source} / {media}: {media_id}') @@ -606,7 +616,7 @@ def download_media(media_id): media.downloaded_hdr = cformat['is_hdr'] else: media.downloaded_format = 'audio' - media.save() + save_model(media) # If selected, copy the thumbnail over as well if media.source.copy_thumbnails: if not media.thumb_file_exists: @@ -704,8 +714,7 @@ def save_all_media_for_source(source_id): for mn, media in enumerate(mqs, start=1): if media.uuid not in saved_later: update_task_status(task, tvn_format.format(mn)) - with atomic(): - media.save() + save_model(media) # Reset task.verbose_name to the saved value update_task_status(task, None) @@ -722,8 +731,7 @@ def refesh_formats(media_id): log.debug(f'Failed to refresh formats for: {media.source} / {media.key}: {e!s}') pass else: - with atomic(): - media.save() + save_model(media) @background(schedule=dict(priority=20, run_at=60), queue=Val(TaskQueue.FS), remove_existing_tasks=True) @@ -780,17 +788,16 @@ def wait_for_media_premiere(media_id): return now = timezone.now() if media.published < now: + # the download tasks start after the media is saved media.manual_skip = False media.skip = False - # start the download tasks - media.save() else: media.manual_skip = True media.title = _(f'Premieres in {hours(media.published - now)} hours') - media.save() task = get_media_premiere_task(media_id) if task: update_task_status(task, f'available in {hours(media.published - now)} hours') + save_model(media) @background(schedule=dict(priority=1, run_at=300), queue=Val(TaskQueue.FS), remove_existing_tasks=False) def delete_all_media_for_source(source_id, source_name):