Удаление элементов из celery_beat не удаляет их из расписания базы данных - PullRequest
0 голосов
/ 08 мая 2019

Я использую django-celery-beat в приложении django (это сохраняет расписание в базе данных вместо локального файла). Я настроил свое расписание через celery_beat, с которым Celery инициализируется через app.config_from_object(...)

Я недавно переименовал / удалил несколько задач и перезапустил приложение. Появились новые задачи, но задачи, удаленные из словаря celery_beat, не были удалены из базы данных.

Является ли это ожидаемым рабочим процессом - требующим ручного удаления задач из базы данных? Есть ли обходной путь для автоматического согласования расписания при запуске Django?

Я попробовал PeriodicTask.objects.all().delete() в celery/__init__.py

def _clean_schedule():                                                         
    from django.db import transaction                                           
    from django_celery_beat.models import PeriodicTask                          
    from django_celery_beat.models import PeriodicTasks                         
    with transaction.atomic():                                                  
         PeriodicTask.objects.\                                                  
            exclude(task__startswith='celery.').\                               
            exclude(name__in=settings.CELERY_CONFIG.celery_beat.keys()).\      
            delete()                                                            
         PeriodicTasks.update_changed()                                          
_clean_schedule()           

но это не разрешено, потому что Django еще не запущен должным образом:

django.core.exceptions.AppRegistryNotReady: приложения еще не загружены.

Вы также не можете использовать Django AppConfig.ready(), потому что создание запросов / соединений в db в ready() не поддерживается.

1 Ответ

1 голос
/ 08 мая 2019

Глядя на то, как на самом деле работает django-celery-beat для установки расписаний, я подумал, что, возможно, смогу подключиться к этому процессу.

Это не происходит, когда запускается Django - это происходит, когда начинается beat .Он вызывает setup_schedule() для класса, переданного в командной строке beat.

Поэтому мы можем просто переопределить планировщик с помощью

--scheduler=myproject.lib.scheduler:DatabaseSchedulerWithCleanup

, чтобы выполнить очистку:

import logging

from django_celery_beat.models import PeriodicTask                               
from django_celery_beat.models import PeriodicTasks                              
from django_celery_beat.schedulers import DatabaseScheduler                     
from django.db import transaction                                                


class DatabaseSchedulerWithCleanup(DatabaseScheduler):                           

    def setup_schedule(self):                                                    
        schedule = self.app.conf.beat_schedule                                   
        with transaction.atomic():                                               
            num, info = PeriodicTask.objects.\                                   
                exclude(task__startswith='celery.').\                            
                exclude(name__in=schedule.keys()).\                              
                delete()                                                         
            logging.info("Removed %d obsolete periodic tasks.", num)            
            if num > 0:                                                          
                PeriodicTasks.update_changed()                                   
        super(DatabaseSchedulerWithCleanup, self).setup_schedule()    

Обратите внимание, вы хотите это только в том случае, если вы исключительно управляете задачами с помощью beat_schedule.Если вы добавляете задачи через администратора Django или программно, они также будут удалены.

...