I’m working on a Django blog and I need to be able to schedule posts to publish at a later date. Celery works great for initially scheduling posts, but I run into problems when a user tries to update the post to either have it either reschedule or canceled indefinitely.
Here is what I am trying to do:
def save(self, **kwargs):
'''
Saves an event. If the event is currently scheduled to publish,
sets a celery task to publish the event at the selected time.
If there is an existing scheduled task,cancel it and reschedule it
if necessary.
'''
import celery
this_task_id = 'publish-post-%s' % self.id
celery.task.control.revoke(task_id=this_task_id)
if self.status == self.STATUS_SCHEDULED:
from blog import tasks
tasks.publish_post.apply_async(args=[self.id], eta=self.date_published,
task_id=this_task_id)
else:
self.date_published = datetime.now()
super(Post, self).save(**kwargs)
The problem is, once a Celery task ID has been listed as revoked, it stays revoked even after I try and reschedule it. This seems like a common enough task that there should be an easy solution.
I don’t know what your tasks.py file looks like, but I assume it’s something like the following:
You should edit the filter within the task to make sure that the current status is STATUS_SCHEDULED and that the time in date_published has passed. e.g.:
This way, users can change the status back and forth, change the time, and the task will only ever change the status to publish if the task is running after the date_published column. No need to track ids or revoke tasks.