Celery在使用django数据库执行之前撤销任务

时间:2014-07-30 20:21:53

标签: python django celery django-celery

出于并发原因,我正在使用Django数据库而不是RabbitMQ。

但我无法在执行任务之前解决撤销任务的问题。

我找到了一些关于这个问题的答案,但它们看起来并不完整,或者我得不到足够的帮助。

如何使用模型扩展芹菜任务表,添加一个布尔字段(已撤销)以在我不希望任务执行时进行设置?

感谢。

1 个答案:

答案 0 :(得分:4)

由于Celery通过ID跟踪任务,因此您真正需要的是能够分辨哪些ID已被取消。您可以创建自己的表(或kombu等)来跟踪已取消的ID,然后检查当前可取消任务的ID是否在其中。而不是修改memcached内部。

这是支持远程revoke命令的传输在内部执行的操作:

  

所有工作节点都在内存中保留已撤销任务ID的内存   或持久在磁盘上(请参阅持久撤销)。 (来自Celery docs)

当您使用django传输时,您自己负责这样做。在这种情况下,它可以检查每项任务是否已被取消。

因此,任务的基本形式(添加日志代替实际操作)变为:

from celery import shared_task
from celery.exceptions import Ignore
from celery.utils.log import get_task_logger
from .models import task_canceled
logger = get_task_logger(__name__)

@shared_task
def my_task():
    if task_canceled(my_task.request.id):
        raise Ignore
    logger.info("Doing my stuff")

你可以扩展&以各种方式改进这一点,例如通过创建一个基础CancelableTask类,就像你链接到的其他答案之一,但这是基本形式。您现在缺少的是模型和检查它的功能。

请注意,在这种情况下,ID将是一个字符串ID,如a5644f08-7d30-43ff-a61e-81c165ad9e19不是整数。您的模型可以像这样简单:

from django.db import models

class CanceledTask(models.Model):
    task_id = models.CharField(max_length=200)

def cancel_task(request_id):
    CanceledTask.objects.create(task_id=request_id)

def task_canceled(request_id):
    return CanceledTask.objects.filter(task_id=request_id).exists()

您现在可以通过观察芹菜服务的调试日志来检查行为,同时执行以下操作:

my_task.delay()
models.cancel_task(my_task.delay())