summary refs log tree commit diff
diff options
context:
space:
mode:
authorRichard van der Hoff <richard@matrix.org>2018-09-26 12:16:13 +0100
committerRichard van der Hoff <richard@matrix.org>2018-09-27 11:37:39 +0100
commitbd61c82bdf97460a33080bcb6b2c836616a3b415 (patch)
tree8ff0f2ce1116794dbe2aea4991a530023b42c69d
parentFix "unhashable type: 'list'" exception in federation handling (diff)
downloadsynapse-bd61c82bdf97460a33080bcb6b2c836616a3b415.tar.xz
Include state from remote servers in pdu handling
If we've fetched state events from remote servers in order to resolve the state
for a new event, we need to actually pass those events into
resolve_events_with_factory (so that it can do the state res) and then persist
the ones we need - otherwise other bits of the codebase get confused about why
we have state groups pointing to non-existent events.
-rw-r--r--synapse/handlers/federation.py23
1 files changed, 19 insertions, 4 deletions
diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py
index 2d6b8edec4..cdad565d04 100644
--- a/synapse/handlers/federation.py
+++ b/synapse/handlers/federation.py
@@ -326,6 +326,9 @@ class FederationHandler(BaseHandler):
                 # Calculate the state of the previous events, and
                 # de-conflict them to find the current state.
                 auth_chains = set()
+                event_map = {
+                    event_id: pdu,
+                }
                 try:
                     # Get the state of the events we know about
                     ours = yield self.store.get_state_groups_ids(room_id, seen)
@@ -365,18 +368,30 @@ class FederationHandler(BaseHandler):
                             }
                             state_maps.append(remote_state_map)
 
+                            for x in remote_state:
+                                event_map[x.event_id] = x
+
                     # Resolve any conflicting state
+                    @defer.inlineCallbacks
                     def fetch(ev_ids):
-                        return self.store.get_events(
-                            ev_ids, get_prev_content=False, check_redacted=False
+                        fetched = yield self.store.get_events(
+                            ev_ids, get_prev_content=False, check_redacted=False,
                         )
+                        # add any events we fetch here to the `event_map` so that we
+                        # can use them to build the state event list below.
+                        event_map.update(fetched)
+                        defer.returnValue(fetched)
 
                     room_version = yield self.store.get_room_version(room_id)
                     state_map = yield resolve_events_with_factory(
-                        room_version, state_maps, {event_id: pdu}, fetch,
+                        room_version, state_maps, event_map, fetch,
                     )
 
-                    state = (yield self.store.get_events(state_map.values())).values()
+                    # we need to give _process_received_pdu the actual state events
+                    # rather than event ids, so generate that now.
+                    state = [
+                        event_map[e] for e in six.itervalues(state_map)
+                    ]
                     auth_chain = list(auth_chains)
                 except Exception:
                     logger.warn(