Merge pull request #1872 from matrix-org/erikj/key_changes

Include newly joined users in /keys/changes API
This commit is contained in:
Erik Johnston 2017-02-01 18:10:33 +00:00 committed by GitHub
commit 14d5e22700
3 changed files with 57 additions and 5 deletions

View File

@ -14,6 +14,7 @@
# limitations under the License. # limitations under the License.
from synapse.api import errors from synapse.api import errors
from synapse.api.constants import EventTypes
from synapse.util import stringutils from synapse.util import stringutils
from synapse.util.async import Linearizer from synapse.util.async import Linearizer
from synapse.types import get_domain_from_id from synapse.types import get_domain_from_id
@ -221,15 +222,52 @@ class DeviceHandler(BaseHandler):
self.federation_sender.send_device_messages(host) self.federation_sender.send_device_messages(host)
@defer.inlineCallbacks @defer.inlineCallbacks
def get_user_ids_changed(self, user_id, from_device_key): def get_user_ids_changed(self, user_id, from_token):
"""Get list of users that have had the devices updated, or have newly
joined a room, that `user_id` may be interested in.
Args:
user_id (str)
from_token (StreamToken)
"""
rooms = yield self.store.get_rooms_for_user(user_id) rooms = yield self.store.get_rooms_for_user(user_id)
room_ids = set(r.room_id for r in rooms) room_ids = set(r.room_id for r in rooms)
user_ids_changed = set() # First we check if any devices have changed
changed = yield self.store.get_user_whose_devices_changed( changed = yield self.store.get_user_whose_devices_changed(
from_device_key from_token.device_list_key
) )
for other_user_id in changed:
# Then work out if any users have since joined
rooms_changed = self.store.get_rooms_that_changed(room_ids, from_token.room_key)
possibly_changed = set(changed)
for room_id in rooms_changed:
# Fetch (an approximation) of the current state at the time.
event_rows, token = yield self.store.get_recent_event_ids_for_room(
room_id, end_token=from_token.room_key, limit=1,
)
if event_rows:
last_event_id = event_rows[-1]["event_id"]
prev_state_ids = yield self.store.get_state_ids_for_event(last_event_id)
else:
prev_state_ids = {}
current_state_ids = yield self.state.get_current_state_ids(room_id)
# If there has been any change in membership, include them in the
# possibly changed list. We'll check if they are joined below,
# and we're not toooo worried about spuriously adding users.
for key, event_id in current_state_ids.iteritems():
etype, state_key = key
if etype == EventTypes.Member:
prev_event_id = prev_state_ids.get(key, None)
if not prev_event_id or prev_event_id != event_id:
possibly_changed.add(state_key)
user_ids_changed = set()
for other_user_id in possibly_changed:
other_rooms = yield self.store.get_rooms_for_user(other_user_id) other_rooms = yield self.store.get_rooms_for_user(other_user_id)
if room_ids.intersection(e.room_id for e in other_rooms): if room_ids.intersection(e.room_id for e in other_rooms):
user_ids_changed.add(other_user_id) user_ids_changed.add(other_user_id)

View File

@ -189,7 +189,7 @@ class KeyChangesServlet(RestServlet):
user_id = requester.user.to_string() user_id = requester.user.to_string()
changed = yield self.device_handler.get_user_ids_changed( changed = yield self.device_handler.get_user_ids_changed(
user_id, from_token.device_list_key, user_id, from_token,
) )
defer.returnValue((200, { defer.returnValue((200, {

View File

@ -244,6 +244,20 @@ class StreamStore(SQLBaseStore):
defer.returnValue(results) defer.returnValue(results)
def get_rooms_that_changed(self, room_ids, from_key):
"""Given a list of rooms and a token, return rooms where there may have
been changes.
Args:
room_ids (list)
from_key (str): The room_key portion of a StreamToken
"""
from_key = RoomStreamToken.parse_stream_token(from_key).stream
return set(
room_id for room_id in room_ids
if self._events_stream_cache.has_entity_changed(room_id, from_key)
)
@defer.inlineCallbacks @defer.inlineCallbacks
def get_room_events_stream_for_room(self, room_id, from_key, to_key, limit=0, def get_room_events_stream_for_room(self, room_id, from_key, to_key, limit=0,
order='DESC'): order='DESC'):