[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:
@@ -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}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user