tubesync/app/sync/signals.py

102 lines
3.9 KiB
Python

from django.conf import settings
from django.db.models.signals import pre_save, post_save, pre_delete, post_delete
from django.dispatch import receiver
from django.utils.translation import gettext_lazy as _
from background_task.signals import task_failed
from background_task.models import Task
from common.logger import log
from .models import Source, Media
from .tasks import (delete_index_source_task, index_source_task,
download_media_thumbnail, map_task_to_instance)
from .utils import delete_file
@receiver(pre_save, sender=Source)
def source_pre_save(sender, instance, **kwargs):
# Triggered before a source is saved, if the schedule has been updated recreate
# its indexing task
try:
existing_source = Source.objects.get(pk=instance.pk)
except Source.DoesNotExist:
# Probably not possible?
return
if existing_source.index_schedule != instance.index_schedule:
# Indexing schedule has changed, recreate the indexing task
delete_index_source_task(str(instance.pk))
verbose_name = _('Index media from source "{}"')
index_source_task(
str(instance.pk),
repeat=instance.index_schedule,
queue=str(instance.pk),
verbose_name=verbose_name.format(instance.name)
)
@receiver(post_save, sender=Source)
def source_post_save(sender, instance, created, **kwargs):
# Triggered after a source is saved
if created:
# Create a new indexing task for newly created sources
delete_index_source_task(str(instance.pk))
log.info(f'Scheduling media indexing for source: {instance.name}')
verbose_name = _('Index media from source "{}"')
index_source_task(
str(instance.pk),
repeat=instance.index_schedule,
queue=str(instance.pk),
verbose_name=verbose_name.format(instance.name)
)
@receiver(pre_delete, sender=Source)
def source_post_delete(sender, instance, **kwargs):
# Triggered before a source is deleted, delete all media objects to trigger
# the Media models post_delete signal
for media in Media.objects.filter(source=instance):
log.info(f'Deleting media for source: {instance.name} item: {media.name}')
media.delete()
@receiver(post_delete, sender=Source)
def source_post_delete(sender, instance, **kwargs):
# Triggered after a source is deleted
log.info(f'Deleting tasks for source: {instance.name}')
delete_index_source_task(str(instance.pk))
@receiver(task_failed, sender=Task)
def task_task_failed(sender, task_id, completed_task, **kwargs):
# Triggered after a source fails by reaching its max retry attempts
obj, url = map_task_to_instance(completed_task)
if isinstance(obj, Source):
log.error(f'Permanent failure for source: {obj} task: {completed_task}')
obj.has_failed = True
obj.save()
@receiver(post_save, sender=Media)
def media_post_save(sender, instance, created, **kwargs):
# Triggered after media is saved
if created:
# If the media is newly created fire a task off to download its thumbnail
metadata = instance.loaded_metadata
thumbnail_url = metadata.get('thumbnail', '')
if thumbnail_url:
log.info(f'Scheduling task to download thumbnail for: {instance.name} '
f'from: {thumbnail_url}')
verbose_name = _('Downloading media thumbnail for "{}"')
download_media_thumbnail(
str(instance.pk),
thumbnail_url,
queue=str(instance.source.pk),
verbose_name=verbose_name.format(instance.name)
)
@receiver(post_delete, sender=Media)
def media_post_delete(sender, instance, **kwargs):
# Triggered after media is deleted, delete media thumbnail
if instance.thumb:
log.info(f'Deleting thumbnail for: {instance} path: {instance.thumb.path}')
delete_file(instance.thumb.path)