summary refs log tree commit diff
path: root/synapse/handlers/room.py
diff options
context:
space:
mode:
Diffstat (limited to 'synapse/handlers/room.py')
-rw-r--r--synapse/handlers/room.py129
1 files changed, 56 insertions, 73 deletions
diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py
index 5a4569ac95..7b4b051888 100644
--- a/synapse/handlers/room.py
+++ b/synapse/handlers/room.py
@@ -25,14 +25,14 @@ from synapse.api.events.room import (
 from synapse.api.streams.event import EventStream, EventsStreamData
 from synapse.handlers.presence import PresenceStreamData
 from synapse.util import stringutils
-from ._base import BaseHandler
+from ._base import BaseRoomHandler
 
 import logging
 
 logger = logging.getLogger(__name__)
 
 
-class MessageHandler(BaseHandler):
+class MessageHandler(BaseRoomHandler):
 
     def __init__(self, hs):
         super(MessageHandler, self).__init__(hs)
@@ -84,20 +84,12 @@ class MessageHandler(BaseHandler):
         if stamp_event:
             event.content["hsob_ts"] = int(self.clock.time_msec())
 
-        with (yield self.room_lock.lock(event.room_id)):
-            if not suppress_auth:
-                yield self.auth.check(event, raises=True)
+        snapshot = yield self.store.snapshot_room(event.room_id, event.user_id)
 
-            # store message in db
-            store_id = yield self.store.persist_event(event)
+        if not suppress_auth:
+            yield self.auth.check(event, snapshot, raises=True)
 
-            event.destinations = yield self.store.get_joined_hosts_for_room(
-                event.room_id
-            )
-
-            self.notifier.on_new_room_event(event, store_id)
-
-        yield self.hs.get_federation().handle_new_event(event)
+        yield self._on_new_room_event(event, snapshot)
 
     @defer.inlineCallbacks
     def get_messages(self, user_id=None, room_id=None, pagin_config=None,
@@ -134,23 +126,16 @@ class MessageHandler(BaseHandler):
             SynapseError if something went wrong.
         """
 
-        with (yield self.room_lock.lock(event.room_id)):
-            yield self.auth.check(event, raises=True)
+        snapshot = yield self.store.snapshot_room(event.room_id, event.user_id)
 
-            if stamp_event:
-                event.content["hsob_ts"] = int(self.clock.time_msec())
+        yield self.auth.check(event, snapshot, raises=True)
 
-            yield self.state_handler.handle_new_event(event)
-
-            # store in db
-            store_id = yield self.store.persist_event(event)
+        if stamp_event:
+            event.content["hsob_ts"] = int(self.clock.time_msec())
 
-            event.destinations = yield self.store.get_joined_hosts_for_room(
-                event.room_id
-            )
-            self.notifier.on_new_room_event(event, store_id)
+        yield self.state_handler.handle_new_event(event, snapshot)
 
-        yield self.hs.get_federation().handle_new_event(event)
+        yield self._on_new_room_event(event, snapshot)
 
     @defer.inlineCallbacks
     def get_room_data(self, user_id=None, room_id=None,
@@ -219,18 +204,12 @@ class MessageHandler(BaseHandler):
         if stamp_event:
             event.content["hsob_ts"] = int(self.clock.time_msec())
 
-        with (yield self.room_lock.lock(event.room_id)):
-            yield self.auth.check(event, raises=True)
-
-            # store message in db
-            store_id = yield self.store.persist_event(event)
+        snapshot = yield self.store.snapshot_room(event.room_id, event.user_id)
 
-            event.destinations = yield self.store.get_joined_hosts_for_room(
-                event.room_id
-            )
-        yield self.hs.get_federation().handle_new_event(event)
+        yield self.auth.check(event, snapshot, raises=True)
 
-        self.notifier.on_new_room_event(event, store_id)
+        # store message in db
+        yield self._on_new_room_event(event, snapshot)
 
     @defer.inlineCallbacks
     def snapshot_all_rooms(self, user_id=None, pagin_config=None,
@@ -312,7 +291,7 @@ class MessageHandler(BaseHandler):
         defer.returnValue(ret)
 
 
-class RoomCreationHandler(BaseHandler):
+class RoomCreationHandler(BaseRoomHandler):
 
     @defer.inlineCallbacks
     def create_room(self, user_id, room_id, config):
@@ -383,6 +362,13 @@ class RoomCreationHandler(BaseHandler):
             content=config,
         )
 
+        snapshot = yield self.store.snapshot_room(
+            room_id=room_id,
+            user_id=user_id,
+            state_type=RoomConfigEvent.TYPE,
+            state_key="",
+        )
+
         if room_alias:
             yield self.store.create_room_alias_association(
                 room_id=room_id,
@@ -390,10 +376,11 @@ class RoomCreationHandler(BaseHandler):
                 servers=[self.hs.hostname],
             )
 
-        yield self.state_handler.handle_new_event(config_event)
+        yield self.state_handler.handle_new_event(config_event, snapshot)
         # store_id = persist...
 
-        yield self.hs.get_federation().handle_new_event(config_event)
+        federation_handler = self.hs.get_handlers().federation_handler
+        yield federation_handler.handle_new_event(config_event, snapshot)
         # self.notifier.on_new_room_event(event, store_id)
 
         content = {"membership": Membership.JOIN}
@@ -418,7 +405,7 @@ class RoomCreationHandler(BaseHandler):
         defer.returnValue(result)
 
 
-class RoomMemberHandler(BaseHandler):
+class RoomMemberHandler(BaseRoomHandler):
     # TODO(paul): This handler currently contains a messy conflation of
     #   low-level API that works on UserID objects and so on, and REST-level
     #   API that takes ID strings and returns pagination chunks. These concerns
@@ -529,6 +516,11 @@ class RoomMemberHandler(BaseHandler):
         """
         target_user_id = event.state_key
 
+        snapshot = yield self.store.snapshot_room(
+            event.room_id, event.user_id,
+            RoomMemberEvent.TYPE, target_user_id
+        )
+        ## TODO(markjh): get prev state from snapshot.
         prev_state = yield self.store.get_room_member(
             target_user_id, event.room_id
         )
@@ -549,24 +541,22 @@ class RoomMemberHandler(BaseHandler):
         # if this HS is not currently in the room, i.e. we have to do the
         # invite/join dance.
         if event.membership == Membership.JOIN:
-            yield self._do_join(event, do_auth=do_auth)
+            yield self._do_join(event, snapshot, do_auth=do_auth)
         else:
             # This is not a JOIN, so we can handle it normally.
             if do_auth:
-                yield self.auth.check(event, raises=True)
+                yield self.auth.check(event, snapshot, raises=True)
 
-            prev_state = yield self.store.get_room_member(
-                target_user_id, event.room_id
-            )
             if prev_state and prev_state.membership == event.membership:
                 # double same action, treat this event as a NOOP.
                 defer.returnValue({})
                 return
 
-            yield self.state_handler.handle_new_event(event)
+            yield self.state_handler.handle_new_event(event, snapshot)
             yield self._do_local_membership_update(
                 event,
                 membership=event.content["membership"],
+                snapshot=snapshot,
             )
 
         defer.returnValue({"room_id": room_id})
@@ -596,12 +586,16 @@ class RoomMemberHandler(BaseHandler):
             content=content,
         )
 
-        yield self._do_join(new_event, room_host=host, do_auth=True)
+        snapshot = yield self.store.snapshot_room(
+            room_id, joinee, RoomMemberEvent.TYPE, joinee
+        )
+
+        yield self._do_join(new_event, snapshot, room_host=host, do_auth=True)
 
         defer.returnValue({"room_id": room_id})
 
     @defer.inlineCallbacks
-    def _do_join(self, event, room_host=None, do_auth=True):
+    def _do_join(self, event, snapshot, room_host=None, do_auth=True):
         joinee = self.hs.parse_userid(event.state_key)
         # room_id = RoomID.from_string(event.room_id, self.hs)
         room_id = event.room_id
@@ -623,6 +617,7 @@ class RoomMemberHandler(BaseHandler):
         elif room_host:
             should_do_dance = True
         else:
+            # TODO(markjh): get prev_state from snapshot
             prev_state = yield self.store.get_room_member(
                 joinee.to_string(), room_id
             )
@@ -642,7 +637,7 @@ class RoomMemberHandler(BaseHandler):
         if should_do_dance:
             handler = self.hs.get_handlers().federation_handler
             have_joined = yield handler.do_invite_join(
-                room_host, room_id, event.user_id, event.content
+                room_host, room_id, event.user_id, event.content, snapshot
             )
 
         # We want to do the _do_update inside the room lock.
@@ -650,12 +645,13 @@ class RoomMemberHandler(BaseHandler):
             logger.debug("Doing normal join")
 
             if do_auth:
-                yield self.auth.check(event, raises=True)
+                yield self.auth.check(event, snapshot, raises=True)
 
-            yield self.state_handler.handle_new_event(event)
+            yield self.state_handler.handle_new_event(event, snapshot)
             yield self._do_local_membership_update(
                 event,
                 membership=event.content["membership"],
+                snapshot=snapshot,
             )
 
         user = self.hs.parse_userid(event.user_id)
@@ -699,39 +695,26 @@ class RoomMemberHandler(BaseHandler):
 
         defer.returnValue([r.room_id for r in rooms])
 
-    @defer.inlineCallbacks
-    def _do_local_membership_update(self, event, membership):
-        # store membership
-        store_id = yield self.store.persist_event(event)
-
-        # Send a PDU to all hosts who have joined the room.
-        destinations = yield self.store.get_joined_hosts_for_room(
-            event.room_id
-        )
+    def _do_local_membership_update(self, event, membership, snapshot):
+        destinations = []
 
         # If we're inviting someone, then we should also send it to that
         # HS.
         target_user_id = event.state_key
         if membership == Membership.INVITE:
-            host = UserID.from_string(
-                target_user_id, self.hs
-            ).domain
+            host = UserID.from_string(target_user_id, self.hs).domain
             destinations.append(host)
 
         # If we are joining a remote HS, include that.
         if membership == Membership.JOIN:
-            host = UserID.from_string(
-                target_user_id, self.hs
-            ).domain
+            host = UserID.from_string(target_user_id, self.hs).domain
             destinations.append(host)
 
-        event.destinations = list(set(destinations))
-
-        yield self.hs.get_federation().handle_new_event(event)
-        self.notifier.on_new_room_event(event, store_id)
-
+        return self._on_new_room_event(
+            event, snapshot, extra_destinations=destinations
+        )
 
-class RoomListHandler(BaseHandler):
+class RoomListHandler(BaseRoomHandler):
 
     @defer.inlineCallbacks
     def get_public_room_list(self):