mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-07-27 12:04:12 +00:00
Delete celery tasks properly during m3u account deletion.
This commit is contained in:
parent
8779e6a8cf
commit
6afccadf74
2 changed files with 83 additions and 5 deletions
|
|
@ -2,9 +2,12 @@
|
|||
from django.db.models.signals import post_save, post_delete, pre_save
|
||||
from django.dispatch import receiver
|
||||
from .models import M3UAccount
|
||||
from .tasks import refresh_single_m3u_account, refresh_m3u_groups
|
||||
from .tasks import refresh_single_m3u_account, refresh_m3u_groups, delete_m3u_refresh_task_by_id
|
||||
from django_celery_beat.models import PeriodicTask, IntervalSchedule
|
||||
import json
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@receiver(post_save, sender=M3UAccount)
|
||||
def refresh_account_on_save(sender, instance, created, **kwargs):
|
||||
|
|
@ -65,9 +68,21 @@ def delete_refresh_task(sender, instance, **kwargs):
|
|||
"""
|
||||
Delete the associated Celery Beat periodic task when a Channel is deleted.
|
||||
"""
|
||||
if instance.refresh_task:
|
||||
instance.refresh_task.interval.delete()
|
||||
instance.refresh_task.delete()
|
||||
try:
|
||||
# First try the foreign key relationship to find the task ID
|
||||
task = None
|
||||
if instance.refresh_task:
|
||||
logger.info(f"Found task via foreign key: {instance.refresh_task.id} for M3UAccount {instance.id}")
|
||||
task = instance.refresh_task
|
||||
|
||||
# Use the helper function to delete the task
|
||||
if task:
|
||||
delete_m3u_refresh_task_by_id(instance.id)
|
||||
else:
|
||||
# Otherwise use the helper function
|
||||
delete_m3u_refresh_task_by_id(instance.id)
|
||||
except Exception as e:
|
||||
logger.error(f"Error in delete_refresh_task signal handler: {str(e)}", exc_info=True)
|
||||
|
||||
@receiver(pre_save, sender=M3UAccount)
|
||||
def update_status_on_active_change(sender, instance, **kwargs):
|
||||
|
|
|
|||
|
|
@ -733,6 +733,60 @@ def refresh_m3u_groups(account_id, use_cache=False, full_refresh=False):
|
|||
|
||||
return extinf_data, groups
|
||||
|
||||
def delete_m3u_refresh_task_by_id(account_id):
|
||||
"""
|
||||
Delete the periodic task associated with an M3U account ID.
|
||||
Can be called directly or from the post_delete signal.
|
||||
Returns True if a task was found and deleted, False otherwise.
|
||||
"""
|
||||
try:
|
||||
task = None
|
||||
task_name = f"m3u_account-refresh-{account_id}"
|
||||
|
||||
# Look for task by name
|
||||
try:
|
||||
from django_celery_beat.models import PeriodicTask, IntervalSchedule
|
||||
task = PeriodicTask.objects.get(name=task_name)
|
||||
logger.info(f"Found task by name: {task.id} for M3UAccount {account_id}")
|
||||
except PeriodicTask.DoesNotExist:
|
||||
logger.warning(f"No PeriodicTask found with name {task_name}")
|
||||
return False
|
||||
|
||||
# Now delete the task and its interval
|
||||
if task:
|
||||
# Store interval info before deleting the task
|
||||
interval_id = None
|
||||
if hasattr(task, 'interval') and task.interval:
|
||||
interval_id = task.interval.id
|
||||
|
||||
# Count how many TOTAL tasks use this interval (including this one)
|
||||
tasks_with_same_interval = PeriodicTask.objects.filter(interval_id=interval_id).count()
|
||||
logger.info(f"Interval {interval_id} is used by {tasks_with_same_interval} tasks total")
|
||||
|
||||
# Delete the task first
|
||||
task_id = task.id
|
||||
task.delete()
|
||||
logger.info(f"Successfully deleted periodic task {task_id}")
|
||||
|
||||
# Now check if we should delete the interval
|
||||
# We only delete if it was the ONLY task using this interval
|
||||
if interval_id and tasks_with_same_interval == 1:
|
||||
try:
|
||||
interval = IntervalSchedule.objects.get(id=interval_id)
|
||||
logger.info(f"Deleting interval schedule {interval_id} (not shared with other tasks)")
|
||||
interval.delete()
|
||||
logger.info(f"Successfully deleted interval {interval_id}")
|
||||
except IntervalSchedule.DoesNotExist:
|
||||
logger.warning(f"Interval {interval_id} no longer exists")
|
||||
elif interval_id:
|
||||
logger.info(f"Not deleting interval {interval_id} as it's shared with {tasks_with_same_interval-1} other tasks")
|
||||
|
||||
return True
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error(f"Error deleting periodic task for M3UAccount {account_id}: {str(e)}", exc_info=True)
|
||||
return False
|
||||
|
||||
@shared_task
|
||||
def refresh_single_m3u_account(account_id):
|
||||
"""Splits M3U processing into chunks and dispatches them as parallel tasks."""
|
||||
|
|
@ -758,8 +812,17 @@ def refresh_single_m3u_account(account_id):
|
|||
|
||||
filters = list(account.filters.all())
|
||||
except M3UAccount.DoesNotExist:
|
||||
# The M3U account doesn't exist, so delete the periodic task if it exists
|
||||
logger.warning(f"M3U account with ID {account_id} not found, but task was triggered. Cleaning up orphaned task.")
|
||||
|
||||
# Call the helper function to delete the task
|
||||
if delete_m3u_refresh_task_by_id(account_id):
|
||||
logger.info(f"Successfully cleaned up orphaned task for M3U account {account_id}")
|
||||
else:
|
||||
logger.info(f"No orphaned task found for M3U account {account_id}")
|
||||
|
||||
release_task_lock('refresh_single_m3u_account', account_id)
|
||||
return f"M3UAccount with ID={account_id} not found or inactive."
|
||||
return f"M3UAccount with ID={account_id} not found or inactive, task cleaned up"
|
||||
|
||||
# Fetch M3U lines and handle potential issues
|
||||
extinf_data = []
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue