Closed martin-bts closed 5 years ago
:+1:
So far I have found three distinct messaging systems in Askbot:
Authenticated users can use session based messaging for a bunch of use cases where (it looks like) today messages are sent through the database.
The Askbot messaging systems all allow sending notifications to different users, which the Django messaging system does not. Further, the database based messaging allows sending notifications to offline users.
The group_messages app suppports a specific message type ONE_TIME
, which seems to fit the spirit of notifications. Group_messages is an Askbot (sub)project and apparently only implemented as far as needed, i.e. ONE_TIME
is an option, but it is never used thus making a message ONE_TIME
only makes them not show up in certain (most) result sets.
However, when dropping Askbot's session based and database based messaging systems, group_messages can be used to cover remaining use cases that Django messages do not cover.
AFAICT group_messages work a lot like "site-local" emails. A message of type ONE_TIME
is probably meant to show up in the inbox and get deleted when the user reads the message. In our use cases we want messages that never show up in the inbox but get displayed as user notifications, i.e. yellow banner at the top of the page. As this is probably a different intent as a read-once message, we shall create a new message type. Since messages can already be typed this is simple to facilitate.
When created, messages default to type STORED
and the MessagesManager explicitly looks for/creates messages of type STORED
. There is a good chance that a new message type has close to no side effects.
This seems easy enough. Context_processors provide lists of Messages and we iterate over the lists while rendering Templates with Jinja. I duplicated this Askbot method to also render Django messages and similarly we can duplicate this method again where we create the list of messages via a query to group messages.
At the moment when Askbot sends a notification to a different user it has a corresponding User
object and then calls user.message_set.create()
to send a message to that user. Given that we do have a User
object, we have all required information to send the message. We can draw inspiration from how the Askbot test suite sends messages.
To make it work, we need a MessagesManager
that can create messages with our newly created message type, because the currently available MessagesManager
as the type STORED
hardcoded.
I think this is only a theoretical corner case, because offline users do not have sessions that create notifications. Whenever a notification is to be sent to an offline user, it's the "messages to different user" use case.
HOWEVER, to be on the safe side, we should write a custom storage backend for the Django messages, that uses group_messages to store the notifications, using our newly created message type. We then derive from storage.fallback.FallbackStorage
and extend it by an additional fallback to our custom group_messages storage backend. Through this, sending user notifications happens using cookies, if those are unavailable through the session and if thats not available (i.e. the user is offline) through a group message
Then we should have all cases covered.
This does not cover the case of sending a message to a different anonymous user.
I finished my work on messaging. The main contribution is probably refined knowledge and (soon) documentation on how messages work and why we have them, e.g. see https://askbot.org/en/question/16762/how-does-system-to-user-messaging-system-works-in-askbot/ .
The entire messaging problem can be structured like this:
That covers 100% of all use cases. Askbot does not have a running dedicated facility for user-to-user messages. There is a lot of work on that with the group_messaging app, but it isn't active at the moment.
The use cases 1.
and 2.
are 100% synchronous, i.e. Askbot sends a notification because the user just did something inside the Askbot app that triggers on-screen feedback. Use case 3.
, sending model update information to the user is asynchronouos, i.e. these notifications are not an immediate result of what the receiver did and it is even possible that the user does not have a running session at the time the notification is sent.
Django messages can immediately be used for use case 1.
Django messages work for anonymous and authenticated users alike.
Use case 2.
mostly sends notifications with the Ajax response for immediate rendering on the client side. This works for anonymous and authenticated users alike. However, handling Ajax requests may additionally store notifications. These are notifications send to the user as an immediate result of their actions, analogous to use case 1.
, which means we can also use Django messages here.
Analysing Askbot to ensure every other use of messages is indeed the same and only use case 3.
was the hardest part of this work. Thanks again @evgenyfadeev for doing this with me.
Askbot ships with its own messaging system which mimics the behaviour of Django's old messaging system that was removed with Django 1.4.
I'm replacing it in the feature branch https://github.com/martin-bts/askbot-devel/tree/switch_to_django_messages