Załóżmy, że mam model Event
. Chcę wysłać powiadomienie (e-mail, push, cokolwiek) do wszystkich zaproszonych użytkowników po zakończeniu wydarzenia. Coś w stylu:
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")
Teraz oczywiście najważniejszą częścią jest wywoływanie onEventElapsed
za każdym razem timezone.now() >= event.end
. Pamiętaj, że end
może upłynąć kilka miesięcy od bieżącej daty.
Pomyślałem o dwóch podstawowych sposobach:
Użyj okresowego
cron
zadania (powiedzmy co około pięć minut), które sprawdza, czy jakieś zdarzenia minęły w ciągu ostatnich pięciu minut i wykonuje moją metodę.Użyj
celery
i zaplanuj,onEventElapsed
używająceta
parametru do uruchomienia w przyszłości (w ramachsave
metody modeli ).
Biorąc pod uwagę opcję 1, potencjalnym rozwiązaniem może być django-celery-beat
. Jednak wydaje się nieco dziwne uruchamianie zadania w ustalonych odstępach czasu w celu wysyłania powiadomień. Ponadto wpadłem na (potencjalny) problem, który (prawdopodobnie) spowodowałby nie tak eleganckie rozwiązanie:
- Czy sprawdzać co pięć minut zdarzenia, które upłynęły w ciągu ostatnich pięciu minut? wydaje się chwiejne, może niektóre wydarzenia zostały pominięte (lub inne otrzymały dwa powiadomienia wysyłane dwukrotnie?). Potencjalne obejście: dodaj pole boolowskie do modelu, który jest ustawiony na
True
po wysłaniu powiadomień.
Z drugiej strony, opcja 2 ma również swoje problemy:
- Ręcznie zajmij się sytuacją, w której przenoszona jest data / godzina rozpoczęcia zdarzenia. Podczas korzystania
celery
należy zapisaćtaskID
(łatwe, ofc) i odwołać zadanie po zmianie dat i wydać nowe zadanie. Ale czytałem, że seler ma problemy (specyficzne dla projektu) podczas wykonywania zadań, które będą uruchamiane w przyszłości: Open Issue on github . Zdaję sobie sprawę z tego, jak to się dzieje i dlaczego rozwiązanie tego problemu jest trywialne.
Teraz natknąłem się na biblioteki, które potencjalnie mogłyby rozwiązać mój problem:
- celery_longterm_scheduler (Ale czy to oznacza, że nie mogę używać selera, tak jak wcześniej, ze względu na inną klasę Scheduler? To także wiąże się z możliwym użyciem
django-celery-beat
... Przy użyciu dowolnego z dwóch frameworków, czy nadal można kolejkować zadania (że są trochę dłużej, ale nie za kilka miesięcy?) - django-apscheduler , używa
apscheduler
. Nie udało mi się jednak znaleźć żadnych informacji o tym, jak poradzi sobie z zadaniami, które są uruchamiane w dalekiej przyszłości.
Czy jest jakiś poważny błąd w sposobie, w jaki do tego podchodzę? Cieszę się z wszelkich informacji, które możesz mieć.
Uwaga: Wiem, że prawdopodobnie jest to oparte na niektórych opiniach, jednak może brakuje mi bardzo podstawowej rzeczy, niezależnie od tego, co niektórzy mogą uznać za brzydką lub elegancką.