Пример #1
0
    def send_command(self, cmd: Command):
        """Send a command if connection has been established.

        Args:
            cmd (Command)
        """
        string = "%s %s" % (cmd.NAME, cmd.to_line())
        if "\n" in string:
            raise Exception("Unexpected newline in command: %r", string)

        encoded_string = string.encode("utf-8")

        # We use "redis" as the name here as we don't have 1:1 connections to
        # remote instances.
        tcp_outbound_commands_counter.labels(cmd.NAME, "redis").inc()

        async def _send():
            with PreserveLoggingContext():
                # Note that we use the other connection as we can't send
                # commands using the subscription connection.
                await self.outbound_redis_connection.publish(
                    self.stream_name, encoded_string
                )

        run_as_background_process("send-cmd", _send)
Пример #2
0
    def send_command(self, cmd: Command, do_buffer: bool = True) -> None:
        """Send a command if connection has been established.

        Args:
            cmd
            do_buffer: Whether to buffer the message or always attempt
                to send the command. This is mostly used to send an error
                message if we're about to close the connection due our buffers
                becoming full.
        """
        if self.state == ConnectionStates.CLOSED:
            logger.debug("[%s] Not sending, connection closed", self.id())
            return

        if do_buffer and self.state != ConnectionStates.ESTABLISHED:
            self._queue_command(cmd)
            return

        tcp_outbound_commands_counter.labels(cmd.NAME, self.name).inc()

        string = "%s %s" % (cmd.NAME, cmd.to_line())
        if "\n" in string:
            raise Exception("Unexpected newline in command: %r", string)

        encoded_string = string.encode("utf-8")

        if len(encoded_string) > self.MAX_LENGTH:
            raise Exception("Failed to send command %s as too long (%d > %d)" %
                            (cmd.NAME, len(encoded_string), self.MAX_LENGTH))

        self.sendLine(encoded_string)

        self.last_sent_command = self.clock.time_msec()
Пример #3
0
    async def _async_send_command(self, cmd: Command) -> None:
        """Encode a replication command and send it over our outbound connection"""
        string = "%s %s" % (cmd.NAME, cmd.to_line())
        if "\n" in string:
            raise Exception("Unexpected newline in command: %r", string)

        encoded_string = string.encode("utf-8")

        # We use "redis" as the name here as we don't have 1:1 connections to
        # remote instances.
        tcp_outbound_commands_counter.labels(cmd.NAME, "redis").inc()

        channel_name = cmd.redis_channel_name(self.synapse_stream_prefix)

        await make_deferred_yieldable(
            self.synapse_outbound_redis_connection.publish(
                channel_name, encoded_string))
Пример #4
0
    def handle_command(self, cmd: Command) -> None:
        """Handle a command we have received over the replication stream.

        First calls `self.on_<COMMAND>` if it exists, then calls
        `self.command_handler.on_<COMMAND>` if it exists (which can optionally
        return an Awaitable).

        This allows for protocol level handling of commands (e.g. PINGs), before
        delegating to the handler.

        Args:
            cmd: received command
        """
        handled = False

        # First call any command handlers on this instance. These are for TCP
        # specific handling.
        cmd_func = getattr(self, "on_%s" % (cmd.NAME,), None)
        if cmd_func:
            cmd_func(cmd)
            handled = True

        # Then call out to the handler.
        cmd_func = getattr(self.command_handler, "on_%s" % (cmd.NAME,), None)
        if cmd_func:
            res = cmd_func(self, cmd)

            # the handler might be a coroutine: fire it off as a background process
            # if so.

            if isawaitable(res):
                run_as_background_process(
                    "replication-" + cmd.get_logcontext_id(), lambda: res
                )

            handled = True

        if not handled:
            logger.warning("Unhandled command: %r", cmd)
Пример #5
0
    def handle_command(self, cmd: Command) -> None:
        """Handle a command we have received over the replication stream.

        Delegates to `self.handler.on_<COMMAND>` (which can optionally return an
        Awaitable).

        Args:
            cmd: received command
        """

        cmd_func = getattr(self.synapse_handler, "on_%s" % (cmd.NAME, ), None)
        if not cmd_func:
            logger.warning("Unhandled command: %r", cmd)
            return

        res = cmd_func(self, cmd)

        # the handler might be a coroutine: fire it off as a background process
        # if so.

        if isawaitable(res):
            run_as_background_process("replication-" + cmd.get_logcontext_id(),
                                      lambda: res)