diff --git a/addons/mail/controllers/discuss.py b/addons/mail/controllers/discuss.py index 7ae3c99bad0..3ef41e6901d 100644 --- a/addons/mail/controllers/discuss.py +++ b/addons/mail/controllers/discuss.py @@ -377,7 +377,11 @@ class DiscussController(http.Controller): ('id', '=', int(rtc_session_id)), ('channel_partner_id', '=', channel_partner_sudo.id), ]).write({}) # update write_date - return {'rtcSessions': channel_partner_sudo._rtc_sync_sessions(check_rtc_session_ids=check_rtc_session_ids)} + current_rtc_sessions, outdated_rtc_sessions = channel_partner_sudo._rtc_sync_sessions(check_rtc_session_ids=check_rtc_session_ids) + return {'rtcSessions': [ + ('insert', [rtc_session_sudo._mail_rtc_session_format(complete_info=False) for rtc_session_sudo in current_rtc_sessions]), + ('insert-and-unlink', [{'id': missing_rtc_session_sudo.id} for missing_rtc_session_sudo in outdated_rtc_sessions]), + ]} # -------------------------------------------------------------------------- # Chatter API diff --git a/addons/mail/models/mail_channel_partner.py b/addons/mail/models/mail_channel_partner.py index cf4ce567867..8abca5a1c36 100644 --- a/addons/mail/models/mail_channel_partner.py +++ b/addons/mail/models/mail_channel_partner.py @@ -114,9 +114,13 @@ class ChannelPartner(models.Model): self.channel_id._rtc_cancel_invitations(partner_ids=self.partner_id.ids, guest_ids=self.guest_id.ids) self.rtc_session_ids.unlink() rtc_session = self.env['mail.channel.rtc.session'].create({'channel_partner_id': self.id}) + current_rtc_sessions, outdated_rtc_sessions = self._rtc_sync_sessions(check_rtc_session_ids=check_rtc_session_ids) res = { 'iceServers': self.env['mail.ice.server']._get_ice_servers() or False, - 'rtcSessions': self._rtc_sync_sessions(check_rtc_session_ids=check_rtc_session_ids), + 'rtcSessions': [ + ('insert', [rtc_session_sudo._mail_rtc_session_format() for rtc_session_sudo in current_rtc_sessions]), + ('insert-and-unlink', [{'id': missing_rtc_session_sudo.id} for missing_rtc_session_sudo in outdated_rtc_sessions]), + ], 'sessionId': rtc_session.id, } if len(self.channel_id.rtc_session_ids) == 1 and self.channel_id.channel_type in {'chat', 'group'}: @@ -141,15 +145,13 @@ class ChannelPartner(models.Model): - Current sessions are returned. - Sessions given in check_rtc_session_ids that no longer exists are returned as non-existing. - Returns a list of JS command for updating rtcSessions field of channel. + :param list check_rtc_session_ids: list of the ids of the sessions to check + :returns tuple: (current_rtc_sessions, outdated_rtc_sessions) """ self.ensure_one() self.channel_id.rtc_session_ids._delete_inactive_rtc_sessions() check_rtc_sessions = self.env['mail.channel.rtc.session'].browse([int(check_rtc_session_id) for check_rtc_session_id in (check_rtc_session_ids or [])]) - return [ - ('insert', [rtc_session_sudo._mail_rtc_session_format() for rtc_session_sudo in self.channel_id.rtc_session_ids]), - ('insert-and-unlink', [{'id': missing_rtc_session_sudo.id} for missing_rtc_session_sudo in check_rtc_sessions - self.channel_id.rtc_session_ids]), - ] + return self.channel_id.rtc_session_ids, check_rtc_sessions - self.channel_id.rtc_session_ids def _rtc_invite_members(self, partner_ids=None, guest_ids=None): """ Sends invitations to join the RTC call to all connected members of the thread who are not already invited. diff --git a/addons/mail/models/mail_channel_rtc_session.py b/addons/mail/models/mail_channel_rtc_session.py index d6ba1b15fde..ca1d22796c3 100644 --- a/addons/mail/models/mail_channel_rtc_session.py +++ b/addons/mail/models/mail_channel_rtc_session.py @@ -115,15 +115,18 @@ class MailRtcSession(models.Model): 'payload': payload, }) for target, payload in payload_by_target.items()]) - def _mail_rtc_session_format(self): + def _mail_rtc_session_format(self, complete_info=True): self.ensure_one() vals = { 'id': self.id, - 'isCameraOn': self.is_camera_on, - 'isDeaf': self.is_deaf, - 'isMuted': self.is_muted, - 'isScreenSharingOn': self.is_screen_sharing_on, } + if complete_info: + vals.update({ + 'isCameraOn': self.is_camera_on, + 'isDeaf': self.is_deaf, + 'isMuted': self.is_muted, + 'isScreenSharingOn': self.is_screen_sharing_on, + }) if self.guest_id: vals['guest'] = [('insert', { 'id': self.guest_id.id, diff --git a/addons/mail/tests/test_rtc.py b/addons/mail/tests/test_rtc.py index 65eed27b376..0ede07d94ac 100644 --- a/addons/mail/tests/test_rtc.py +++ b/addons/mail/tests/test_rtc.py @@ -592,3 +592,45 @@ class TestChannelInternals(MailCommon): ): channel_partner.rtc_session_ids.action_disconnect() self.assertFalse(channel_partner.rtc_session_ids) + + @users('employee') + @mute_logger('odoo.models.unlink') + def test_60_rtc_sync_sessions_should_gc_and_return_outdated_and_active_sessions(self): + channel = self.env['mail.channel'].browse(self.env['mail.channel'].create_group(partners_to=self.user_employee.partner_id.ids)['id']) + channel_partner = channel.sudo().channel_last_seen_partner_ids.filtered(lambda channel_partner: channel_partner.partner_id == self.user_employee.partner_id) + join_call_values = channel_partner._rtc_join_call() + test_guest = self.env['mail.guest'].sudo().create({'name': "Test Guest"}) + test_channel_partner = self.env['mail.channel.partner'].create({ + 'guest_id': test_guest.id, + 'channel_id': channel.id, + }) + test_session = self.env['mail.channel.rtc.session'].sudo().create({'channel_partner_id': test_channel_partner.id}) + test_session.flush() + test_session._write({'write_date': fields.Datetime.now() - relativedelta(days=2)}) + unused_ids = [9998, 9999] + self.env['bus.bus'].sudo().search([]).unlink() + with self.assertBus( + [ + (self.cr.dbname, 'mail.guest', test_guest.id), # session ended + (self.cr.dbname, 'mail.channel', channel.id), # update list of sessions + ], + [ + { + 'type': 'rtc_session_ended', + 'payload': { + 'sessionId': test_session.id, + }, + }, + { + 'type': 'rtc_sessions_update', + 'payload': { + 'id': channel.id, + 'rtcSessions': [('insert-and-unlink', [{'id': test_session.id}])], + }, + }, + ], + ): + current_rtc_sessions, outdated_rtc_sessions = channel_partner._rtc_sync_sessions(check_rtc_session_ids=[join_call_values['sessionId']] + unused_ids) + self.assertEqual(channel_partner.rtc_session_ids, current_rtc_sessions) + self.assertEqual(unused_ids, outdated_rtc_sessions.ids) + self.assertFalse(outdated_rtc_sessions.exists())