如何取消Celery中的冲突/旧任务?

时间:2014-10-25 03:16:39

标签: python locking rabbitmq celery

我正在使用Celery + RabbitMQ 当Celery工作人员不可用时,所有任务都在RabbitMQ中等待 正如它变得在线一样,所有这些任务都会立即执行 我可以以某种方式阻止它发生吗?

例如,有等待Celery工作人员的100个任务(相同),当Celery工作人员上线时,我可以只执行其中一个吗?

2 个答案:

答案 0 :(得分:2)

由于队列中的所有任务都相同,更好的方法是仅发送一次,为此,您需要能够跟踪任务是否已发布,例如:

在发布任务时添加自定义状态:

from celery import current_app
from celery.signals import after_task_publish

@after_task_publish.connect
def add_sent_state(sender=None, body=None, **kwargs):
    """Track Published Tasks."""
    # get the task instance from its name
    task = current_app.tasks.get(sender)

    # if there is no task.backend fallback to app.backend
    backend = task.backend if task else current_app.backend

    # store the task state
    backend.store_result(body['id'], None, 'SENT')

当您要发送任务时,您可以检查任务是否已发布,并且由于我们使用自定义状态,因此任务的状态不会是PENDING当它发布时(可能是未知的)所以我们可以使用:

进行检查
from celery import states

# the task has a custom ID
task = task_func.AsyncResult('CUSTOM_ID')

if task.state != states.PENDING:
    # the task already exists
else:
    # send the task
    task_func.apply_async(args, kwargs, task_id='CUSTOM_ID')

我在我的应用中使用这种方法并且工作得很好,我的任务可以多次发送,并且可以通过ID标识,这样每个任务都会发送一次。

如果您仍想取消队列中的所有任务,可以使用:

# import your Celery instance
from project.celery import app

app.control.purge()

查看芹菜常见问题How do I purge all waiting tasks ?

答案 1 :(得分:1)

有两种方法可以做到这一点。

首先,只运行一个并发为1的worker。

celery worker -A your_app -l info -c 1

此命令启动并发为1的worker。因此,一次只能执行一项任务。这是首选方法。

第二种方法有点复杂。您需要获取锁定并释放锁定以确保仅one task is executed at a time

或者,如果需要,可以使用purge命令从队列中删除所有任务。

celery -A your_app purge