-
Notifications
You must be signed in to change notification settings - Fork 522
Faster redis replication handling #19138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
74ce8c1
955c143
cae42be
9f8a540
4c9db58
b9a1611
d04778b
4437b4a
75fc400
6f2c518
98d8abc
4740afa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Minor speed up of processing of inbound replication. | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -20,7 +20,6 @@ | |||||||||||||
| # | ||||||||||||||
| # | ||||||||||||||
| import logging | ||||||||||||||
| from collections import deque | ||||||||||||||
| from typing import ( | ||||||||||||||
| TYPE_CHECKING, | ||||||||||||||
| Any, | ||||||||||||||
|
|
@@ -71,6 +70,7 @@ | |||||||||||||
| DeviceListsStream, | ||||||||||||||
| ThreadSubscriptionsStream, | ||||||||||||||
| ) | ||||||||||||||
| from synapse.util.async_helpers import BackgroundQueue | ||||||||||||||
|
|
||||||||||||||
| if TYPE_CHECKING: | ||||||||||||||
| from synapse.server import HomeServer | ||||||||||||||
|
|
@@ -115,8 +115,8 @@ | |||||||||||||
|
|
||||||||||||||
|
|
||||||||||||||
| # the type of the entries in _command_queues_by_stream | ||||||||||||||
| _StreamCommandQueue = deque[ | ||||||||||||||
| tuple[Union[RdataCommand, PositionCommand], IReplicationConnection] | ||||||||||||||
| _StreamCommandQueueItem = tuple[ | ||||||||||||||
| Union[RdataCommand, PositionCommand], IReplicationConnection | ||||||||||||||
| ] | ||||||||||||||
|
|
||||||||||||||
|
|
||||||||||||||
|
|
@@ -265,7 +265,12 @@ def __init__(self, hs: "HomeServer"): | |||||||||||||
| # for each stream, a queue of commands that are awaiting processing, and the | ||||||||||||||
| # connection that they arrived on. | ||||||||||||||
| self._command_queues_by_stream = { | ||||||||||||||
| stream_name: _StreamCommandQueue() for stream_name in self._streams | ||||||||||||||
| stream_name: BackgroundQueue[_StreamCommandQueueItem]( | ||||||||||||||
| hs, | ||||||||||||||
| "process-replication-data", | ||||||||||||||
| self._unsafe_process, | ||||||||||||||
| ) | ||||||||||||||
| for stream_name in self._streams | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| # For each connection, the incoming stream names that have received a POSITION | ||||||||||||||
|
|
@@ -349,38 +354,13 @@ def _add_command_to_stream_queue( | |||||||||||||
| logger.error("Got %s for unknown stream: %s", cmd.NAME, stream_name) | ||||||||||||||
| return | ||||||||||||||
|
|
||||||||||||||
| queue.append((cmd, conn)) | ||||||||||||||
|
|
||||||||||||||
| # if we're already processing this stream, there's nothing more to do: | ||||||||||||||
| # the new entry on the queue will get picked up in due course | ||||||||||||||
| if stream_name in self._processing_streams: | ||||||||||||||
| return | ||||||||||||||
|
|
||||||||||||||
| # fire off a background process to start processing the queue. | ||||||||||||||
| self.hs.run_as_background_process( | ||||||||||||||
| "process-replication-data", | ||||||||||||||
| self._unsafe_process_queue, | ||||||||||||||
| stream_name, | ||||||||||||||
| ) | ||||||||||||||
|
|
||||||||||||||
| async def _unsafe_process_queue(self, stream_name: str) -> None: | ||||||||||||||
| """Processes the command queue for the given stream, until it is empty | ||||||||||||||
| queue.add((cmd, conn)) | ||||||||||||||
|
|
||||||||||||||
| Does not check if there is already a thread processing the queue, hence "unsafe" | ||||||||||||||
| """ | ||||||||||||||
| assert stream_name not in self._processing_streams | ||||||||||||||
|
|
||||||||||||||
| self._processing_streams.add(stream_name) | ||||||||||||||
| try: | ||||||||||||||
| queue = self._command_queues_by_stream.get(stream_name) | ||||||||||||||
| while queue: | ||||||||||||||
| cmd, conn = queue.popleft() | ||||||||||||||
| try: | ||||||||||||||
| await self._process_command(cmd, conn, stream_name) | ||||||||||||||
| except Exception: | ||||||||||||||
| logger.exception("Failed to handle command %s", cmd) | ||||||||||||||
| finally: | ||||||||||||||
| self._processing_streams.discard(stream_name) | ||||||||||||||
| async def _unsafe_process(self, item: _StreamCommandQueueItem) -> None: | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this unsafe anymore? If unsafe, we should maintain the docstring note from before. If not, we should rename this function.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Feel like this still needs a bit more clarity on why unsafe. Here is what it was changed to: synapse/synapse/replication/tcp/handler.py Lines 359 to 364 in 6790312
"Unsafe because this should be called ..." (and it's the caller's responsibility) |
||||||||||||||
| """Process a single command from the stream queue""" | ||||||||||||||
| cmd, conn = item | ||||||||||||||
| stream_name = cmd.stream_name | ||||||||||||||
| await self._process_command(cmd, conn, stream_name) | ||||||||||||||
|
|
||||||||||||||
| async def _process_command( | ||||||||||||||
| self, | ||||||||||||||
|
|
||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.