[IMP] bus: last notification id reset after restoring db

Before this PR, the last notification id known by the client
was not reset after restoring the database. This was an issue
since there can be a gap between the last notification  and the
one that has been restored with the database. In this scenario,
messages are not received after restoring the database since the
client subscribes to higher notification ids that the ones that are
created.

This PR fixes this issue by defaulting to 0 if the one the client
passed is higher.

closes odoo/odoo#103311

X-original-commit: 5118da53a6e9adb94577a4f16999522a7e1e8c10
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
Signed-off-by: Stockbauer Matthieu (tsm) <tsm@odoo.com>
This commit is contained in:
tsm-odoo
2022-10-17 17:11:05 +02:00
parent 47ffe7b285
commit 461f1c7998
3 changed files with 42 additions and 0 deletions
+3
View File
@@ -44,6 +44,9 @@ class WebsocketController(Controller):
channel_with_db(request.db, c)
for c in request.env['ir.websocket']._build_bus_channel_list(channels)
))
last_known_notification_id = request.env['bus.bus'].sudo().search([], limit=1, order='id desc').id or 0
if last > last_known_notification_id:
last = 0
notifications = request.env['bus.bus']._poll(channels, last)
return {'channels': channels, 'notifications': notifications}
+3
View File
@@ -32,6 +32,9 @@ class IrWebsocket(models.AbstractModel):
def _subscribe(self, data):
if not all(isinstance(c, str) for c in data['channels']):
raise ValueError("bus.Bus only string channels are allowed.")
last_known_notification_id = self.env['bus.bus'].sudo().search([], limit=1, order='id desc').id or 0
if data['last'] > last_known_notification_id:
data['last'] = 0
channels = set(self._build_bus_channel_list(data['channels']))
dispatch.subscribe(channels, data['last'], self.env.registry.db_name, wsrequest.ws)
@@ -248,3 +248,39 @@ class TestWebsocketCaryall(WebsocketCase):
# But ChromeHeadless still can.
headers = ['User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/102.0.0.0 Safari/537.36']
self.websocket_connect()
def test_subscribe_higher_last_notification_id(self):
subscribe_done_event = Event()
server_last_notification_id = self.env['bus.bus'].sudo().search([], limit=1, order='id desc').id or 0
client_last_notification_id = server_last_notification_id + 1
def subscribe_side_effect(_, last):
# Last notification id given by the client is higher than
# the one known by the server, should default to 0.
self.assertEqual(last, 0)
subscribe_done_event.set()
with patch.object(Websocket, 'subscribe', side_effect=subscribe_side_effect):
websocket = self.websocket_connect()
websocket.send(json.dumps({
'event_name': 'subscribe',
'data': {'channels': ['my_channel'], 'last': client_last_notification_id}
}))
subscribe_done_event.wait()
def test_subscribe_lower_last_notification_id(self):
subscribe_done_event = Event()
server_last_notification_id = self.env['bus.bus'].sudo().search([], limit=1, order='id desc').id or 0
client_last_notification_id = server_last_notification_id - 1
def subscribe_side_effect(_, last):
self.assertEqual(last, client_last_notification_id)
subscribe_done_event.set()
with patch.object(Websocket, 'subscribe', side_effect=subscribe_side_effect):
websocket = self.websocket_connect()
websocket.send(json.dumps({
'event_name': 'subscribe',
'data': {'channels': ['my_channel'], 'last': client_last_notification_id}
}))
subscribe_done_event.wait()