-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Move catchup of replication streams to worker. #7024
Changes from 15 commits
7233d38
811d2ec
ba90596
1f83255
8734b75
32c6568
259cdff
4f2a803
a2070a2
ba1a8be
3204b0e
2380e40
e4c5b1d
309aee4
bd64b8f
f8038f4
309c7eb
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 @@ | ||
Move catchup of replication streams logic to worker. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -401,6 +401,9 @@ def process_replication_rows(self, token, rows): | |
self._room_serials[row.room_id] = token | ||
self._room_typing[row.room_id] = row.user_ids | ||
|
||
def get_current_token(self) -> int: | ||
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. where is this used? 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. This gets used by the |
||
return self._latest_room_serial | ||
|
||
|
||
class GenericWorkerSlavedStore( | ||
# FIXME(#3714): We need to add UserDirectoryStore as we write directly | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
# -*- coding: utf-8 -*- | ||
# Copyright 2020 The Matrix.org Foundation C.I.C. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
import logging | ||
|
||
from synapse.api.errors import SynapseError | ||
from synapse.http.servlet import parse_integer | ||
from synapse.replication.http._base import ReplicationEndpoint | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class ReplicationGetStreamUpdates(ReplicationEndpoint): | ||
"""Fetches stream updates from a server. Used for streams not persisted to | ||
the database, e.g. typing notifications. | ||
|
||
The API looks like: | ||
|
||
GET /_synapse/replication/get_repl_stream_updates/events?from_token=0&to_token=10&limit=100 | ||
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.
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. I thought we generally avoided saying inclusive vs exclusive, and rather thought about tokens as being "between" items? I don't know if that is helpful, can add the comment in |
||
|
||
200 OK | ||
|
||
{ | ||
updates: [ ... ], | ||
upto_token: 10, | ||
limited: False, | ||
} | ||
|
||
""" | ||
erikjohnston marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
NAME = "get_repl_stream_updates" | ||
PATH_ARGS = ("stream_name",) | ||
METHOD = "GET" | ||
|
||
def __init__(self, hs): | ||
super().__init__(hs) | ||
|
||
# We pull the streams from the replication steamer (if we try and make | ||
# them ourselves we end up in an import loop). | ||
self.streams = hs.get_replication_streamer().get_streams() | ||
|
||
@staticmethod | ||
def _serialize_payload(stream_name, from_token, upto_token, limit): | ||
return {"from_token": from_token, "upto_token": upto_token, "limit": limit} | ||
|
||
async def _handle_request(self, request, stream_name): | ||
stream = self.streams.get(stream_name) | ||
if stream is None: | ||
raise SynapseError(400, "Unknown stream") | ||
|
||
from_token = parse_integer(request, "from_token", required=True) | ||
upto_token = parse_integer(request, "upto_token", required=True) | ||
limit = parse_integer(request, "limit", required=True) | ||
|
||
updates, upto_token, limited = await stream.get_updates_since( | ||
from_token, upto_token, limit | ||
) | ||
|
||
return ( | ||
200, | ||
{"updates": updates, "upto_token": upto_token, "limited": limited}, | ||
) | ||
|
||
|
||
def register_servlets(hs, http_server): | ||
ReplicationGetStreamUpdates(hs).register(http_server) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
am I right in thinking it is only sent on connect? might be worth saying that? or otherwise saying when it is sent?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally happens in response to a
REPLICATE
command, but in a redis world they'll be flying around whenever anyone connects and sends aREPLICATE
. Will update comment.