diff --git a/CHANGES.rst b/CHANGES.rst
index 68e9d8c671..9106134b46 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -30,6 +30,7 @@ Changes in synapse v0.18.6 (2017-01-06)
Bug fixes:
* Fix bug when checking if a guest user is allowed to join a room (PR #1772)
+ Thanks to Patrik Oldsberg for diagnosing and the fix!
Changes in synapse v0.18.6-rc3 (2017-01-05)
diff --git a/README.rst b/README.rst
index ba21c52ae7..77e0b470a3 100644
--- a/README.rst
+++ b/README.rst
@@ -138,6 +138,7 @@ Installing prerequisites on openSUSE::
python-devel libffi-devel libopenssl-devel libjpeg62-devel
Installing prerequisites on OpenBSD::
+
doas pkg_add python libffi py-pip py-setuptools sqlite3 py-virtualenv \
libxslt
diff --git a/synapse/app/appservice.py b/synapse/app/appservice.py
index c1379fdd7d..1900930053 100644
--- a/synapse/app/appservice.py
+++ b/synapse/app/appservice.py
@@ -76,8 +76,7 @@ class AppserviceServer(HomeServer):
def _listen_http(self, listener_config):
port = listener_config["port"]
- bind_address = listener_config.get("bind_address", None)
- bind_addresses = listener_config.get("bind_addresses", [])
+ bind_addresses = listener_config["bind_addresses"]
site_tag = listener_config.get("tag", port)
resources = {}
for res in listener_config["resources"]:
@@ -87,9 +86,6 @@ class AppserviceServer(HomeServer):
root_resource = create_resource_tree(resources, Resource())
- if bind_address is not None:
- bind_addresses.append(bind_address)
-
for address in bind_addresses:
reactor.listenTCP(
port,
@@ -109,11 +105,7 @@ class AppserviceServer(HomeServer):
if listener["type"] == "http":
self._listen_http(listener)
elif listener["type"] == "manhole":
- bind_address = listener.get("bind_address", None)
- bind_addresses = listener.get("bind_addresses", [])
-
- if bind_address is not None:
- bind_addresses.append(bind_address)
+ bind_addresses = listener["bind_addresses"]
for address in bind_addresses:
reactor.listenTCP(
diff --git a/synapse/app/client_reader.py b/synapse/app/client_reader.py
index b5e1d659e6..4d081eccd1 100644
--- a/synapse/app/client_reader.py
+++ b/synapse/app/client_reader.py
@@ -90,8 +90,7 @@ class ClientReaderServer(HomeServer):
def _listen_http(self, listener_config):
port = listener_config["port"]
- bind_address = listener_config.get("bind_address", None)
- bind_addresses = listener_config.get("bind_addresses", [])
+ bind_addresses = listener_config["bind_addresses"]
site_tag = listener_config.get("tag", port)
resources = {}
for res in listener_config["resources"]:
@@ -110,9 +109,6 @@ class ClientReaderServer(HomeServer):
root_resource = create_resource_tree(resources, Resource())
- if bind_address is not None:
- bind_addresses.append(bind_address)
-
for address in bind_addresses:
reactor.listenTCP(
port,
@@ -132,11 +128,7 @@ class ClientReaderServer(HomeServer):
if listener["type"] == "http":
self._listen_http(listener)
elif listener["type"] == "manhole":
- bind_address = listener.get("bind_address", None)
- bind_addresses = listener.get("bind_addresses", [])
-
- if bind_address is not None:
- bind_addresses.append(bind_address)
+ bind_addresses = listener["bind_addresses"]
for address in bind_addresses:
reactor.listenTCP(
diff --git a/synapse/app/federation_reader.py b/synapse/app/federation_reader.py
index c6810b83db..90a4816753 100644
--- a/synapse/app/federation_reader.py
+++ b/synapse/app/federation_reader.py
@@ -86,8 +86,7 @@ class FederationReaderServer(HomeServer):
def _listen_http(self, listener_config):
port = listener_config["port"]
- bind_address = listener_config.get("bind_address", None)
- bind_addresses = listener_config.get("bind_addresses", [])
+ bind_addresses = listener_config["bind_addresses"]
site_tag = listener_config.get("tag", port)
resources = {}
for res in listener_config["resources"]:
@@ -101,9 +100,6 @@ class FederationReaderServer(HomeServer):
root_resource = create_resource_tree(resources, Resource())
- if bind_address is not None:
- bind_addresses.append(bind_address)
-
for address in bind_addresses:
reactor.listenTCP(
port,
@@ -123,11 +119,7 @@ class FederationReaderServer(HomeServer):
if listener["type"] == "http":
self._listen_http(listener)
elif listener["type"] == "manhole":
- bind_address = listener.get("bind_address", None)
- bind_addresses = listener.get("bind_addresses", [])
-
- if bind_address is not None:
- bind_addresses.append(bind_address)
+ bind_addresses = listener["bind_addresses"]
for address in bind_addresses:
reactor.listenTCP(
diff --git a/synapse/app/federation_sender.py b/synapse/app/federation_sender.py
index 23aae8a09c..ec06620efb 100644
--- a/synapse/app/federation_sender.py
+++ b/synapse/app/federation_sender.py
@@ -82,8 +82,7 @@ class FederationSenderServer(HomeServer):
def _listen_http(self, listener_config):
port = listener_config["port"]
- bind_address = listener_config.get("bind_address", None)
- bind_addresses = listener_config.get("bind_addresses", [])
+ bind_addresses = listener_config["bind_addresses"]
site_tag = listener_config.get("tag", port)
resources = {}
for res in listener_config["resources"]:
@@ -93,9 +92,6 @@ class FederationSenderServer(HomeServer):
root_resource = create_resource_tree(resources, Resource())
- if bind_address is not None:
- bind_addresses.append(bind_address)
-
for address in bind_addresses:
reactor.listenTCP(
port,
@@ -115,11 +111,7 @@ class FederationSenderServer(HomeServer):
if listener["type"] == "http":
self._listen_http(listener)
elif listener["type"] == "manhole":
- bind_address = listener.get("bind_address", None)
- bind_addresses = listener.get("bind_addresses", [])
-
- if bind_address is not None:
- bind_addresses.append(bind_address)
+ bind_addresses = listener["bind_addresses"]
for address in bind_addresses:
reactor.listenTCP(
diff --git a/synapse/app/homeserver.py b/synapse/app/homeserver.py
index 6c69ccd7e2..e0b87468fe 100755
--- a/synapse/app/homeserver.py
+++ b/synapse/app/homeserver.py
@@ -107,8 +107,7 @@ def build_resource_for_web_client(hs):
class SynapseHomeServer(HomeServer):
def _listener_http(self, config, listener_config):
port = listener_config["port"]
- bind_address = listener_config.get("bind_address", None)
- bind_addresses = listener_config.get("bind_addresses", [])
+ bind_addresses = listener_config["bind_addresses"]
tls = listener_config.get("tls", False)
site_tag = listener_config.get("tag", port)
@@ -175,9 +174,6 @@ class SynapseHomeServer(HomeServer):
root_resource = create_resource_tree(resources, root_resource)
- if bind_address is not None:
- bind_addresses.append(bind_address)
-
if tls:
for address in bind_addresses:
reactor.listenSSL(
@@ -212,11 +208,7 @@ class SynapseHomeServer(HomeServer):
if listener["type"] == "http":
self._listener_http(config, listener)
elif listener["type"] == "manhole":
- bind_address = listener.get("bind_address", None)
- bind_addresses = listener.get("bind_addresses", [])
-
- if bind_address is not None:
- bind_addresses.append(bind_address)
+ bind_addresses = listener["bind_addresses"]
for address in bind_addresses:
reactor.listenTCP(
diff --git a/synapse/app/media_repository.py b/synapse/app/media_repository.py
index a47283e520..ef17b158a5 100644
--- a/synapse/app/media_repository.py
+++ b/synapse/app/media_repository.py
@@ -87,8 +87,7 @@ class MediaRepositoryServer(HomeServer):
def _listen_http(self, listener_config):
port = listener_config["port"]
- bind_address = listener_config.get("bind_address", None)
- bind_addresses = listener_config.get("bind_addresses", [])
+ bind_addresses = listener_config["bind_addresses"]
site_tag = listener_config.get("tag", port)
resources = {}
for res in listener_config["resources"]:
@@ -107,9 +106,6 @@ class MediaRepositoryServer(HomeServer):
root_resource = create_resource_tree(resources, Resource())
- if bind_address is not None:
- bind_addresses.append(bind_address)
-
for address in bind_addresses:
reactor.listenTCP(
port,
@@ -129,11 +125,7 @@ class MediaRepositoryServer(HomeServer):
if listener["type"] == "http":
self._listen_http(listener)
elif listener["type"] == "manhole":
- bind_address = listener.get("bind_address", None)
- bind_addresses = listener.get("bind_addresses", [])
-
- if bind_address is not None:
- bind_addresses.append(bind_address)
+ bind_addresses = listener["bind_addresses"]
for address in bind_addresses:
reactor.listenTCP(
diff --git a/synapse/app/pusher.py b/synapse/app/pusher.py
index a3df375c81..073f2c2489 100644
--- a/synapse/app/pusher.py
+++ b/synapse/app/pusher.py
@@ -121,8 +121,7 @@ class PusherServer(HomeServer):
def _listen_http(self, listener_config):
port = listener_config["port"]
- bind_address = listener_config.get("bind_address", None)
- bind_addresses = listener_config.get("bind_addresses", [])
+ bind_addresses = listener_config["bind_addresses"]
site_tag = listener_config.get("tag", port)
resources = {}
for res in listener_config["resources"]:
@@ -132,9 +131,6 @@ class PusherServer(HomeServer):
root_resource = create_resource_tree(resources, Resource())
- if bind_address is not None:
- bind_addresses.append(bind_address)
-
for address in bind_addresses:
reactor.listenTCP(
port,
@@ -146,17 +142,6 @@ class PusherServer(HomeServer):
),
interface=address
)
- else:
- reactor.listenTCP(
- port,
- SynapseSite(
- "synapse.access.http.%s" % (site_tag,),
- site_tag,
- listener_config,
- root_resource,
- ),
- interface=bind_address
- )
logger.info("Synapse pusher now listening on port %d", port)
@@ -165,11 +150,7 @@ class PusherServer(HomeServer):
if listener["type"] == "http":
self._listen_http(listener)
elif listener["type"] == "manhole":
- bind_address = listener.get("bind_address", None)
- bind_addresses = listener.get("bind_addresses", [])
-
- if bind_address is not None:
- bind_addresses.append(bind_address)
+ bind_addresses = listener["bind_addresses"]
for address in bind_addresses:
reactor.listenTCP(
diff --git a/synapse/app/synchrotron.py b/synapse/app/synchrotron.py
index 439daaa60a..4dfc2dc648 100644
--- a/synapse/app/synchrotron.py
+++ b/synapse/app/synchrotron.py
@@ -289,8 +289,7 @@ class SynchrotronServer(HomeServer):
def _listen_http(self, listener_config):
port = listener_config["port"]
- bind_address = listener_config.get("bind_address", None)
- bind_addresses = listener_config.get("bind_addresses", [])
+ bind_addresses = listener_config["bind_addresses"]
site_tag = listener_config.get("tag", port)
resources = {}
for res in listener_config["resources"]:
@@ -312,9 +311,6 @@ class SynchrotronServer(HomeServer):
root_resource = create_resource_tree(resources, Resource())
- if bind_address is not None:
- bind_addresses.append(bind_address)
-
for address in bind_addresses:
reactor.listenTCP(
port,
@@ -334,11 +330,7 @@ class SynchrotronServer(HomeServer):
if listener["type"] == "http":
self._listen_http(listener)
elif listener["type"] == "manhole":
- bind_address = listener.get("bind_address", None)
- bind_addresses = listener.get("bind_addresses", [])
-
- if bind_address is not None:
- bind_addresses.append(bind_address)
+ bind_addresses = listener["bind_addresses"]
for address in bind_addresses:
reactor.listenTCP(
diff --git a/synapse/config/logger.py b/synapse/config/logger.py
index 63e69a7e0c..77ded0ad25 100644
--- a/synapse/config/logger.py
+++ b/synapse/config/logger.py
@@ -22,7 +22,6 @@ import yaml
from string import Template
import os
import signal
-from synapse.util.debug import debug_deferreds
DEFAULT_LOG_CONFIG = Template("""
@@ -71,8 +70,6 @@ class LoggingConfig(Config):
self.verbosity = config.get("verbose", 0)
self.log_config = self.abspath(config.get("log_config"))
self.log_file = self.abspath(config.get("log_file"))
- if config.get("full_twisted_stacktraces"):
- debug_deferreds()
def default_config(self, config_dir_path, server_name, **kwargs):
log_file = self.abspath("homeserver.log")
@@ -88,11 +85,6 @@ class LoggingConfig(Config):
# A yaml python logging config file
log_config: "%(log_config)s"
-
- # Stop twisted from discarding the stack traces of exceptions in
- # deferreds by waiting a reactor tick before running a deferred's
- # callbacks.
- # full_twisted_stacktraces: true
""" % locals()
def read_arguments(self, args):
diff --git a/synapse/config/server.py b/synapse/config/server.py
index 5e6b2a68a7..1f9999d57a 100644
--- a/synapse/config/server.py
+++ b/synapse/config/server.py
@@ -42,6 +42,15 @@ class ServerConfig(Config):
self.listeners = config.get("listeners", [])
+ for listener in self.listeners:
+ bind_address = listener.pop("bind_address", None)
+ bind_addresses = listener.setdefault("bind_addresses", [])
+
+ if bind_address:
+ bind_addresses.append(bind_address)
+ elif not bind_addresses:
+ bind_addresses.append('')
+
self.gc_thresholds = read_gc_thresholds(config.get("gc_thresholds", None))
bind_port = config.get("bind_port")
@@ -54,7 +63,7 @@ class ServerConfig(Config):
self.listeners.append({
"port": bind_port,
- "bind_address": bind_host,
+ "bind_addresses": [bind_host],
"tls": True,
"type": "http",
"resources": [
@@ -73,7 +82,7 @@ class ServerConfig(Config):
if unsecure_port:
self.listeners.append({
"port": unsecure_port,
- "bind_address": bind_host,
+ "bind_addresses": [bind_host],
"tls": False,
"type": "http",
"resources": [
@@ -92,7 +101,7 @@ class ServerConfig(Config):
if manhole:
self.listeners.append({
"port": manhole,
- "bind_address": "127.0.0.1",
+ "bind_addresses": ["127.0.0.1"],
"type": "manhole",
})
@@ -100,7 +109,7 @@ class ServerConfig(Config):
if metrics_port:
self.listeners.append({
"port": metrics_port,
- "bind_address": config.get("metrics_bind_host", "127.0.0.1"),
+ "bind_addresses": [config.get("metrics_bind_host", "127.0.0.1")],
"tls": False,
"type": "http",
"resources": [
diff --git a/synapse/federation/federation_server.py b/synapse/federation/federation_server.py
index 1fee4e83a6..862ccbef5d 100644
--- a/synapse/federation/federation_server.py
+++ b/synapse/federation/federation_server.py
@@ -52,8 +52,8 @@ class FederationServer(FederationBase):
self.auth = hs.get_auth()
- self._room_pdu_linearizer = Linearizer()
- self._server_linearizer = Linearizer()
+ self._room_pdu_linearizer = Linearizer("fed_room_pdu")
+ self._server_linearizer = Linearizer("fed_server")
# We cache responses to state queries, as they take a while and often
# come in waves.
diff --git a/synapse/handlers/message.py b/synapse/handlers/message.py
index 7a57a69bd3..88bd2d572e 100644
--- a/synapse/handlers/message.py
+++ b/synapse/handlers/message.py
@@ -279,7 +279,9 @@ class MessageHandler(BaseHandler):
if event.type == EventTypes.Message:
presence = self.hs.get_presence_handler()
- yield presence.bump_presence_active_time(user)
+ # We don't want to block sending messages on any presence code. This
+ # matters as sometimes presence code can take a while.
+ preserve_fn(presence.bump_presence_active_time)(user)
@defer.inlineCallbacks
def deduplicate_state_event(self, event, context):
diff --git a/synapse/handlers/room_member.py b/synapse/handlers/room_member.py
index 2f8782e522..b2806555cf 100644
--- a/synapse/handlers/room_member.py
+++ b/synapse/handlers/room_member.py
@@ -45,7 +45,7 @@ class RoomMemberHandler(BaseHandler):
def __init__(self, hs):
super(RoomMemberHandler, self).__init__(hs)
- self.member_linearizer = Linearizer()
+ self.member_linearizer = Linearizer(name="member")
self.clock = hs.get_clock()
@@ -89,7 +89,7 @@ class RoomMemberHandler(BaseHandler):
duplicate = yield msg_handler.deduplicate_state_event(event, context)
if duplicate is not None:
# Discard the new event since this membership change is a no-op.
- return
+ defer.returnValue(duplicate)
yield msg_handler.handle_new_client_event(
requester,
@@ -120,6 +120,8 @@ class RoomMemberHandler(BaseHandler):
if prev_member_event.membership == Membership.JOIN:
user_left_room(self.distributor, target, room_id)
+ defer.returnValue(event)
+
@defer.inlineCallbacks
def remote_join(self, remote_room_hosts, room_id, user, content):
if len(remote_room_hosts) == 0:
@@ -187,6 +189,7 @@ class RoomMemberHandler(BaseHandler):
ratelimit=True,
content=None,
):
+ content_specified = bool(content)
if content is None:
content = {}
@@ -229,6 +232,13 @@ class RoomMemberHandler(BaseHandler):
errcode=Codes.BAD_STATE
)
+ if old_state:
+ same_content = content == old_state.content
+ same_membership = old_membership == effective_membership_state
+ same_sender = requester.user.to_string() == old_state.sender
+ if same_sender and same_membership and same_content:
+ defer.returnValue(old_state)
+
is_host_in_room = yield self._is_host_in_room(current_state_ids)
if effective_membership_state == Membership.JOIN:
@@ -247,8 +257,9 @@ class RoomMemberHandler(BaseHandler):
content["membership"] = Membership.JOIN
profile = self.hs.get_handlers().profile_handler
- content["displayname"] = yield profile.get_displayname(target)
- content["avatar_url"] = yield profile.get_avatar_url(target)
+ if not content_specified:
+ content["displayname"] = yield profile.get_displayname(target)
+ content["avatar_url"] = yield profile.get_avatar_url(target)
if requester.is_guest:
content["kind"] = "guest"
@@ -290,7 +301,7 @@ class RoomMemberHandler(BaseHandler):
defer.returnValue({})
- yield self._local_membership_update(
+ res = yield self._local_membership_update(
requester=requester,
target=target,
room_id=room_id,
@@ -300,6 +311,7 @@ class RoomMemberHandler(BaseHandler):
prev_event_ids=latest_event_ids,
content=content,
)
+ defer.returnValue(res)
@defer.inlineCallbacks
def send_membership_event(
diff --git a/synapse/rest/client/transactions.py b/synapse/rest/client/transactions.py
index 351170edbc..efa77b8c51 100644
--- a/synapse/rest/client/transactions.py
+++ b/synapse/rest/client/transactions.py
@@ -86,7 +86,11 @@ class HttpTransactionCache(object):
pass # execute the function instead.
deferred = fn(*args, **kwargs)
- observable = ObservableDeferred(deferred)
+
+ # We don't add an errback to the raw deferred, so we ask ObservableDeferred
+ # to swallow the error. This is fine as the error will still be reported
+ # to the observers.
+ observable = ObservableDeferred(deferred, consumeErrors=True)
self.transactions[txn_key] = (observable, self.clock.time_msec())
return observable.observe()
diff --git a/synapse/rest/client/v1/room.py b/synapse/rest/client/v1/room.py
index eead435bfd..2ebf5e59a0 100644
--- a/synapse/rest/client/v1/room.py
+++ b/synapse/rest/client/v1/room.py
@@ -152,23 +152,29 @@ class RoomStateEventRestServlet(ClientV1RestServlet):
if state_key is not None:
event_dict["state_key"] = state_key
- msg_handler = self.handlers.message_handler
- event, context = yield msg_handler.create_event(
- event_dict,
- token_id=requester.access_token_id,
- txn_id=txn_id,
- )
-
if event_type == EventTypes.Member:
- yield self.handlers.room_member_handler.send_membership_event(
+ membership = content.get("membership", None)
+ event = yield self.handlers.room_member_handler.update_membership(
requester,
- event,
- context,
+ target=UserID.from_string(state_key),
+ room_id=room_id,
+ action=membership,
+ content=content,
)
else:
+ msg_handler = self.handlers.message_handler
+ event, context = yield msg_handler.create_event(
+ event_dict,
+ token_id=requester.access_token_id,
+ txn_id=txn_id,
+ )
+
yield msg_handler.send_nonmember_event(requester, event, context)
- defer.returnValue((200, {"event_id": event.event_id}))
+ ret = {}
+ if event:
+ ret = {"event_id": event.event_id}
+ defer.returnValue((200, ret))
# TODO: Needs unit testing for generic events + feedback
diff --git a/synapse/rest/media/v1/media_repository.py b/synapse/rest/media/v1/media_repository.py
index 692e078419..3cbeca503c 100644
--- a/synapse/rest/media/v1/media_repository.py
+++ b/synapse/rest/media/v1/media_repository.py
@@ -61,7 +61,7 @@ class MediaRepository(object):
self.dynamic_thumbnails = hs.config.dynamic_thumbnails
self.thumbnail_requirements = hs.config.thumbnail_requirements
- self.remote_media_linearizer = Linearizer()
+ self.remote_media_linearizer = Linearizer(name="media_remote")
self.recently_accessed_remotes = set()
@@ -98,6 +98,8 @@ class MediaRepository(object):
with open(fname, "wb") as f:
f.write(content)
+ logger.info("Stored local media in file %r", fname)
+
yield self.store.store_local_media(
media_id=media_id,
media_type=media_type,
@@ -190,6 +192,8 @@ class MediaRepository(object):
else:
upload_name = None
+ logger.info("Stored remote media in file %r", fname)
+
yield self.store.store_cached_remote_media(
origin=server_name,
media_id=media_id,
diff --git a/synapse/rest/media/v1/thumbnailer.py b/synapse/rest/media/v1/thumbnailer.py
index 0bb3676844..3868d4f65f 100644
--- a/synapse/rest/media/v1/thumbnailer.py
+++ b/synapse/rest/media/v1/thumbnailer.py
@@ -16,6 +16,10 @@
import PIL.Image as Image
from io import BytesIO
+import logging
+
+logger = logging.getLogger(__name__)
+
class Thumbnailer(object):
@@ -86,4 +90,5 @@ class Thumbnailer(object):
output_bytes = output_bytes_io.getvalue()
with open(output_path, "wb") as output_file:
output_file.write(output_bytes)
+ logger.info("Stored thumbnail in file %r", output_path)
return len(output_bytes)
diff --git a/synapse/rest/media/v1/upload_resource.py b/synapse/rest/media/v1/upload_resource.py
index b716d1d892..4ab33f73bf 100644
--- a/synapse/rest/media/v1/upload_resource.py
+++ b/synapse/rest/media/v1/upload_resource.py
@@ -97,6 +97,8 @@ class UploadResource(Resource):
content_length, requester.user
)
+ logger.info("Uploaded content with URI %r", content_uri)
+
respond_with_json(
request, 200, {"content_uri": content_uri}, send_cors=True
)
diff --git a/synapse/state.py b/synapse/state.py
index 8003099c88..b9d5627a82 100644
--- a/synapse/state.py
+++ b/synapse/state.py
@@ -89,7 +89,7 @@ class StateHandler(object):
# dict of set of event_ids -> _StateCacheEntry.
self._state_cache = None
- self.resolve_linearizer = Linearizer()
+ self.resolve_linearizer = Linearizer(name="state_resolve_lock")
def start_caching(self):
logger.debug("start_caching")
diff --git a/synapse/storage/__init__.py b/synapse/storage/__init__.py
index fe936b3e62..e8495f1eb9 100644
--- a/synapse/storage/__init__.py
+++ b/synapse/storage/__init__.py
@@ -189,7 +189,8 @@ class DataStore(RoomMemberStore, RoomStore,
db_conn, "device_inbox",
entity_column="user_id",
stream_column="stream_id",
- max_value=max_device_inbox_id
+ max_value=max_device_inbox_id,
+ limit=1000,
)
self._device_inbox_stream_cache = StreamChangeCache(
"DeviceInboxStreamChangeCache", min_device_inbox_id,
@@ -202,6 +203,7 @@ class DataStore(RoomMemberStore, RoomStore,
entity_column="destination",
stream_column="stream_id",
max_value=max_device_inbox_id,
+ limit=1000,
)
self._device_federation_outbox_stream_cache = StreamChangeCache(
"DeviceFederationOutboxStreamChangeCache", min_device_outbox_id,
diff --git a/synapse/storage/_base.py b/synapse/storage/_base.py
index b62c459d8b..5620a655eb 100644
--- a/synapse/storage/_base.py
+++ b/synapse/storage/_base.py
@@ -838,18 +838,19 @@ class SQLBaseStore(object):
return txn.execute(sql, keyvalues.values())
def _get_cache_dict(self, db_conn, table, entity_column, stream_column,
- max_value):
+ max_value, limit=100000):
# Fetch a mapping of room_id -> max stream position for "recent" rooms.
# It doesn't really matter how many we get, the StreamChangeCache will
# do the right thing to ensure it respects the max size of cache.
sql = (
"SELECT %(entity)s, MAX(%(stream)s) FROM %(table)s"
- " WHERE %(stream)s > ? - 100000"
+ " WHERE %(stream)s > ? - %(limit)s"
" GROUP BY %(entity)s"
) % {
"table": table,
"entity": entity_column,
"stream": stream_column,
+ "limit": limit,
}
sql = self.database_engine.convert_param_style(sql)
diff --git a/synapse/util/async.py b/synapse/util/async.py
index 83875edc85..35380bf8ed 100644
--- a/synapse/util/async.py
+++ b/synapse/util/async.py
@@ -192,8 +192,11 @@ class Linearizer(object):
logger.info(
"Waiting to acquire linearizer lock %r for key %r", self.name, key
)
- with PreserveLoggingContext():
- yield current_defer
+ try:
+ with PreserveLoggingContext():
+ yield current_defer
+ except:
+ logger.exception("Unexpected exception in Linearizer")
logger.info("Acquired linearizer lock %r for key %r", self.name, key)
diff --git a/synapse/util/debug.py b/synapse/util/debug.py
deleted file mode 100644
index dc49162e6a..0000000000
--- a/synapse/util/debug.py
+++ /dev/null
@@ -1,71 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright 2015, 2016 OpenMarket Ltd
-#
-# 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.
-
-from twisted.internet import defer, reactor
-from functools import wraps
-from synapse.util.logcontext import LoggingContext, PreserveLoggingContext
-
-
-def debug_deferreds():
- """Cause all deferreds to wait for a reactor tick before running their
- callbacks. This increases the chance of getting a stack trace out of
- a defer.inlineCallback since the code waiting on the deferred will get
- a chance to add an errback before the deferred runs."""
-
- # Helper method for retrieving and restoring the current logging context
- # around a callback.
- def with_logging_context(fn):
- context = LoggingContext.current_context()
-
- def restore_context_callback(x):
- with PreserveLoggingContext(context):
- return fn(x)
-
- return restore_context_callback
-
- # We are going to modify the __init__ method of defer.Deferred so we
- # need to get a copy of the old method so we can still call it.
- old__init__ = defer.Deferred.__init__
-
- # We need to create a deferred to bounce the callbacks through the reactor
- # but we don't want to add a callback when we create that deferred so we
- # we create a new type of deferred that uses the old __init__ method.
- # This is safe as long as the old __init__ method doesn't invoke an
- # __init__ using super.
- class Bouncer(defer.Deferred):
- __init__ = old__init__
-
- # We'll add this as a callback to all Deferreds. Twisted will wait until
- # the bouncer deferred resolves before calling the callbacks of the
- # original deferred.
- def bounce_callback(x):
- bouncer = Bouncer()
- reactor.callLater(0, with_logging_context(bouncer.callback), x)
- return bouncer
-
- # We'll add this as an errback to all Deferreds. Twisted will wait until
- # the bouncer deferred resolves before calling the errbacks of the
- # original deferred.
- def bounce_errback(x):
- bouncer = Bouncer()
- reactor.callLater(0, with_logging_context(bouncer.errback), x)
- return bouncer
-
- @wraps(old__init__)
- def new__init__(self, *args, **kargs):
- old__init__(self, *args, **kargs)
- self.addCallbacks(bounce_callback, bounce_errback)
-
- defer.Deferred.__init__ = new__init__
diff --git a/tests/rest/client/v1/test_rooms.py b/tests/rest/client/v1/test_rooms.py
index 4fe99ebc0b..6bce352c5f 100644
--- a/tests/rest/client/v1/test_rooms.py
+++ b/tests/rest/client/v1/test_rooms.py
@@ -259,8 +259,8 @@ class RoomPermissionsTestCase(RestTestCase):
# set [invite/join/left] of self, set [invite/join/left] of other,
# expect all 404s because room doesn't exist on any server
for usr in [self.user_id, self.rmcreator_id]:
- yield self.join(room=room, user=usr, expect_code=403)
- yield self.leave(room=room, user=usr, expect_code=403)
+ yield self.join(room=room, user=usr, expect_code=404)
+ yield self.leave(room=room, user=usr, expect_code=404)
@defer.inlineCallbacks
def test_membership_private_room_perms(self):
diff --git a/tests/rest/client/v1/utils.py b/tests/rest/client/v1/utils.py
index 17524b2e23..3bb1dd003a 100644
--- a/tests/rest/client/v1/utils.py
+++ b/tests/rest/client/v1/utils.py
@@ -87,7 +87,10 @@ class RestTestCase(unittest.TestCase):
(code, response) = yield self.mock_resource.trigger(
"PUT", path, json.dumps(data)
)
- self.assertEquals(expect_code, code, msg=str(response))
+ self.assertEquals(
+ expect_code, code,
+ msg="Expected: %d, got: %d, resp: %r" % (expect_code, code, response)
+ )
self.auth_user_id = temp_id
|