Supponiamo che io abbia un modello Event
. Desidero inviare una notifica (e-mail, push, qualunque cosa) a tutti gli utenti invitati una volta trascorso l'evento. Qualcosa sulla falsariga di:
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")
Ora, ovviamente, la parte cruciale è invocare onEventElapsed
ogni volta timezone.now() >= event.end
. Tieni presente che end
potrebbero mancare mesi alla data corrente.
Ho pensato a due modi base per farlo:
Usa un
cron
lavoro periodico (diciamo, ogni cinque minuti circa) che controlla se sono trascorsi eventi negli ultimi cinque minuti ed esegue il mio metodo.Utilizzare
celery
e pianificareonEventElapsed
utilizzando ileta
parametro da eseguire in futuro (con ilsave
metodo dei modelli ).
Considerando l'opzione 1, una potenziale soluzione potrebbe essere django-celery-beat
. Tuttavia, sembra un po 'strano eseguire un'attività a intervalli fissi per l'invio di notifiche. Inoltre ho escogitato un (potenziale) problema che avrebbe (probabilmente) comportato una soluzione non così elegante:
- Controlla ogni cinque minuti gli eventi che sono trascorsi nei cinque minuti precedenti? sembra traballante, forse alcuni eventi sono mancati (o altri ricevono le loro notifiche inviate due volte?). Soluzione alternativa potenziale: aggiungere un campo booleano al modello impostato su
True
dopo l'invio delle notifiche.
Quindi, anche l'opzione 2 ha i suoi problemi:
- Gestire manualmente la situazione quando si sposta un datetime di inizio / fine di un evento. Durante l'utilizzo
celery
, si dovrebbe archiviaretaskID
(easy, ofc) e revocare l'attività una volta che le date sono state modificate ed emettere una nuova attività. Ma ho letto che il sedano ha problemi (specifici del design) quando si affrontano attività che verranno eseguite in futuro: Open Issue su github . Mi rendo conto di come ciò accada e perché è tutt'altro che banale da risolvere.
Ora, ho trovato alcune librerie che potrebbero potenzialmente risolvere il mio problema:
- celery_longterm_scheduler (Ma questo significa che non posso usare il sedano come avrei fatto prima, a causa della diversa classe Scheduler? Ciò si collega anche al possibile utilizzo di
django-celery-beat
... Utilizzando uno dei due framework, è ancora possibile mettere in coda i lavori (che sono solo un po 'più lunghi ma non a mesi?) - django-apscheduler , usa
apscheduler
. Tuttavia, non sono stato in grado di trovare alcuna informazione su come gestire le attività che verranno eseguite in un futuro lontano.
C'è un difetto fondamentale nel modo in cui mi sto avvicinando a questo? Sono contento per qualsiasi input tu possa avere.
Nota: so che è probabile che questo sia basato sull'opinione di qualcuno, tuttavia, forse c'è qualcosa di molto semplice che mi sono perso, indipendentemente da ciò che alcuni potrebbero considerare brutti o eleganti.