Supongamos que tengo un Event modelo. Quiero enviar una notificación (correo electrónico, push, lo que sea) a todos los usuarios invitados una vez que haya transcurrido el evento. Algo del estilo 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") Ahora, por supuesto, la parte crucial es invocar onEventElapsed siempre que timezone.now() >= event.end . Tenga en cuenta que el end podría estar a meses de distancia de la fecha actual.
He pensado en dos formas básicas de hacer esto:
Use un trabajo cron periódico (digamos, cada cinco minutos más o menos) que verifique si ha transcurrido algún evento en los últimos cinco minutos y ejecute mi método.
Use celery y programe onEventElapsed usando el parámetro eta para que se ejecute en el futuro (dentro del método de save de modelos).
Teniendo en cuenta la opción 1, una posible solución podría ser django-celery-beat . Sin embargo, parece un poco extraño ejecutar una tarea en un intervalo fijo para enviar notificaciones. Además, se me ocurrió un problema (potencial) que (probablemente) resultaría en una solución no tan elegante:
True una vez que se hayan enviado las notificaciones.Por otra parte, la opción 2 también tiene sus problemas:
celery , uno tendría que almacenar el taskID de tarea (fácil, ofc) y revocar la tarea una vez que las fechas hayan cambiado y emitir una nueva tarea. Pero he leído que el apio tiene problemas (específicos del diseño) cuando se trata de tareas que se ejecutarán en el futuro: Abrir problema en github . Me doy cuenta de cómo sucede esto y por qué es todo menos trivial de resolver.Ahora, me he encontrado con algunas bibliotecas que podrían resolver mi problema:
django-celery-beat ... Usando cualquiera de los dos marcos, ¿sigue siendo posible? para poner en cola trabajos (¿que duran un poco más pero no faltan meses?)apscheduler . Sin embargo, no pude encontrar ninguna información sobre cómo manejaría las tareas que se ejecutan en un futuro lejano.¿Hay una falla fundamental en la forma en que estoy abordando esto? Me alegro por cualquier entrada que pueda tener.
Aviso: sé que es probable que esto se base en alguna opinión, sin embargo, tal vez hay algo muy básico que me he perdido, independientemente de lo que algunos puedan considerar feo o elegante.
Estamos haciendo algo como esto en la empresa para la que trabajo, y la solución es bastante simple.
Tenga un ritmo de cron / apio que se ejecute cada hora para verificar si es necesario enviar alguna notificación. Luego envíe esas notificaciones y márquelas como hechas. De esta manera, incluso si su tiempo de notificación está adelantado en años, aún se enviará. Usar ETA NO es el camino a seguir durante un tiempo de espera muy largo, su caché / amqp podría perder los datos.
Puede reducir su intervalo según sus necesidades, pero asegúrese de que no se superpongan.
Si una hora es una diferencia horaria demasiado grande, entonces lo que puede hacer es ejecutar un programador cada hora. La lógica sería algo como
Usar esa metodología les daría a ambos los mejores mundos (eta y beat)