sometimes, the web client receives unsubscribe notification and an extra
notification on that channel. This is then followed by an attempt to
rejoin the channel that we just left. This commit prevents that
situation to occur.
For that, it needs to know the notifications received by the bus in one
batch, not one at a time.
This commit introduces native notifications (if available) to the
discuss application.
Those notifications will only appear if the user grants the permission
for that. A notification bar will appear in the discuss application if
necessary to prompt the user.
Also, it always is the master bus that will be the one sending the
notification.
For this change, it was necessary to be able to detect if the user has
the focus on some other odoo tabs. For this reason, the bus was
extended.
Commit 5d1b323. re-enabled the user presence updates and notifications.
Unfortunately, it showed poor performance due to the high frequency of bus
notifications triggered on our instance (~600k users).
In this rev., we don't trigger notifications on presence changes anymore, but
we rather send the presence of users we have a DM open with, at the end of each
poll period. For performance reasons, we ensure not to do that more than once
every 30 seconds.
We also refined the detection of the 'away' status client side. 'Last presence'
timestamps are stored in the local storage, and the current inactivity period
is sent at each poll. Those presence timestamps now rely on browser activity
detection (click, keypress... events) rather than on the focus on Odoo tabs.
Finally, we removed the no more necessary cron introduced in 5d1b323.
Before this rev., no notification was sent on the bus when the user presence
changed. Thus, the bullets displayed in Discuss were never updated and stayed
as they were on the initialilization of the chat_manager (on webclient launch).
This rev. makes the bus.presence notifications work, and handles them client
side.
Moreover, the disconnections detection is now performed at each poll (with a
maximum of 1 per minute), instead of randomly (1/100 chance) at each poll, as
it scales better than the former solution. We also added a cron that performs
this check every 5 minutes. It is needed to detect that the last connected user
just disconnected (useful for visitors in the website, trying to talk with a
livechat operator).
Also, the 'away' status is now handled client side, as it makes more sense
that way (being away at each poll, e.g. every 50seconds, during 10 minutes
doesn't mean that we didn't come back between two polls).
Finaly, in bus.js, CrossTabBus, we moved the code writing in/reading the local
storage after the tab registration as this code depends on the fact that the
tab is the master tab or not (and this is known only once the tab is
registered).
This rev. was necessary in stable because the livechat uses the user status to
detect if there is an operator available, and this was often inaccurate.
Moreover, it improves the user experience of the chat in the backend.
On browser refresh, the bus sends the last notifications for the last
50secs. This is really annoying to deal with, especially in the chat
applicatiion. This commits ensure that duplicate notifications are
ignored. This is done by saving the id of the last notif in the local
storage.
Note: it is also necessary to clear the last message id in the local
storage to prevent problems when a developer resets his db, and will not
receive any notifications.
The problem was that the tab_manager compared its last heartbeat value with an
old value stored in the local storage (when being elicted master, the tab
writes a new heartbeat in the locat storage).
This solution makes sure to compare the actual value in the local storage with
the heartbeat value stored in the tab_manager.
The bus is somewhat tricky. (at least, the crosstab version). It needs
to elect a leader, and to communicate with the server through it.
However, several tabs have a different event loop, so, we need to be
careful to avoid race conditions. The current version was not
race-condition-proof, and this commits improves on this.
The idea is to allow the bus to detect if some other tab is also
considering himself master. In that case, it is allowed to unelect
himself.
This should allow the bus to self correct those situations in a short
time.
The bus used to do a long poll as soon as it is started. This is fine
when the user has a single tab, but not so fine when 5 or 6 tabs are
open. This commit introduce the concept of tab manager, a way to decide
among all tabs who is the leader. The leader will then initiate the
long poll, and share the notifications via the local storage.
The bus was allowed to restart polling, client side, to allow the user
to directly receive messages in new channels. This was only acceptable
as a temporary fix, the correct way to do this is to actually notify the
bus server side. This is even more urgent since the client was allowed
to keep multiple longpolls simultaneously, which degraded the experience
in some cases.
If calling more than once `sendmany` (or `sendone`) on the same http request, the `NOTIFY imbus` will tell pertinent polling thread to
fetch their notifications in the bus table, which will not contain the new notifications, since they are not yet committed. For some reason, this
doesn't happen when calling only once `sendmany`. Committing the notifications breaks the tests since no rollback is possible.
So, `self._cr.commit()` should not be called in a test environement.
In this case, we cannot use `isinstance(self._cr, TestCursor)` since TestCursor is only avaiblable for http request in test mode. Here the cursor is a normal cursor, and to determine if we are in test mode, there is no other option than checking the config of the odoo server.
In test mode, only one cursor is available, and longpolling will take
it, and not give it back before 60s, causing a phantomjs timeout. This
commit simply return an error when the server is in test mode.
Sadly, I had to patch the web client to prevent logging the error in
this case, because that's the way phantomjs detect if there is a
problem.
The problem was that the bus didn't listen to new channels when they were
registered until the end of the current longpoll. This allows mail to manually
restart the polling.
The stdlib version of the json library is more recent than the 3.5.3
version we are pinning in `requirements.txt`
There is no reason to use it.
Closes#6940