I have created an advertising app in my websilte with django and the Ad model looks like this
AdModel(models.Model):
starting_date = models.DateField()
expiring_date = models.DateField()
active = models.BooleanField(default=False)
My goal is to create a task using Celery to activate (set ad.active = True) and deactivate ads based on their starting and expiring date and since the celery beat is for periodic recurring task so it’s not going to solve it.
Probably passing the starting_date as eta to the task like this will be the solution:
#signals.py
@receiver(post_save, sender=AdModel)
def start_task(sender, instance, created, **kwargs):
if created:
ad_activator_task.apply_async( (instance.id), eta=instance.starting_date)
If the instance.starting_date is three months far from now, is it going to be executed ? i have read that Celery not usefull for long term future tasks (far future) and i’m kinda confused.
note: im using Redis as broker
2
Answers
I have come up with inelegant workaround wish is creating a periodic task that runs everyday at midnight to check for ads to activate/deactivate and the task is like so:
and the beat config :
any other approachs are welcome
I strongly advise not to implement this with scheduled tasks. You better do not use an
active
field anyway: whether an ad is active is here determine by thestarting_date
and theexpiring_date
. We can thus model this as:We can use annotations to determine if an
AdModel
is active with:If you need this often, you can make a
Manager
that will automatically annotateAdModel.objects
:If you want extra control, you can just add an extra nullable boolean field
force_active
that is set to NULL by default, but you can set it toTrue
/False
to override the expiration mechanism: