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

Commit 405f8c4

Browse files
committed
Merge branch 'release-v0.9.2'
2 parents 6d1dea3 + 1a87f5f commit 405f8c4

33 files changed

+547
-281
lines changed

CHANGES.rst

+23
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,26 @@
1+
Changes in synapse v0.9.2 (2015-06-12)
2+
======================================
3+
4+
General:
5+
6+
* Use ultrajson for json (de)serialisation when a canonical encoding is not
7+
required. Ultrajson is significantly faster than simplejson in certain
8+
circumstances.
9+
* Use connection pools for outgoing HTTP connections.
10+
* Process thumbnails on separate threads.
11+
12+
Configuration:
13+
14+
* Add option, ``gzip_responses``, to disable HTTP response compression.
15+
16+
Federation:
17+
18+
* Improve resilience of backfill by ensuring we fetch any missing auth events.
19+
* Improve performance of backfill and joining remote rooms by removing
20+
unnecessary computations. This included handling events we'd previously
21+
handled as well as attempting to compute the current state for outliers.
22+
23+
124
Changes in synapse v0.9.1 (2015-05-26)
225
======================================
326

contrib/systemd/log_config.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,5 @@ handlers:
2121
root:
2222
level: INFO
2323
handlers: [journal]
24+
25+
disable_existing_loggers: False

synapse/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@
1616
""" This is a reference implementation of a Matrix home server.
1717
"""
1818

19-
__version__ = "0.9.1"
19+
__version__ = "0.9.2"

synapse/app/homeserver.py

+12-2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@
5454
from synapse.rest.client.v2_alpha import ClientV2AlphaRestResource
5555
from synapse.metrics.resource import MetricsResource, METRICS_PREFIX
5656

57+
from synapse import events
58+
5759
from daemonize import Daemonize
5860
import twisted.manhole.telnet
5961

@@ -85,10 +87,16 @@ def build_http_client(self):
8587
return MatrixFederationHttpClient(self)
8688

8789
def build_resource_for_client(self):
88-
return gz_wrap(ClientV1RestResource(self))
90+
res = ClientV1RestResource(self)
91+
if self.config.gzip_responses:
92+
res = gz_wrap(res)
93+
return res
8994

9095
def build_resource_for_client_v2_alpha(self):
91-
return gz_wrap(ClientV2AlphaRestResource(self))
96+
res = ClientV2AlphaRestResource(self)
97+
if self.config.gzip_responses:
98+
res = gz_wrap(res)
99+
return res
92100

93101
def build_resource_for_federation(self):
94102
return JsonResource(self)
@@ -415,6 +423,8 @@ def setup(config_options):
415423
logger.info("Server hostname: %s", config.server_name)
416424
logger.info("Server version: %s", version_string)
417425

426+
events.USE_FROZEN_DICTS = config.use_frozen_dicts
427+
418428
if re.search(":[0-9]+$", config.server_name):
419429
domain_with_port = config.server_name
420430
else:

synapse/config/captcha.py

+4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ def read_config(self, config):
2626
config["captcha_ip_origin_is_x_forwarded"]
2727
)
2828
self.captcha_bypass_secret = config.get("captcha_bypass_secret")
29+
self.recaptcha_siteverify_api = config["recaptcha_siteverify_api"]
2930

3031
def default_config(self, config_dir_path, server_name):
3132
return """\
@@ -48,4 +49,7 @@ def default_config(self, config_dir_path, server_name):
4849
4950
# A secret key used to bypass the captcha test entirely.
5051
#captcha_bypass_secret: "YOUR_SECRET_HERE"
52+
53+
# The API endpoint to use for verifying m.login.recaptcha responses.
54+
recaptcha_siteverify_api: "https://www.google.com/recaptcha/api/siteverify"
5155
"""

synapse/config/registration.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def default_config(self, config_dir, server_name):
3939
## Registration ##
4040
4141
# Enable registration for new users.
42-
enable_registration: True
42+
enable_registration: False
4343
4444
# If set, allows registration by anyone who also has the shared
4545
# secret, even if registration is otherwise disabled.

synapse/config/server.py

+7
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ def read_config(self, config):
2828
self.web_client = config["web_client"]
2929
self.soft_file_limit = config["soft_file_limit"]
3030
self.daemonize = config.get("daemonize")
31+
self.use_frozen_dicts = config.get("use_frozen_dicts", True)
32+
self.gzip_responses = config["gzip_responses"]
3133

3234
# Attempt to guess the content_addr for the v0 content repostitory
3335
content_addr = config.get("content_addr")
@@ -85,6 +87,11 @@ def default_config(self, config_dir_path, server_name):
8587
# Turn on the twisted telnet manhole service on localhost on the given
8688
# port.
8789
#manhole: 9000
90+
91+
# Should synapse compress HTTP responses to clients that support it?
92+
# This should be disabled if running synapse behind a load balancer
93+
# that can do automatic compression.
94+
gzip_responses: True
8895
""" % locals()
8996

9097
def read_arguments(self, args):

synapse/events/__init__.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@
1616
from synapse.util.frozenutils import freeze
1717

1818

19+
# Whether we should use frozen_dict in FrozenEvent. Using frozen_dicts prevents
20+
# bugs where we accidentally share e.g. signature dicts. However, converting
21+
# a dict to frozen_dicts is expensive.
22+
USE_FROZEN_DICTS = True
23+
24+
1925
class _EventInternalMetadata(object):
2026
def __init__(self, internal_metadata_dict):
2127
self.__dict__ = dict(internal_metadata_dict)
@@ -122,7 +128,10 @@ def __init__(self, event_dict, internal_metadata_dict={}, rejected_reason=None):
122128

123129
unsigned = dict(event_dict.pop("unsigned", {}))
124130

125-
frozen_dict = freeze(event_dict)
131+
if USE_FROZEN_DICTS:
132+
frozen_dict = freeze(event_dict)
133+
else:
134+
frozen_dict = event_dict
126135

127136
super(FrozenEvent, self).__init__(
128137
frozen_dict,

synapse/federation/federation_base.py

+4-7
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818

1919
from synapse.events.utils import prune_event
2020

21-
from syutil.jsonutil import encode_canonical_json
22-
2321
from synapse.crypto.event_signing import check_event_content_hash
2422

2523
from synapse.api.errors import SynapseError
@@ -120,16 +118,15 @@ def _check_sigs_and_hash(self, pdu):
120118
)
121119
except SynapseError:
122120
logger.warn(
123-
"Signature check failed for %s redacted to %s",
124-
encode_canonical_json(pdu.get_pdu_json()),
125-
encode_canonical_json(redacted_pdu_json),
121+
"Signature check failed for %s",
122+
pdu.event_id,
126123
)
127124
raise
128125

129126
if not check_event_content_hash(pdu):
130127
logger.warn(
131-
"Event content has been tampered, redacting %s, %s",
132-
pdu.event_id, encode_canonical_json(pdu.get_dict())
128+
"Event content has been tampered, redacting.",
129+
pdu.event_id,
133130
)
134131
defer.returnValue(redacted_event)
135132

synapse/federation/transport/server.py

+2
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ def strip_quotes(value):
9393

9494
yield self.keyring.verify_json_for_server(origin, json_request)
9595

96+
logger.info("Request from %s", origin)
97+
9698
defer.returnValue((origin, content))
9799

98100
@log_function

synapse/handlers/_base.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,9 @@ def _create_new_client_event(self, builder):
7878
context = yield state_handler.compute_event_context(builder)
7979

8080
if builder.is_state():
81-
builder.prev_state = context.prev_state_events
81+
builder.prev_state = yield self.store.add_event_hashes(
82+
context.prev_state_events
83+
)
8284

8385
yield self.auth.add_auth_events(builder, context)
8486

synapse/handlers/auth.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,8 @@ def _check_recaptcha(self, authdict, clientip):
187187
# each request
188188
try:
189189
client = SimpleHttpClient(self.hs)
190-
data = yield client.post_urlencoded_get_json(
191-
"https://www.google.com/recaptcha/api/siteverify",
190+
resp_body = yield client.post_urlencoded_get_json(
191+
self.hs.config.recaptcha_siteverify_api,
192192
args={
193193
'secret': self.hs.config.recaptcha_private_key,
194194
'response': user_response,
@@ -198,7 +198,8 @@ def _check_recaptcha(self, authdict, clientip):
198198
except PartialDownloadError as pde:
199199
# Twisted is silly
200200
data = pde.response
201-
resp_body = simplejson.loads(data)
201+
resp_body = simplejson.loads(data)
202+
202203
if 'success' in resp_body and resp_body['success']:
203204
defer.returnValue(True)
204205
raise LoginError(401, "", errcode=Codes.UNAUTHORIZED)

synapse/handlers/federation.py

+50-3
Original file line numberDiff line numberDiff line change
@@ -247,9 +247,15 @@ def backfill(self, dest, room_id, limit, extremities=[]):
247247
if set(e_id for e_id, _ in ev.prev_events) - event_ids
248248
]
249249

250+
logger.info(
251+
"backfill: Got %d events with %d edges",
252+
len(events), len(edges),
253+
)
254+
250255
# For each edge get the current state.
251256

252257
auth_events = {}
258+
state_events = {}
253259
events_to_state = {}
254260
for e_id in edges:
255261
state, auth = yield self.replication_layer.get_state_for_room(
@@ -258,12 +264,46 @@ def backfill(self, dest, room_id, limit, extremities=[]):
258264
event_id=e_id
259265
)
260266
auth_events.update({a.event_id: a for a in auth})
267+
auth_events.update({s.event_id: s for s in state})
268+
state_events.update({s.event_id: s for s in state})
261269
events_to_state[e_id] = state
262270

271+
seen_events = yield self.store.have_events(
272+
set(auth_events.keys()) | set(state_events.keys())
273+
)
274+
275+
all_events = events + state_events.values() + auth_events.values()
276+
required_auth = set(
277+
a_id for event in all_events for a_id, _ in event.auth_events
278+
)
279+
280+
missing_auth = required_auth - set(auth_events)
281+
results = yield defer.gatherResults(
282+
[
283+
self.replication_layer.get_pdu(
284+
[dest],
285+
event_id,
286+
outlier=True,
287+
timeout=10000,
288+
)
289+
for event_id in missing_auth
290+
],
291+
consumeErrors=True
292+
).addErrback(unwrapFirstError)
293+
auth_events.update({a.event_id: a for a in results})
294+
263295
yield defer.gatherResults(
264296
[
265-
self._handle_new_event(dest, a)
297+
self._handle_new_event(
298+
dest, a,
299+
auth_events={
300+
(auth_events[a_id].type, auth_events[a_id].state_key):
301+
auth_events[a_id]
302+
for a_id, _ in a.auth_events
303+
},
304+
)
266305
for a in auth_events.values()
306+
if a.event_id not in seen_events
267307
],
268308
consumeErrors=True,
269309
).addErrback(unwrapFirstError)
@@ -274,6 +314,11 @@ def backfill(self, dest, room_id, limit, extremities=[]):
274314
dest, event_map[e_id],
275315
state=events_to_state[e_id],
276316
backfilled=True,
317+
auth_events={
318+
(auth_events[a_id].type, auth_events[a_id].state_key):
319+
auth_events[a_id]
320+
for a_id, _ in event_map[e_id].auth_events
321+
},
277322
)
278323
for e_id in events_to_state
279324
],
@@ -900,8 +945,10 @@ def _handle_new_event(self, origin, event, state=None, backfilled=False,
900945
event.event_id, event.signatures,
901946
)
902947

948+
outlier = event.internal_metadata.is_outlier()
949+
903950
context = yield self.state_handler.compute_event_context(
904-
event, old_state=state
951+
event, old_state=state, outlier=outlier,
905952
)
906953

907954
if not auth_events:
@@ -912,7 +959,7 @@ def _handle_new_event(self, origin, event, state=None, backfilled=False,
912959
event.event_id, auth_events,
913960
)
914961

915-
is_new_state = not event.internal_metadata.is_outlier()
962+
is_new_state = not outlier
916963

917964
# This is a hack to fix some old rooms where the initial join event
918965
# didn't reference the create event in its auth events.

synapse/http/client.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020

2121
from twisted.internet import defer, reactor
2222
from twisted.web.client import (
23-
Agent, readBody, FileBodyProducer, PartialDownloadError
23+
Agent, readBody, FileBodyProducer, PartialDownloadError,
24+
HTTPConnectionPool,
2425
)
2526
from twisted.web.http_headers import Headers
2627

@@ -55,7 +56,9 @@ def __init__(self, hs):
5556
# The default context factory in Twisted 14.0.0 (which we require) is
5657
# BrowserLikePolicyForHTTPS which will do regular cert validation
5758
# 'like a browser'
58-
self.agent = Agent(reactor)
59+
pool = HTTPConnectionPool(reactor)
60+
pool.maxPersistentPerHost = 10
61+
self.agent = Agent(reactor, pool=pool)
5962
self.version_string = hs.version_string
6063

6164
def request(self, method, *args, **kwargs):

synapse/http/matrixfederationclient.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
from twisted.internet import defer, reactor, protocol
1818
from twisted.internet.error import DNSLookupError
19-
from twisted.web.client import readBody, _AgentBase, _URI
19+
from twisted.web.client import readBody, _AgentBase, _URI, HTTPConnectionPool
2020
from twisted.web.http_headers import Headers
2121
from twisted.web._newclient import ResponseDone
2222

@@ -103,7 +103,9 @@ def __init__(self, hs):
103103
self.hs = hs
104104
self.signing_key = hs.config.signing_key[0]
105105
self.server_name = hs.hostname
106-
self.agent = MatrixFederationHttpAgent(reactor)
106+
pool = HTTPConnectionPool(reactor)
107+
pool.maxPersistentPerHost = 10
108+
self.agent = MatrixFederationHttpAgent(reactor, pool=pool)
107109
self.clock = hs.get_clock()
108110
self.version_string = hs.version_string
109111

0 commit comments

Comments
 (0)