如何防止执行另一个相同的任务?

时间:2017-09-25 11:46:18

标签: python django celery django-celery

我有一项任务是从API中提取数据,然后针对数据库(SQLite)进行系统自动化(删除,重命名......)。我将任务设置为每5分钟执行一次。但是,有时任务完成需要5分钟以上,因此两个任务并行运行。这不好,因为SQLite数据库在0分钟内被锁定到任务。

我怎么能拥有

  • 除非上一个任务已经完成或
  • ,否则不会执行任务
  • 第二个任务排队并在0分钟任务完成后直接执行?

我试图使用全局布尔值来阻止任务在运行时执行,就像这样。

automate_is_running = False
@periodic_task(run_every=timedelta(minutes=5))
def automate():
    if not automate_is_running:
        automate_is_running = True

        automate_all()

        automate_is_running = False

但是返回UnboundLocalError: local variable 'automate_is_running' referenced before assignment错误。我该怎么办?

3 个答案:

答案 0 :(得分:0)

首先,您必须在函数中使用global。但是这仍然不能按你的意愿工作,因为每个Celery工作者都有自己的流程,而且流程之间不共享数据。

您需要使用某种外部互斥锁,例如磁盘上的文件或db或缓存中的条目。有一个使用memcached的示例in the Celery cookbook

答案 1 :(得分:0)

不是使其定期,而是在开始时安排一次,并始终在任务结束时安排下一次执行。还要确保重试失败的任务 错误TypeError: automate() missing 1 required positional argument: 'self'是因为Celery task装饰器创建了一个任务对象,因此您需要接受它的实例作为第一个参数self
以下代码将尽快运行任务一次,然后在任务成功完成后始终运行300秒。它也会在失败时尽快重试 要立即再次触发任务,请将self.apply_async(countdown=300)替换为self.delay()或传递countdown=0

@task
def automate(self):
    try:
        automate_all()
    except Exception as exc:
        raise self.retry(exc=exc)
    else:
        self.apply_async(countdown=300)

automate.delay()

尝试使用specyfic异常类而不是Exception。我不知道你的代码做了什么以及你期望的例外。

答案 2 :(得分:0)

您可以设置芹菜节拍的调度程序,并在第一个任务结束时调用您的第二个任务。

celery.py(Celery 2.3)

custom.css

tasks.py:

from django.conf import settings
from celery.schedules import crontab

settings.CELERYBEAT_SCHEDULE = {
    'runs-every-5-minutes' : {
        'task': 'automate',
        'schedule': crontab(minute='*/5'),
        'args' : (),
     },
}

文档:

芹菜2.3: http://docs.celeryproject.org/en/v2.3.3/userguide/periodic-tasks.html#crontab-schedules

芹菜4.1 http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html#crontab-schedules