从celery_beat中删除项目不会将其从数据库计划中删除

时间:2019-05-08 18:52:35

标签: django celery celerybeat

我在django应用程序中使用django-celery-beat(这将日程表存储在数据库中,而不是本地文件中)。我已通过celery_beat配置了计划,以通过app.config_from_object(...)

初始化Celery

我最近重命名/删除了一些任务,然后重新启动了该应用程序。出现了新任务,但是从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(),因为不支持在ready()中进行查询/数据库连接。

1 个答案:

答案 0 :(得分:1)

看看django-celery-beat实际如何安装时间表,我想我也许可以参与该过程。

在Django启动时不会发生-在 beat 启动时会发生。它会向Beat命令行上传递的类调用setup_schedule()

因此,我们可以使用

覆盖计划程序。
--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管理员或以编程方式添加任务,这些任务也会被删除。