【问题标题】:Celery revoke task before execute using django database芹菜在使用 django 数据库执行之前撤销任务
【发布时间】:2014-09-22 15:33:48
【问题描述】:

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

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

我找到了一些关于这个问题的答案,但它们似乎并不完整,或者我无法获得足够的帮助。

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

谢谢。

【问题讨论】:

    标签: python django celery django-celery


    【解决方案1】:

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

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

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

    当您使用 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()
    

    您现在可以在执行以下操作时通过查看 celery 服务的调试日志来检查行为:

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

    【讨论】:

    • 谢谢它的工作:D。有了你的解释,现在更清楚了:)。毕竟这也不是什么难事。信息:我使用自定义 task_id,因此无需手动记录操作。再次感谢。
    猜你喜欢
    • 2023-03-07
    • 1970-01-01
    • 2014-10-28
    • 2022-01-21
    • 2018-01-08
    • 2015-01-21
    • 2021-10-01
    • 2021-12-16
    • 2018-03-07
    相关资源
    最近更新 更多