Example #1
0
    def test_send_receipts(self):
        mock_send_transaction = (
            self.hs.get_federation_transport_client().send_transaction)
        mock_send_transaction.return_value = make_awaitable({})

        sender = self.hs.get_federation_sender()
        receipt = ReadReceipt("room_id", "m.read", "user_id", ["event_id"],
                              {"ts": 1234})
        self.successResultOf(
            defer.ensureDeferred(sender.send_read_receipt(receipt)))

        self.pump()

        # expect a call to send_transaction
        mock_send_transaction.assert_called_once()
        json_cb = mock_send_transaction.call_args[0][1]
        data = json_cb()
        self.assertEqual(
            data["edus"],
            [{
                "edu_type": "m.receipt",
                "content": {
                    "room_id": {
                        "m.read": {
                            "user_id": {
                                "event_ids": ["event_id"],
                                "data": {
                                    "ts": 1234
                                },
                            }
                        }
                    }
                },
            }],
        )
Example #2
0
    async def _received_remote_receipt(self, origin: str,
                                       content: JsonDict) -> None:
        """Called when we receive an EDU of type m.receipt from a remote HS."""
        receipts = []
        for room_id, room_values in content.items():
            for receipt_type, users in room_values.items():
                for user_id, user_values in users.items():
                    if get_domain_from_id(user_id) != origin:
                        logger.info(
                            "Received receipt for user %r from server %s, ignoring",
                            user_id,
                            origin,
                        )
                        continue

                    receipts.append(
                        ReadReceipt(
                            room_id=room_id,
                            receipt_type=receipt_type,
                            user_id=user_id,
                            event_ids=user_values["event_ids"],
                            data=user_values.get("data", {}),
                        ))

        await self._handle_new_receipts(receipts)
Example #3
0
    def _received_remote_receipt(self, origin, content):
        """Called when we receive an EDU of type m.receipt from a remote HS.
        """
        receipts = [
            ReadReceipt(
                room_id=room_id,
                receipt_type=receipt_type,
                user_id=user_id,
                event_ids=user_values["event_ids"],
                data=user_values.get("data", {}),
            ) for room_id, room_values in content.items()
            for receipt_type, users in room_values.items()
            for user_id, user_values in users.items()
        ]

        yield self._handle_new_receipts(receipts)
Example #4
0
    async def received_client_receipt(self, room_id, receipt_type, user_id, event_id):
        """Called when a client tells us a local user has read up to the given
        event_id in the room.
        """
        receipt = ReadReceipt(
            room_id=room_id,
            receipt_type=receipt_type,
            user_id=user_id,
            event_ids=[event_id],
            data={"ts": int(self.clock.time_msec())},
        )

        is_new = await self._handle_new_receipts([receipt])
        if not is_new:
            return

        await self.federation.send_read_receipt(receipt)
Example #5
0
 def _on_new_receipts(self, rows):
     """
     Args:
         rows (iterable[synapse.replication.tcp.streams.ReceiptsStreamRow]):
             new receipts to be processed
     """
     for receipt in rows:
         # we only want to send on receipts for our own users
         if not self._is_mine_id(receipt.user_id):
             continue
         receipt_info = ReadReceipt(
             receipt.room_id,
             receipt.receipt_type,
             receipt.user_id,
             [receipt.event_id],
             receipt.data,
         )
         yield self.federation_sender.send_read_receipt(receipt_info)
Example #6
0
    async def received_client_receipt(self, room_id: str, receipt_type: str,
                                      user_id: str, event_id: str) -> None:
        """Called when a client tells us a local user has read up to the given
        event_id in the room.
        """
        receipt = ReadReceipt(
            room_id=room_id,
            receipt_type=receipt_type,
            user_id=user_id,
            event_ids=[event_id],
            data={"ts": int(self.clock.time_msec())},
        )

        is_new = await self._handle_new_receipts([receipt])
        if not is_new:
            return

        if self.federation_sender and receipt_type != ReceiptTypes.READ_PRIVATE:
            await self.federation_sender.send_read_receipt(receipt)
Example #7
0
 async def _on_new_receipts(self, rows):
     """
     Args:
         rows (Iterable[synapse.replication.tcp.streams.ReceiptsStream.ReceiptsStreamRow]):
             new receipts to be processed
     """
     for receipt in rows:
         # we only want to send on receipts for our own users
         if not self._is_mine_id(receipt.user_id):
             continue
         if (receipt.data.get("hidden", False)
                 and self._hs.config.experimental.msc2285_enabled):
             continue
         receipt_info = ReadReceipt(
             receipt.room_id,
             receipt.receipt_type,
             receipt.user_id,
             [receipt.event_id],
             receipt.data,
         )
         await self.federation_sender.send_read_receipt(receipt_info)
Example #8
0
 async def _on_new_receipts(
         self, rows: Iterable[ReceiptsStream.ReceiptsStreamRow]) -> None:
     """
     Args:
         rows: new receipts to be processed
     """
     for receipt in rows:
         # we only want to send on receipts for our own users
         if not self._is_mine_id(receipt.user_id):
             continue
         # Private read receipts never get sent over federation.
         if receipt.receipt_type == ReceiptTypes.READ_PRIVATE:
             continue
         receipt_info = ReadReceipt(
             receipt.room_id,
             receipt.receipt_type,
             receipt.user_id,
             [receipt.event_id],
             receipt.data,
         )
         await self.federation_sender.send_read_receipt(receipt_info)
Example #9
0
    async def _received_remote_receipt(self, origin: str, content: JsonDict) -> None:
        """Called when we receive an EDU of type m.receipt from a remote HS."""
        receipts = []
        for room_id, room_values in content.items():
            # If we're not in the room just ditch the event entirely. This is
            # probably an old server that has come back and thinks we're still in
            # the room (or we've been rejoined to the room by a state reset).
            is_in_room = await self.event_auth_handler.check_host_in_room(
                room_id, self.server_name
            )
            if not is_in_room:
                logger.info(
                    "Ignoring receipt for room %r from server %s as we're not in the room",
                    room_id,
                    origin,
                )
                continue

            for receipt_type, users in room_values.items():
                for user_id, user_values in users.items():
                    if get_domain_from_id(user_id) != origin:
                        logger.info(
                            "Received receipt for user %r from server %s, ignoring",
                            user_id,
                            origin,
                        )
                        continue

                    receipts.append(
                        ReadReceipt(
                            room_id=room_id,
                            receipt_type=receipt_type,
                            user_id=user_id,
                            event_ids=user_values["event_ids"],
                            data=user_values.get("data", {}),
                        )
                    )

        await self._handle_new_receipts(receipts)
Example #10
0
    async def received_client_receipt(
        self, room_id: str, receipt_type: str, user_id: str, event_id: str, hidden: bool
    ) -> None:
        """Called when a client tells us a local user has read up to the given
        event_id in the room.
        """
        receipt = ReadReceipt(
            room_id=room_id,
            receipt_type=receipt_type,
            user_id=user_id,
            event_ids=[event_id],
            data={"ts": int(self.clock.time_msec()), "hidden": hidden},
        )

        is_new = await self._handle_new_receipts([receipt])
        if not is_new:
            return

        if self.federation_sender and not (
            self.hs.config.experimental.msc2285_enabled and hidden
        ):
            await self.federation_sender.send_read_receipt(receipt)
Example #11
0
    def test_send_receipts(self):
        mock_state_handler = self.hs.get_state_handler()
        mock_state_handler.get_current_hosts_in_room.return_value = [
            "test", "host2"
        ]

        mock_send_transaction = (
            self.hs.get_federation_transport_client().send_transaction)
        mock_send_transaction.return_value = defer.succeed({})

        sender = self.hs.get_federation_sender()
        receipt = ReadReceipt("room_id", "m.read", "user_id", ["event_id"],
                              {"ts": 1234})
        self.successResultOf(sender.send_read_receipt(receipt))

        self.pump()

        # expect a call to send_transaction
        mock_send_transaction.assert_called_once()
        json_cb = mock_send_transaction.call_args[0][1]
        data = json_cb()
        self.assertEqual(
            data['edus'],
            [{
                'edu_type': 'm.receipt',
                'content': {
                    'room_id': {
                        'm.read': {
                            'user_id': {
                                'event_ids': ['event_id'],
                                'data': {
                                    'ts': 1234
                                },
                            }
                        }
                    }
                },
            }],
        )
Example #12
0
    def test_send_receipts_with_backoff(self):
        """Send two receipts in quick succession; the second should be flushed, but
        only after 20ms"""
        mock_send_transaction = (
            self.hs.get_federation_transport_client().send_transaction)
        mock_send_transaction.return_value = make_awaitable({})

        sender = self.hs.get_federation_sender()
        receipt = ReadReceipt("room_id", "m.read", "user_id", ["event_id"],
                              {"ts": 1234})
        self.successResultOf(
            defer.ensureDeferred(sender.send_read_receipt(receipt)))

        self.pump()

        # expect a call to send_transaction
        mock_send_transaction.assert_called_once()
        json_cb = mock_send_transaction.call_args[0][1]
        data = json_cb()
        self.assertEqual(
            data["edus"],
            [{
                "edu_type": "m.receipt",
                "content": {
                    "room_id": {
                        "m.read": {
                            "user_id": {
                                "event_ids": ["event_id"],
                                "data": {
                                    "ts": 1234
                                },
                            }
                        }
                    }
                },
            }],
        )
        mock_send_transaction.reset_mock()

        # send the second RR
        receipt = ReadReceipt("room_id", "m.read", "user_id", ["other_id"],
                              {"ts": 1234})
        self.successResultOf(
            defer.ensureDeferred(sender.send_read_receipt(receipt)))
        self.pump()
        mock_send_transaction.assert_not_called()

        self.reactor.advance(19)
        mock_send_transaction.assert_not_called()

        self.reactor.advance(10)
        mock_send_transaction.assert_called_once()
        json_cb = mock_send_transaction.call_args[0][1]
        data = json_cb()
        self.assertEqual(
            data["edus"],
            [{
                "edu_type": "m.receipt",
                "content": {
                    "room_id": {
                        "m.read": {
                            "user_id": {
                                "event_ids": ["other_id"],
                                "data": {
                                    "ts": 1234
                                },
                            }
                        }
                    }
                },
            }],
        )
Example #13
0
    def test_send_receipts_with_backoff(self):
        """Send two receipts in quick succession; the second should be flushed, but
        only after 20ms"""
        mock_state_handler = self.hs.get_state_handler()
        mock_state_handler.get_current_hosts_in_room.return_value = [
            "test", "host2"
        ]

        mock_send_transaction = (
            self.hs.get_federation_transport_client().send_transaction)
        mock_send_transaction.return_value = defer.succeed({})

        sender = self.hs.get_federation_sender()
        receipt = ReadReceipt("room_id", "m.read", "user_id", ["event_id"],
                              {"ts": 1234})
        self.successResultOf(sender.send_read_receipt(receipt))

        self.pump()

        # expect a call to send_transaction
        mock_send_transaction.assert_called_once()
        json_cb = mock_send_transaction.call_args[0][1]
        data = json_cb()
        self.assertEqual(
            data['edus'],
            [{
                'edu_type': 'm.receipt',
                'content': {
                    'room_id': {
                        'm.read': {
                            'user_id': {
                                'event_ids': ['event_id'],
                                'data': {
                                    'ts': 1234
                                },
                            }
                        }
                    }
                },
            }],
        )
        mock_send_transaction.reset_mock()

        # send the second RR
        receipt = ReadReceipt("room_id", "m.read", "user_id", ["other_id"],
                              {"ts": 1234})
        self.successResultOf(sender.send_read_receipt(receipt))
        self.pump()
        mock_send_transaction.assert_not_called()

        self.reactor.advance(19)
        mock_send_transaction.assert_not_called()

        self.reactor.advance(10)
        mock_send_transaction.assert_called_once()
        json_cb = mock_send_transaction.call_args[0][1]
        data = json_cb()
        self.assertEqual(
            data['edus'],
            [{
                'edu_type': 'm.receipt',
                'content': {
                    'room_id': {
                        'm.read': {
                            'user_id': {
                                'event_ids': ['other_id'],
                                'data': {
                                    'ts': 1234
                                },
                            }
                        }
                    }
                },
            }],
        )