W obecnym Systemie Zapisów wiele rzeczy dzieje się w tle i bez ręcznego sprawdzania student nie dowie się na przykład o fakcie zostania 'wciągnietym' do grupy z kolejki oczekujących na zapis na przedmiot. Chcielibyśmy dać użytkownikom możliwość otrzymywania powiadomień o takich zdarzeniach, podzielonych na kategorie.
Nasze rozwiązanie można podzielić na kilka głównych części:
- Realizujący wzorzec projektowy Repository interfejs do zapisywania i odczytywania powiadomień
- Oparta na systemie Redis implementacja tego interfejsu
- Widok (django view) pozwalający na przejrzenie powiadomień dotyczących zalogowanego użytkownika
- Rozszerzenie już istniejącego panelu konfiguracji konta o preferencje otrzymywania powiadomień - przykładowo, chcę dostawać emaile z kategorii X, o kategorii Y nie chcę dostawać niczego
- Napisany przy użyciu django-rq task zajmujący się faktycznym wysłaniem powiadomień (za pomocą emaila, Web Push Notification bądź dowolnego innego sposobu) asynchronicznie
Powiadomienie jest wewnętrznie reprezentowane przez klasę Notification
,
której najciekawszą częścią są dwa atrybuty: description_id
oraz description_args
.
Pierwszy z nich jest niejako wskaźnikiem do szablonu tekstu, który ma zawierać
powiadomienie, drugi - słownikiem z parametrami do tego szablonu. Takie podejście pozwoli nam
na bezproblemowe przetłumaczenie tych tekstów oraz pozwoli zaoszczędzić miejsce,
które powiadomienia zajmują w bazie. Przykładowy szablon:
Zostałeś zapisany na przedmiot {course_name}
gdzie course_name jest właśnie parametrem potrzebnym do wyrenderowania szablonu.
Obiekty tejże klasy przed zapisem będą serializowane (i analogicznie, przed odczytem deserializowane) - pierwszym pomysłem jest JSON, ze względu na swoją prostotę i względną czytelność, jednak w razie jakichkolwiek problemów (na przykład z miejscem w pamięci - każdy obiekt będzie przechowywał informacje o nazwach swoich kluczy, co w tym wypadku raczej nie będzie konieczne, jako że klucze te powtarzają się w każdym powiadomieniu) zmiana go na dowolny inny format będzie trywialna.
Po stronie Redisa natomiast oprzemy się na udostępnianej przez niego strukturze Set,
która pozwala m.in. na uzyskanie informacji o liczebności zbioru (powiadomień) w O(1).
Każdy użytkownik będzie posiadał przypisane do siebie dwa takie Sety,
przykładowo, dla studenta z ID = 1234: notifications_unsent_1234
oraz notifications_sent_1234
.
Pierwszy z nich zawiera powiadomienia, o których informacje nie zostały jeszcze wysłane -
przy zapisie nowego powiadomienia trafia ono właśnie tutaj. Natomiast drugi z nich
zawiera powiadomienia, o których użytkownik został już poinformowany - jedną z czynności,
które będzie wykonywał task zajmujący się rozsyłaniem tych informacji będzie przekładanie
ich z jednego zbioru do drugiego.
TODO