Suponha que eu tenho um modelo Event
. Quero enviar uma notificação (email, push, qualquer que seja) a todos os usuários convidados depois que o evento terminar. Algo ao longo das linhas 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")
Agora, é claro, a parte crucial é invocar onEventElapsed
sempre timezone.now() >= event.end
. Lembre-se de que end
pode demorar meses para a data atual.
Eu pensei em duas maneiras básicas de fazer isso:
Use um
cron
trabalho periódico (digamos, a cada cinco minutos mais ou menos) que verifique se algum evento ocorreu nos últimos cinco minutos e execute meu método.Use
celery
e programeonEventElapsed
usando oeta
parâmetro a ser executado no futuro (dentro dosave
método de modelos ).
Considerando a opção 1, uma solução potencial poderia ser django-celery-beat
. No entanto, parece um pouco estranho executar uma tarefa em um intervalo fixo para enviar notificações. Além disso, eu vim com um problema (potencial) que provavelmente resultaria em uma solução não tão elegante:
- Verifique a cada cinco minutos se há eventos decorridos nos cinco minutos anteriores? parece instável, talvez alguns eventos sejam perdidos (ou outros recebam as notificações duas vezes?). Área de trabalho potencial: adicione um campo booleano ao modelo definido como
True
uma vez que as notificações forem enviadas.
Então, novamente, a opção 2 também tem seus problemas:
- Cuide manualmente da situação quando um horário de início / término do evento for movido. Ao usar
celery
, seria necessário armazenar otaskID
(easy, ofc) e revogar a tarefa assim que as datas mudarem e emitir uma nova tarefa. Mas eu li que o aipo tem problemas (específicos do projeto) ao lidar com tarefas que são executadas no futuro: Open Issue no github . Percebo como isso acontece e por que tudo é trivial de resolver.
Agora, encontrei algumas bibliotecas que poderiam solucionar meu problema:
- celery_longterm_scheduler (Mas isso significa que não posso usar o aipo como antes, devido à classe diferente do Scheduler? Isso também está relacionado ao possível uso de
django-celery-beat
... Usando qualquer uma das duas estruturas, ainda é possível enfileirar trabalhos (que demoram um pouco mais, mas não demoram meses?) - django-apscheduler , usa
apscheduler
. No entanto, não consegui encontrar nenhuma informação sobre como ele lidaria com tarefas executadas no futuro distante.
Existe uma falha fundemantal na maneira como estou abordando isso? Fico feliz por quaisquer entradas que você possa ter.
Aviso: Eu sei que é provável que isso seja baseado em opiniões, no entanto, talvez haja uma coisa muito básica que eu tenha perdido, independentemente do que possa ser considerado por alguns como feio ou elegante.