我在Django应用中使用django-celery-beat
(这将附表存储在数据库中,而不是本地文件(。我已经通过celery_beat
配置了我的时间表,该芹菜是通过app.config_from_object(...)
我最近重命名/删除了一些任务,然后重新启动了该应用程序。出现了新任务,但是从celery_beat
字典中删除的任务并未从数据库中删除。
这个预期的工作流程是否需要手动从数据库中删除任务?是否有解决方法可以自动调和Django启动的时间表?
我在celery/__init__.py
PeriodicTask.objects.all().delete()
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()
中的查询/db连接。
查看 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管理员或编程添加任务,也将删除它们。