Supposons que j'ai un modèle Event
. Je souhaite envoyer une notification (e-mail, push, etc.) à tous les utilisateurs invités une fois l'événement terminé. Quelque chose dans le sens de:
class Event(models.Model):
start = models.DateTimeField(...)
end = models.DateTimeField(...)
invited = models.ManyToManyField(model=User)
def onEventElapsed(self):
for user in self.invited:
my_notification_backend.sendMessage(target=user, message="Event has elapsed")
Maintenant, bien sûr, la partie cruciale est d'invoquer onEventElapsed
chaque fois timezone.now() >= event.end
. Gardez à l'esprit que cela end
pourrait être à des mois de la date actuelle.
J'ai réfléchi à deux façons de procéder:
Utilisez un
cron
travail périodique (disons toutes les cinq minutes environ) qui vérifie si des événements se sont écoulés au cours des cinq dernières minutes et exécute ma méthode.Utiliser
celery
et planifier enonEventElapsed
utilisant leeta
paramètre à exécuter dans le futur (dans lasave
méthode des modèles ).
En considérant l'option 1, une solution potentielle pourrait être django-celery-beat
. Cependant, il semble un peu étrange d'exécuter une tâche à un intervalle fixe pour l'envoi de notifications. De plus, j'ai trouvé un problème (potentiel) qui résulterait (probablement) en une solution pas si élégante:
- Vérifiez toutes les cinq minutes les événements qui se sont écoulés au cours des cinq minutes précédentes? semble fragile, peut-être que certains événements sont manqués (ou que d'autres reçoivent leurs notifications deux fois?). Workaroung potentiel: ajoutez un champ booléen au modèle qui est défini sur
True
une fois les notifications envoyées.
Là encore, l'option 2 a également ses problèmes:
- Prenez soin manuellement de la situation lors du déplacement d'un datetime de début / fin d'événement. Lors de l'utilisation
celery
, il faudrait stocker letaskID
(facile, ofc) et révoquer la tâche une fois que les dates ont changé et émettre une nouvelle tâche. Mais j'ai lu que le céleri a des problèmes (spécifiques à la conception) lorsqu'il s'agit de tâches qui seront exécutées à l'avenir: Problème ouvert sur github . Je me rends compte comment cela se produit et pourquoi c'est tout sauf trivial à résoudre.
Maintenant, j'ai rencontré des bibliothèques qui pourraient potentiellement résoudre mon problème:
- celery_longterm_scheduler (Mais cela signifie que je ne peux pas utiliser le céleri comme je l' aurais avant, à cause de la classe Différend Scheduler? Cela a également des liens dans l'utilisation possible
django-celery-beat
... En utilisant l' un des deux cadres, est - il encore possible de faire la queue des emplois (qui sont juste un peu plus longs mais pas dans des mois?) - django-apscheduler , utilise
apscheduler
. Cependant, je n'ai pas pu trouver d'informations sur la façon dont il gérerait les tâches exécutées dans un avenir lointain.
Y a-t-il une faille fondamentale dans la façon dont j'aborde cette question? Je suis content pour toutes les entrées que vous pourriez avoir.
Remarque: je sais que cela est probablement basé sur l'opinion de quelque chose, cependant, il y a peut-être une chose très basique que j'ai manquée, indépendamment de ce qui pourrait être considéré par certains comme laid ou élégant.