twingo
twingo

Reputation: 119

updated queue in RabbitMQ

I have a task that is to be executed after a POST or PATCH for an object, say ABC

The code goes as follows:

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

So, when the field is updated, the queued message should be executed at the updated start_at value. However, with the code above two messages are queued for the same object but different timestamps. How can I avoid that?

Thanks in advance

Upvotes: 0

Views: 33

Answers (1)

MaximeK
MaximeK

Reputation: 2061

when you create your object you need to store the 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'])

add this field to ABC model, and store it inside.

when you are in patch, you need to revoke the 1st task if not yet executed :

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'])

This way you will have still 2 messages in queue, but the first will be skipped when executed (revoked didnt remove from queue, that just dont execute it when it popoff)

Upvotes: 1

Related Questions