mirror of
https://github.com/element-hq/synapse.git
synced 2024-12-22 20:50:23 +03:00
dkjfhsdklfhsdlkjf
This commit is contained in:
parent
0473f87a17
commit
83ecaeecbf
13 changed files with 90 additions and 60 deletions
|
@ -604,7 +604,7 @@ class GenericWorkerReplicationHandler(ReplicationDataHandler):
|
||||||
self.pusher_pool = hs.get_pusherpool()
|
self.pusher_pool = hs.get_pusherpool()
|
||||||
|
|
||||||
if hs.config.send_federation:
|
if hs.config.send_federation:
|
||||||
self.send_handler = FederationSenderHandler(hs, self)
|
self.send_handler = FederationSenderHandler(hs)
|
||||||
else:
|
else:
|
||||||
self.send_handler = None
|
self.send_handler = None
|
||||||
|
|
||||||
|
@ -624,7 +624,9 @@ class GenericWorkerReplicationHandler(ReplicationDataHandler):
|
||||||
async def process_and_notify(self, stream_name, instance_name, token, rows):
|
async def process_and_notify(self, stream_name, instance_name, token, rows):
|
||||||
try:
|
try:
|
||||||
if self.send_handler:
|
if self.send_handler:
|
||||||
self.send_handler.process_replication_rows(stream_name, token, rows)
|
self.send_handler.process_replication_rows(
|
||||||
|
stream_name, instance_name, token, rows
|
||||||
|
)
|
||||||
|
|
||||||
if stream_name == EventsStream.NAME:
|
if stream_name == EventsStream.NAME:
|
||||||
# We shouldn't get multiple rows per token for events stream, so
|
# We shouldn't get multiple rows per token for events stream, so
|
||||||
|
@ -724,13 +726,14 @@ class FederationSenderHandler(object):
|
||||||
to the federation sender.
|
to the federation sender.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, hs: GenericWorkerServer, replication_client):
|
def __init__(self, hs: GenericWorkerServer):
|
||||||
|
self.hs = hs
|
||||||
self.store = hs.get_datastore()
|
self.store = hs.get_datastore()
|
||||||
self._is_mine_id = hs.is_mine_id
|
self._is_mine_id = hs.is_mine_id
|
||||||
self.federation_sender = hs.get_federation_sender()
|
self.federation_sender = hs.get_federation_sender()
|
||||||
self.replication_client = replication_client
|
# self.replication_client = hs.get_tcp_replication()
|
||||||
|
|
||||||
self.federation_position = self.store.federation_out_pos_startup
|
self.federation_position = {"master": self.store.federation_out_pos_startup}
|
||||||
self._fed_position_linearizer = Linearizer(name="_fed_position_linearizer")
|
self._fed_position_linearizer = Linearizer(name="_fed_position_linearizer")
|
||||||
|
|
||||||
self._last_ack = self.federation_position
|
self._last_ack = self.federation_position
|
||||||
|
@ -749,14 +752,14 @@ class FederationSenderHandler(object):
|
||||||
self.federation_sender.wake_destination(server)
|
self.federation_sender.wake_destination(server)
|
||||||
|
|
||||||
def stream_positions(self):
|
def stream_positions(self):
|
||||||
return {"federation": {"master": self.federation_position}}
|
return {"federation": self.federation_position}
|
||||||
|
|
||||||
def process_replication_rows(self, stream_name, token, rows):
|
def process_replication_rows(self, stream_name, instance_name, token, rows):
|
||||||
# The federation stream contains things that we want to send out, e.g.
|
# The federation stream contains things that we want to send out, e.g.
|
||||||
# presence, typing, etc.
|
# presence, typing, etc.
|
||||||
if stream_name == "federation":
|
if stream_name == "federation":
|
||||||
send_queue.process_rows_for_federation(self.federation_sender, rows)
|
send_queue.process_rows_for_federation(self.federation_sender, rows)
|
||||||
run_in_background(self.update_token, token)
|
run_in_background(self.update_token, instance_name, token)
|
||||||
|
|
||||||
# We also need to poke the federation sender when new events happen
|
# We also need to poke the federation sender when new events happen
|
||||||
elif stream_name == "events":
|
elif stream_name == "events":
|
||||||
|
@ -804,9 +807,12 @@ class FederationSenderHandler(object):
|
||||||
)
|
)
|
||||||
await self.federation_sender.send_read_receipt(receipt_info)
|
await self.federation_sender.send_read_receipt(receipt_info)
|
||||||
|
|
||||||
async def update_token(self, token):
|
async def update_token(self, instance_name, token):
|
||||||
try:
|
try:
|
||||||
self.federation_position = token
|
self.federation_position[instance_name] = token
|
||||||
|
return
|
||||||
|
|
||||||
|
# FIXME
|
||||||
|
|
||||||
# We linearize here to ensure we don't have races updating the token
|
# We linearize here to ensure we don't have races updating the token
|
||||||
with (await self._fed_position_linearizer.queue(None)):
|
with (await self._fed_position_linearizer.queue(None)):
|
||||||
|
@ -817,7 +823,7 @@ class FederationSenderHandler(object):
|
||||||
|
|
||||||
# We ACK this token over replication so that the master can drop
|
# We ACK this token over replication so that the master can drop
|
||||||
# its in memory queues
|
# its in memory queues
|
||||||
self.replication_client.send_federation_ack(
|
self.hs.get_tcp_replication().send_federation_ack(
|
||||||
self.federation_position
|
self.federation_position
|
||||||
)
|
)
|
||||||
self._last_ack = self.federation_position
|
self._last_ack = self.federation_position
|
||||||
|
|
|
@ -48,6 +48,8 @@ class WorkerConfig(Config):
|
||||||
|
|
||||||
self.worker_main_http_uri = config.get("worker_main_http_uri", None)
|
self.worker_main_http_uri = config.get("worker_main_http_uri", None)
|
||||||
|
|
||||||
|
self.instance_http_map = config.get("instance_http_map", {})
|
||||||
|
|
||||||
# This option is really only here to support `--manhole` command line
|
# This option is really only here to support `--manhole` command line
|
||||||
# argument.
|
# argument.
|
||||||
manhole = config.get("worker_manhole")
|
manhole = config.get("worker_manhole")
|
||||||
|
|
|
@ -819,7 +819,16 @@ class ReplicationFederationHandlerRegistry(FederationHandlerRegistry):
|
||||||
edu_type, origin, content
|
edu_type, origin, content
|
||||||
)
|
)
|
||||||
|
|
||||||
return await self._send_edu(edu_type=edu_type, origin=origin, content=content)
|
if edu_type == "m.typing":
|
||||||
|
instance_name = "synapse.app.client_reader"
|
||||||
|
else:
|
||||||
|
instance_name = "master"
|
||||||
|
return await self._send_edu(
|
||||||
|
instance_name=instance_name,
|
||||||
|
edu_type=edu_type,
|
||||||
|
origin=origin,
|
||||||
|
content=content,
|
||||||
|
)
|
||||||
|
|
||||||
async def on_query(self, query_type, args):
|
async def on_query(self, query_type, args):
|
||||||
"""Overrides FederationHandlerRegistry
|
"""Overrides FederationHandlerRegistry
|
||||||
|
|
|
@ -56,7 +56,7 @@ class TypingHandler(object):
|
||||||
self.clock = hs.get_clock()
|
self.clock = hs.get_clock()
|
||||||
self.wheel_timer = WheelTimer(bucket_size=5000)
|
self.wheel_timer = WheelTimer(bucket_size=5000)
|
||||||
|
|
||||||
# self.federation = hs.get_federation_sender()
|
self.federation = hs.get_federation_sender()
|
||||||
|
|
||||||
hs.get_federation_registry().register_edu_handler("m.typing", self._recv_edu)
|
hs.get_federation_registry().register_edu_handler("m.typing", self._recv_edu)
|
||||||
|
|
||||||
|
@ -203,16 +203,16 @@ class TypingHandler(object):
|
||||||
for domain in {get_domain_from_id(u) for u in users}:
|
for domain in {get_domain_from_id(u) for u in users}:
|
||||||
if domain != self.server_name:
|
if domain != self.server_name:
|
||||||
logger.debug("sending typing update to %s", domain)
|
logger.debug("sending typing update to %s", domain)
|
||||||
# self.federation.build_and_send_edu(
|
self.federation.build_and_send_edu(
|
||||||
# destination=domain,
|
destination=domain,
|
||||||
# edu_type="m.typing",
|
edu_type="m.typing",
|
||||||
# content={
|
content={
|
||||||
# "room_id": member.room_id,
|
"room_id": member.room_id,
|
||||||
# "user_id": member.user_id,
|
"user_id": member.user_id,
|
||||||
# "typing": typing,
|
"typing": typing,
|
||||||
# },
|
},
|
||||||
# key=member,
|
key=member,
|
||||||
# )
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.exception("Error pushing typing notif to remotes")
|
logger.exception("Error pushing typing notif to remotes")
|
||||||
|
|
||||||
|
@ -309,7 +309,9 @@ class TypingSlaveHandler(object):
|
||||||
# We must update this typing token from the response of the previous
|
# We must update this typing token from the response of the previous
|
||||||
# sync. In particular, the stream id may "reset" back to zero/a low
|
# sync. In particular, the stream id may "reset" back to zero/a low
|
||||||
# value which we *must* use for the next replication request.
|
# value which we *must* use for the next replication request.
|
||||||
return {"typing": {"master": self._latest_room_serial}}
|
return {
|
||||||
|
"typing": {"synapse.app.client_reader": self._latest_room_serial}
|
||||||
|
} # FIXME
|
||||||
|
|
||||||
def process_replication_rows(self, stream_name, token, rows):
|
def process_replication_rows(self, stream_name, token, rows):
|
||||||
if stream_name != TypingStream.NAME:
|
if stream_name != TypingStream.NAME:
|
||||||
|
|
|
@ -33,10 +33,12 @@ class ReplicationRestResource(JsonResource):
|
||||||
self.register_servlets(hs)
|
self.register_servlets(hs)
|
||||||
|
|
||||||
def register_servlets(self, hs):
|
def register_servlets(self, hs):
|
||||||
|
if hs.config.worker_app is None:
|
||||||
send_event.register_servlets(hs, self)
|
send_event.register_servlets(hs, self)
|
||||||
membership.register_servlets(hs, self)
|
membership.register_servlets(hs, self)
|
||||||
federation.register_servlets(hs, self)
|
|
||||||
login.register_servlets(hs, self)
|
login.register_servlets(hs, self)
|
||||||
register.register_servlets(hs, self)
|
register.register_servlets(hs, self)
|
||||||
devices.register_servlets(hs, self)
|
devices.register_servlets(hs, self)
|
||||||
|
|
||||||
streams.register_servlets(hs, self)
|
streams.register_servlets(hs, self)
|
||||||
|
federation.register_servlets(hs, self)
|
||||||
|
|
|
@ -128,15 +128,23 @@ class ReplicationEndpoint(object):
|
||||||
Returns a callable that accepts the same parameters as `_serialize_payload`.
|
Returns a callable that accepts the same parameters as `_serialize_payload`.
|
||||||
"""
|
"""
|
||||||
clock = hs.get_clock()
|
clock = hs.get_clock()
|
||||||
host = hs.config.worker_replication_host
|
master_host = hs.config.worker_replication_host
|
||||||
port = hs.config.worker_replication_http_port
|
master_port = hs.config.worker_replication_http_port
|
||||||
|
|
||||||
|
instance_http_map = hs.config.instance_http_map
|
||||||
|
|
||||||
client = hs.get_simple_http_client()
|
client = hs.get_simple_http_client()
|
||||||
|
|
||||||
@trace(opname="outgoing_replication_request")
|
@trace(opname="outgoing_replication_request")
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def send_request(instance_name="master", **kwargs):
|
def send_request(instance_name="master", **kwargs):
|
||||||
if instance_name != "master":
|
if instance_name == "master":
|
||||||
|
host = master_host
|
||||||
|
port = master_port
|
||||||
|
elif instance_name in instance_http_map:
|
||||||
|
host = instance_http_map[instance_name]["host"]
|
||||||
|
port = instance_http_map[instance_name]["port"]
|
||||||
|
else:
|
||||||
raise Exception("Unknown instance")
|
raise Exception("Unknown instance")
|
||||||
|
|
||||||
data = yield cls._serialize_payload(**kwargs)
|
data = yield cls._serialize_payload(**kwargs)
|
||||||
|
|
|
@ -277,8 +277,10 @@ class ReplicationStoreRoomOnInviteRestServlet(ReplicationEndpoint):
|
||||||
|
|
||||||
|
|
||||||
def register_servlets(hs, http_server):
|
def register_servlets(hs, http_server):
|
||||||
|
if hs.config.worker_app is None:
|
||||||
ReplicationFederationSendEventsRestServlet(hs).register(http_server)
|
ReplicationFederationSendEventsRestServlet(hs).register(http_server)
|
||||||
ReplicationFederationSendEduRestServlet(hs).register(http_server)
|
|
||||||
ReplicationGetQueryRestServlet(hs).register(http_server)
|
ReplicationGetQueryRestServlet(hs).register(http_server)
|
||||||
ReplicationCleanRoomRestServlet(hs).register(http_server)
|
ReplicationCleanRoomRestServlet(hs).register(http_server)
|
||||||
ReplicationStoreRoomOnInviteRestServlet(hs).register(http_server)
|
ReplicationStoreRoomOnInviteRestServlet(hs).register(http_server)
|
||||||
|
|
||||||
|
ReplicationFederationSendEduRestServlet(hs).register(http_server)
|
||||||
|
|
|
@ -51,6 +51,8 @@ class ReplicationGetStreamUpdates(ReplicationEndpoint):
|
||||||
# them ourselves we end up in an import loop).
|
# them ourselves we end up in an import loop).
|
||||||
self.streams = hs.get_replication_streamer().get_streams()
|
self.streams = hs.get_replication_streamer().get_streams()
|
||||||
|
|
||||||
|
self.instance_name = hs.config.worker_name or "master"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _serialize_payload(stream_name, from_token, upto_token, limit):
|
def _serialize_payload(stream_name, from_token, upto_token, limit):
|
||||||
return {"from_token": from_token, "upto_token": upto_token, "limit": limit}
|
return {"from_token": from_token, "upto_token": upto_token, "limit": limit}
|
||||||
|
|
|
@ -63,6 +63,8 @@ class ReplicationClientHandler:
|
||||||
self.presence_handler = hs.get_presence_handler()
|
self.presence_handler = hs.get_presence_handler()
|
||||||
self.instance_id = hs.get_instance_id()
|
self.instance_id = hs.get_instance_id()
|
||||||
|
|
||||||
|
self.instance_name = hs.config.worker.worker_name or "master"
|
||||||
|
|
||||||
self.connections = [] # type: List[Any]
|
self.connections = [] # type: List[Any]
|
||||||
|
|
||||||
self.streams = {
|
self.streams = {
|
||||||
|
@ -134,7 +136,9 @@ class ReplicationClientHandler:
|
||||||
|
|
||||||
for stream_name, stream in self.streams.items():
|
for stream_name, stream in self.streams.items():
|
||||||
current_token = stream.current_token()
|
current_token = stream.current_token()
|
||||||
self.send_command(PositionCommand(stream_name, "master", current_token))
|
self.send_command(
|
||||||
|
PositionCommand(stream_name, self.instance_name, current_token)
|
||||||
|
)
|
||||||
|
|
||||||
async def on_USER_SYNC(self, cmd: UserSyncCommand):
|
async def on_USER_SYNC(self, cmd: UserSyncCommand):
|
||||||
user_sync_counter.inc()
|
user_sync_counter.inc()
|
||||||
|
@ -232,17 +236,17 @@ class ReplicationClientHandler:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Find where we previously streamed up to.
|
# Find where we previously streamed up to.
|
||||||
current_token = (
|
current_tokens = self.replication_data_handler.get_streams_to_replicate().get(
|
||||||
self.replication_data_handler.get_streams_to_replicate()
|
cmd.stream_name
|
||||||
.get(cmd.stream_name, {})
|
|
||||||
.get(cmd.instance_name)
|
|
||||||
)
|
)
|
||||||
if current_token is None:
|
if current_tokens is None:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Got POSITION for stream we're not subscribed to: %s", cmd.stream_name
|
"Got POSITION for stream we're not subscribed to: %s", cmd.stream_name
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
current_token = current_tokens.get(cmd.instance_name, 0)
|
||||||
|
|
||||||
# Fetch all updates between then and now.
|
# Fetch all updates between then and now.
|
||||||
limited = cmd.token != current_token
|
limited = cmd.token != current_token
|
||||||
while limited:
|
while limited:
|
||||||
|
@ -335,7 +339,7 @@ class ReplicationClientHandler:
|
||||||
|
|
||||||
We need to check if the client is interested in the stream or not
|
We need to check if the client is interested in the stream or not
|
||||||
"""
|
"""
|
||||||
self.send_command(RdataCommand(stream_name, "master", token, data))
|
self.send_command(RdataCommand(stream_name, self.instance_name, token, data))
|
||||||
|
|
||||||
|
|
||||||
class ReplicationDataHandler:
|
class ReplicationDataHandler:
|
||||||
|
|
|
@ -74,9 +74,7 @@ class ReplicationStreamer(object):
|
||||||
self.streams = [] # type: List[Stream]
|
self.streams = [] # type: List[Stream]
|
||||||
if hs.config.worker_app is None:
|
if hs.config.worker_app is None:
|
||||||
for stream in STREAMS_MAP.values():
|
for stream in STREAMS_MAP.values():
|
||||||
if stream == FederationStream and hs.config.send_federation:
|
if stream == FederationStream:
|
||||||
# We only support federation stream if federation sending
|
|
||||||
# hase been disabled on the master.
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if stream == TypingStream:
|
if stream == TypingStream:
|
||||||
|
@ -87,6 +85,9 @@ class ReplicationStreamer(object):
|
||||||
if hs.config.server.handle_typing:
|
if hs.config.server.handle_typing:
|
||||||
self.streams.append(TypingStream(hs))
|
self.streams.append(TypingStream(hs))
|
||||||
|
|
||||||
|
# We always add federation stream
|
||||||
|
self.streams.append(FederationStream(hs))
|
||||||
|
|
||||||
self.streams_by_name = {stream.NAME: stream for stream in self.streams}
|
self.streams_by_name = {stream.NAME: stream for stream in self.streams}
|
||||||
|
|
||||||
self.notifier.add_replication_callback(self.on_notifier_poke)
|
self.notifier.add_replication_callback(self.on_notifier_poke)
|
||||||
|
|
|
@ -256,7 +256,7 @@ class TypingStream(Stream):
|
||||||
|
|
||||||
self.current_token = typing_handler.get_current_token # type: ignore
|
self.current_token = typing_handler.get_current_token # type: ignore
|
||||||
|
|
||||||
if hs.config.worker_app is None:
|
if hs.config.handle_typing:
|
||||||
self.update_function = db_query_to_update_function(typing_handler.get_all_typing_updates) # type: ignore
|
self.update_function = db_query_to_update_function(typing_handler.get_all_typing_updates) # type: ignore
|
||||||
else:
|
else:
|
||||||
# Query master process
|
# Query master process
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
from twisted.internet import defer
|
|
||||||
|
|
||||||
from synapse.replication.tcp.streams._base import Stream, db_query_to_update_function
|
from synapse.replication.tcp.streams._base import Stream, db_query_to_update_function
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,12 +39,8 @@ class FederationStream(Stream):
|
||||||
# Not all synapse instances will have a federation sender instance,
|
# Not all synapse instances will have a federation sender instance,
|
||||||
# whether that's a `FederationSender` or a `FederationRemoteSendQueue`,
|
# whether that's a `FederationSender` or a `FederationRemoteSendQueue`,
|
||||||
# so we stub the stream out when that is the case.
|
# so we stub the stream out when that is the case.
|
||||||
if hs.config.worker_app is None or hs.should_send_federation():
|
|
||||||
federation_sender = hs.get_federation_sender()
|
federation_sender = hs.get_federation_sender()
|
||||||
self.current_token = federation_sender.get_current_token # type: ignore
|
self.current_token = federation_sender.get_current_token # type: ignore
|
||||||
self.update_function = db_query_to_update_function(federation_sender.get_replication_rows) # type: ignore
|
self.update_function = db_query_to_update_function(federation_sender.get_replication_rows) # type: ignore
|
||||||
else:
|
|
||||||
self.current_token = lambda: 0 # type: ignore
|
|
||||||
self.update_function = lambda from_token, upto_token, limit: defer.succeed(([], upto_token, bool)) # type: ignore
|
|
||||||
|
|
||||||
super(FederationStream, self).__init__(hs)
|
super(FederationStream, self).__init__(hs)
|
||||||
|
|
|
@ -457,10 +457,8 @@ class HomeServer(object):
|
||||||
def build_federation_sender(self):
|
def build_federation_sender(self):
|
||||||
if self.should_send_federation():
|
if self.should_send_federation():
|
||||||
return FederationSender(self)
|
return FederationSender(self)
|
||||||
elif not self.config.worker_app:
|
|
||||||
return FederationRemoteSendQueue(self)
|
|
||||||
else:
|
else:
|
||||||
raise Exception("Workers cannot send federation traffic")
|
return FederationRemoteSendQueue(self)
|
||||||
|
|
||||||
def build_receipts_handler(self):
|
def build_receipts_handler(self):
|
||||||
return ReceiptsHandler(self)
|
return ReceiptsHandler(self)
|
||||||
|
|
Loading…
Reference in a new issue