Reputation: 119
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
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