【问题标题】:updated queue in RabbitMQRabbitMQ 中的更新队列
【发布时间】:2020-12-23 12:21:54
【问题描述】:

我有一个task,它要在一个对象的POSTPATCH 之后执行,比如ABC

代码如下:

models.py

class ABC(models.Model):
    start_at = models.DateTimeField()

task.py

@app.task
def do_something(obj_id):
    try:
        abc = ABC.objects.get(id=obj_id)
    except ObjectDoesNotExist:
        return

    eta = settings.ETA
    do_something.apply_async([abc.id], eta=eta)
    return

views.py

class ABCPost(CreateAPIView):
    serializer_class = ABCSerializer

    def post(self, request):
        # create object
        # call task do_something
    
    def patch(self, request):
        # update the `start_at` field for ABC
        # call task do_something

因此,当字段更新时,排队的消息应该以更新后的start_at 值执行。但是,对于上面的代码,两条消息为同一个对象排队,但时间戳不同。我怎样才能避免这种情况?

提前致谢

【问题讨论】:

    标签: django rabbitmq celery


    【解决方案1】:

    创建对象时,您需要存储 task_id

    abc = ABC.objects.get(pk=PK)
    abc.task_id = do_something.apply_async([abc.pk], eta=eta).id
    abc.save(updated_fields=['task_id'])
    

    将此字段添加到ABC模型中,并将其存储在其中。

    当您在补丁中时,如果尚未执行,则需要撤销第一个任务:

    from celery.result import AsyncResult
    abc = ABC.objects.get(pk=PK)
    AsyncResult(abc.task_id).revoke()
    abc.task_id = do_something.apply_async([abc.pk], eta=eta).id
    abc.save(updated_fields=['task_id'])
    

    这样你在队列中仍然有 2 条消息,但是在执行时会跳过第一个消息(撤销并没有从队列中删除,只是在它弹出时不执行)

    【讨论】:

    • 谢谢! task_id 是 charField 还是 IntegerField?
    • 这是一个字符域
    猜你喜欢
    • 2017-03-01
    • 2021-06-14
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 2014-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多