Sometimes having real-time notification could improve the work performance because the user can react quickly. Of course such notification should be use with care to not overflow users with useless notification.
A notification is a pop-up display above all other windows. Most desktop has this feature and also most of the browsers.
The challenge is having the client listening for the notification for the current user with a minimal resource consumption client and server sides.
Proposition
We could use the long polling method. So the desktop client will start a new thread and the web client will start such query at login. They will make request on a specific address using the user ID and the session.
On the server side, we could use the LISTEN/NOTIFY mechanism to wait for notifications. For other back-ends which do not support such mechanism, the request will just return an error code and the client will not try any more.
We will created a channel for the user name and another for the session like that we could notify the user anywhere and only for a specific session (could be used with on_change).
On logout, the long polling should be stopped.
On web client, we will use Web Notifications.
On desktop client, we will use libnotify
Why not use the websockets protocol? Two threads, one for pull (normal operation) and the other for push (message from the server).
It needs modification on the server-side but websockets are just a protocol and you can handle all the data in the same format as you have now.
No need for polling, so less traffic needed. No need to have extra mechanisms on the serverside, But the first for me is a big argument, because traffic is expensive.
One potential issue with “LISTEN/NOTIFY” is that it takes permanently a connection resource on the database per long polling. So the number of active client that a server can support will drop quickly with this feature.
A possible solution will be to have one thread per process that listen on a generic channel, each long polling request from the same process will register to this thread. Once the listen thread receive a notification, it dispatches it to the right long polling thread. The inconvenient of this method is that the listen thread will receive all notifications even for users who does not have a long polling thread registered. This could be improved by having the listen thread listen to each channel of the long polling thread.
Maybe a solution will be to have a separate process that listen on a specific port (server should sent the address or the port at the client login). This process will not be threaded but instead just asynchronous. It will use a connection per database and it will listen for all the requested channels. It will use a single event loop for new long polling connection and database notify and it will dispatch the notification to the right request.
A part from the protocol to comunicate with the server i think that it should be possible to relate the notification to some records and the user should be able to access does records with a single click.
For example: I do some long task in async way and I will like to notice the user when it have been finished. As this task may be related to a record the user may be able to open the record (in a new tab) directly when the notification is shown.
On my system I have notifications that have some buttons to click and do some actions related to them. An for what I read in the libnotify is possible to add Actions, and in case the system does not support them we can use a HyperLink with the tryton URL as fallback.
By why websocket? I see no advantages for this protocol because notification is any way in one direction server → client. Also with websocket, you just have something like a socket so you have to create your own protocol on top of it.
So to consider websocket, I need to have a rational for its usage and not just because it is a new cool kid.
This could be done only with a common protocol for all notification systems.
To me it has nothing to do with “new cool kid” because it isn’t a cool kid. It’s hard to implement because of it’s asynchronous nature. Websockets can also be used as “normal” connection. And because Tryton uses RPC, that can be transported by Websockets without a problem. But mostly there is a fallback to HTTP because not all browser support websockets.
By using websockets you lift the system out of the database like you want to do with the LISTEN / NOTIFY functions of PostgreSQL. Websockets gives you also the possibility to do some user-actions like sending notifications to a user from a module.
That’s exactly what I’m thinking of! E.g. print a complex report or do a long-running operation like reconciliation or open the chart of accounts etc. You are then be able to give the user status updates during the process of collecting data or printing. I’m also thinking of voip integration, so when the phone starts ringing, the user gets a notification who it is. Eventually the client can already open a new tab with the caller details.
Please don’t open extra ports! It’s always a security risk and Tryton starts to look like other cool new software where you must open a lot of ports to get the software running with the (new) features.
I think the notification protocol should be flexible and not only limited to notification popup.
Indeed I think we should be able to send to the client action like reload this records, execute this action etc. This way we could get the client refreshing automatically records that were opened before a modification on the server side.
What bothers me after looking the code is that it’s basically just another window managed by tryton not at all something as well integrated as libnotify seems to be.