django - 如何判断一个任务是否已经在 django-celery 中排队?

标签 django message-queue celery django-celery

这是我的设置:

  • django 1.3
  • celery 2.2.6
  • django celery 2.2.4
  • djkombu 0.9.2

  • 在我的 settings.py 文件中,我有
    BROKER_BACKEND = "djkombu.transport.DatabaseTransport"
    

    即我只是使用数据库来排队任务。

    现在谈谈我的问题:我有一个用户启动的任务,可能需要几分钟才能完成。我希望每个用户只运行一次任务,并且我会将任务的结果缓存在一个临时文件中,所以如果用户再次启动任务,我只返回缓存的文件。我的 View 函数中有如下代码:
    task_id = "long-task-%d" % user_id
    result = tasks.some_long_task.AsyncResult(task_id)
    
    if result.state == celery.states.PENDING:
        # The next line makes a duplicate task if the user rapidly refreshes the page
        tasks.some_long_task.apply_async(task_id=task_id)
        return HttpResponse("Task started...")
    elif result.state == celery.states.STARTED:
        return HttpResponse("Task is still running, please wait...")
    elif result.state == celery.states.SUCCESS:
        if cached_file_still_exists():
            return get_cached_file()
        else:
            result.forget()
            tasks.some_long_task.apply_async(task_id=task_id)
            return HttpResponse("Task started...")
    

    这段代码几乎可以工作。但是当用户快速重新加载页面时,我遇到了问题。从任务排队到任务最终从队列中拉出并交给工作人员之间有 1-3 秒的延迟。在此期间,任务的状态保持为 PENDING,这会导致 View 逻辑启动重复任务。

    我需要的是某种方式来判断任务是否已经提交到队列中,所以我最终不会提交两次。在 celery 中有这样做的标准方法吗?

    最佳答案

    我用 Redis 解决了这个问题。只需在 redis 中为每个任务设置一个键,然后在任务的 after_return 方法中从 redis 中删除该键。 Redis 是轻量级和快速的。

    关于django - 如何判断一个任务是否已经在 django-celery 中排队?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5888704/

    相关文章:

    django - Django i18n:如何不翻译管理网站?

    java - 没有连接的 AMQP/RabbitMQ channel 什么时候死掉?

    python-3.x - 使用 flask 路由(Python)启动和停止方法

    python - 如何检测我是否在 Celery worker 中运行?

    python - memcache.get 返回错误的对象(Celery、Django)

    python - 模板表单未在 Django 中呈现

    java - 在应用程序中使用 IBM MQ 客户端 jar 连接到 IBM MQ 服务器时无响应

    javascript - 使用 nginx+pushstream 模块进行长轮询是否可能会丢失消息?

    celery - Django celery : Admin interface showing zero tasks/workers

    django - 如何在 Django 中获取当前应用程序