`psycopg2` errors sometimes happen during tests. This is caused by race conditions between several `cr.execute()`/`cr.fetch*`. This is even worse with websockets that are long lived connections that sometimes open a cursor in the middle of the test. Before websockets, longpolling was just disabled during tests. This commits disable websockets as well in order to prevent those errors as much as possible. Some live chat tours were updated in [1] after the websockets intro- duction due to some race conditions. This was reverted as the fix relied on a hack on websockets that are now unavailable. fixes runbot-25357,24809 [1]: https://github.com/odoo/odoo/pull/103521 closes odoo/odoo#143647 X-original-commit: e3b07a301036fcce76ebbbd856b507326b88160a Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com> Signed-off-by: Matthieu Stockbauer (tsm) <tsm@odoo.com>
65 lines
2.9 KiB
Python
65 lines
2.9 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
import json
|
|
|
|
from odoo.http import Controller, request, route, SessionExpiredException
|
|
from odoo.addons.base.models.assetsbundle import AssetsBundle
|
|
from ..models.bus import channel_with_db
|
|
from ..websocket import WebsocketConnectionHandler
|
|
|
|
|
|
class WebsocketController(Controller):
|
|
@route('/websocket', type="http", auth="public", cors='*', websocket=True)
|
|
def websocket(self):
|
|
"""
|
|
Handle the websocket handshake, upgrade the connection if
|
|
successfull.
|
|
"""
|
|
return WebsocketConnectionHandler.open_connection(request)
|
|
|
|
@route('/websocket/health', type='http', auth='none', save_session=False)
|
|
def health(self):
|
|
data = json.dumps({
|
|
'status': 'pass',
|
|
})
|
|
headers = [('Content-Type', 'application/json'),
|
|
('Cache-Control', 'no-store')]
|
|
return request.make_response(data, headers)
|
|
|
|
@route('/websocket/peek_notifications', type='json', auth='public', cors='*')
|
|
def peek_notifications(self, channels, last, is_first_poll=False):
|
|
if not all(isinstance(c, str) for c in channels):
|
|
raise ValueError("bus.Bus only string channels are allowed.")
|
|
if is_first_poll:
|
|
# Used to detect when the current session is expired.
|
|
request.session['is_websocket_session'] = True
|
|
elif 'is_websocket_session' not in request.session:
|
|
raise SessionExpiredException()
|
|
channels = list(set(
|
|
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}
|
|
|
|
@route('/websocket/update_bus_presence', type='json', auth='public', cors='*')
|
|
def update_bus_presence(self, inactivity_period, im_status_ids_by_model):
|
|
if 'is_websocket_session' not in request.session:
|
|
raise SessionExpiredException()
|
|
request.env['ir.websocket']._update_bus_presence(int(inactivity_period), im_status_ids_by_model)
|
|
return {}
|
|
|
|
@route('/bus/websocket_worker_bundle', type='http', auth='public', cors='*')
|
|
def get_websocket_worker_bundle(self, v=None): # pylint: disable=unused-argument
|
|
"""
|
|
:param str v: Version of the worker, frontend only argument used to
|
|
prevent new worker versions to be loaded from the browser cache.
|
|
"""
|
|
bundle_name = 'bus.websocket_worker_assets'
|
|
bundle = request.env["ir.qweb"]._get_asset_bundle(bundle_name, debug_assets="assets" in request.session.debug)
|
|
stream = request.env['ir.binary']._get_stream_from(bundle.js())
|
|
return stream.get_response()
|