コード例 #1
0
    def on_POSITION(self, conn: IReplicationConnection, cmd: PositionCommand) -> None:
        if cmd.instance_name == self._instance_name:
            # Ignore POSITION that are just our own echoes
            return

        logger.debug("Handling '%s %s'", cmd.NAME, cmd.to_line())

        self._add_command_to_stream_queue(conn, cmd)
コード例 #2
0
ファイル: handler.py プロジェクト: lfaraone/synapse
    async def on_POSITION(self, conn: AbstractConnection, cmd: PositionCommand):
        if cmd.instance_name == self._instance_name:
            # Ignore POSITION that are just our own echoes
            return

        logger.info("Handling '%s %s'", cmd.NAME, cmd.to_line())

        stream_name = cmd.stream_name
        stream = self._streams.get(stream_name)
        if not stream:
            logger.error("Got POSITION for unknown stream: %s", stream_name)
            return

        # We protect catching up with a linearizer in case the replication
        # connection reconnects under us.
        with await self._position_linearizer.queue(stream_name):
            # We're about to go and catch up with the stream, so remove from set
            # of connected streams.
            for streams in self._streams_by_connection.values():
                streams.discard(stream_name)

            # We clear the pending batches for the stream as the fetching of the
            # missing updates below will fetch all rows in the batch.
            self._pending_batches.pop(stream_name, [])

            # Find where we previously streamed up to.
            current_token = stream.current_token(cmd.instance_name)

            # If the position token matches our current token then we're up to
            # date and there's nothing to do. Otherwise, fetch all updates
            # between then and now.
            missing_updates = cmd.token != current_token
            while missing_updates:
                logger.info(
                    "Fetching replication rows for '%s' between %i and %i",
                    stream_name,
                    current_token,
                    cmd.token,
                )
                (
                    updates,
                    current_token,
                    missing_updates,
                ) = await stream.get_updates_since(
                    cmd.instance_name, current_token, cmd.token
                )

                # TODO: add some tests for this

                # Some streams return multiple rows with the same stream IDs,
                # which need to be processed in batches.

                for token, rows in _batch_updates(updates):
                    await self.on_rdata(
                        stream_name,
                        cmd.instance_name,
                        token,
                        [stream.parse_row(row) for row in rows],
                    )

            logger.info("Caught up with stream '%s' to %i", stream_name, cmd.token)

            # We've now caught up to position sent to us, notify handler.
            await self._replication_data_handler.on_position(
                cmd.stream_name, cmd.instance_name, cmd.token
            )

            self._streams_by_connection.setdefault(conn, set()).add(stream_name)