Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit 1df0221

Browse files
authored
Use a custom scheme & the worker name for replication requests. (#15578)
All the information needed is already in the `instance_map`, so use that instead of passing the hostname / IP & port manually for each replication request. This consolidates logic for future improvements of using e.g. UNIX sockets for workers.
1 parent 5b18a21 commit 1df0221

File tree

4 files changed

+35
-19
lines changed

4 files changed

+35
-19
lines changed

changelog.d/15578.misc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Allow connecting to HTTP Replication Endpoints by using `worker_name` when constructing the request.

synapse/http/client.py

+1
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,7 @@ def __init__(
835835

836836
self.agent: IAgent = ReplicationAgent(
837837
hs.get_reactor(),
838+
hs.config.worker.instance_map,
838839
contextFactory=hs.get_http_client_context_factory(),
839840
pool=pool,
840841
)

synapse/http/replicationagent.py

+27-7
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# limitations under the License.
1414

1515
import logging
16-
from typing import Optional
16+
from typing import Dict, Optional
1717

1818
from zope.interface import implementer
1919

@@ -32,6 +32,7 @@
3232
IResponse,
3333
)
3434

35+
from synapse.config.workers import InstanceLocationConfig
3536
from synapse.types import ISynapseReactor
3637

3738
logger = logging.getLogger(__name__)
@@ -44,9 +45,11 @@ class ReplicationEndpointFactory:
4445
def __init__(
4546
self,
4647
reactor: ISynapseReactor,
48+
instance_map: Dict[str, InstanceLocationConfig],
4749
context_factory: IPolicyForHTTPS,
4850
) -> None:
4951
self.reactor = reactor
52+
self.instance_map = instance_map
5053
self.context_factory = context_factory
5154

5255
def endpointForURI(self, uri: URI) -> IStreamClientEndpoint:
@@ -58,15 +61,29 @@ def endpointForURI(self, uri: URI) -> IStreamClientEndpoint:
5861
5962
Returns: The correct client endpoint object
6063
"""
61-
if uri.scheme in (b"http", b"https"):
62-
endpoint = HostnameEndpoint(self.reactor, uri.host, uri.port)
63-
if uri.scheme == b"https":
64+
# The given URI has a special scheme and includes the worker name. The
65+
# actual connection details are pulled from the instance map.
66+
worker_name = uri.netloc.decode("utf-8")
67+
scheme = self.instance_map[worker_name].scheme()
68+
69+
if scheme in ("http", "https"):
70+
endpoint = HostnameEndpoint(
71+
self.reactor,
72+
self.instance_map[worker_name].host,
73+
self.instance_map[worker_name].port,
74+
)
75+
if scheme == "https":
6476
endpoint = wrapClientTLS(
65-
self.context_factory.creatorForNetloc(uri.host, uri.port), endpoint
77+
# The 'port' argument below isn't actually used by the function
78+
self.context_factory.creatorForNetloc(
79+
self.instance_map[worker_name].host,
80+
self.instance_map[worker_name].port,
81+
),
82+
endpoint,
6683
)
6784
return endpoint
6885
else:
69-
raise SchemeNotSupported(f"Unsupported scheme: {uri.scheme!r}")
86+
raise SchemeNotSupported(f"Unsupported scheme: {scheme}")
7087

7188

7289
@implementer(IAgent)
@@ -80,6 +97,7 @@ class ReplicationAgent(_AgentBase):
8097
def __init__(
8198
self,
8299
reactor: ISynapseReactor,
100+
instance_map: Dict[str, InstanceLocationConfig],
83101
contextFactory: IPolicyForHTTPS,
84102
connectTimeout: Optional[float] = None,
85103
bindAddress: Optional[bytes] = None,
@@ -102,7 +120,9 @@ def __init__(
102120
created.
103121
"""
104122
_AgentBase.__init__(self, reactor, pool)
105-
endpoint_factory = ReplicationEndpointFactory(reactor, contextFactory)
123+
endpoint_factory = ReplicationEndpointFactory(
124+
reactor, instance_map, contextFactory
125+
)
106126
self._endpointFactory = endpoint_factory
107127

108128
def request(

synapse/replication/http/_base.py

+6-12
Original file line numberDiff line numberDiff line change
@@ -219,11 +219,7 @@ async def send_request(
219219
with outgoing_gauge.track_inprogress():
220220
if instance_name == local_instance_name:
221221
raise Exception("Trying to send HTTP request to self")
222-
if instance_name in instance_map:
223-
host = instance_map[instance_name].host
224-
port = instance_map[instance_name].port
225-
tls = instance_map[instance_name].tls
226-
else:
222+
if instance_name not in instance_map:
227223
raise Exception(
228224
"Instance %r not in 'instance_map' config" % (instance_name,)
229225
)
@@ -271,13 +267,11 @@ async def send_request(
271267
"Unknown METHOD on %s replication endpoint" % (cls.NAME,)
272268
)
273269

274-
# Here the protocol is hard coded to be http by default or https in case the replication
275-
# port is set to have tls true.
276-
scheme = "https" if tls else "http"
277-
uri = "%s://%s:%s/_synapse/replication/%s/%s" % (
278-
scheme,
279-
host,
280-
port,
270+
# Hard code a special scheme to show this only used for replication. The
271+
# instance_name will be passed into the ReplicationEndpointFactory to
272+
# determine connection details from the instance_map.
273+
uri = "synapse-replication://%s/_synapse/replication/%s/%s" % (
274+
instance_name,
281275
cls.NAME,
282276
"/".join(url_args),
283277
)

0 commit comments

Comments
 (0)