diff options
author | Paul "LeoNerd" Evans <paul@matrix.org> | 2015-02-11 15:53:56 +0000 |
---|---|---|
committer | Paul "LeoNerd" Evans <paul@matrix.org> | 2015-02-11 15:53:56 +0000 |
commit | 7be0f6594e2a6dd7c3dc745eb856025276ec7d1f (patch) | |
tree | c7e2d6965b272a72b5905aecb22397e23579680d | |
parent | Fix bug where variable was not always defined (diff) | |
download | synapse-7be0f6594e2a6dd7c3dc745eb856025276ec7d1f.tar.xz |
First step of making user_rooms_intersect() faster - implement in intersection logic in Python code terms of a DB query that is cacheable per user
-rw-r--r-- | synapse/storage/roommember.py | 38 |
1 files changed, 20 insertions, 18 deletions
diff --git a/synapse/storage/roommember.py b/synapse/storage/roommember.py index c69dd995ce..d490a374e5 100644 --- a/synapse/storage/roommember.py +++ b/synapse/storage/roommember.py @@ -240,28 +240,30 @@ class RoomMemberStore(SQLBaseStore): results = self._parse_events_txn(txn, rows) return results + @defer.inlineCallbacks def user_rooms_intersect(self, user_id_list): """ Checks whether all the users whose IDs are given in a list share a room. + + This is a "hot path" function that's called a lot, e.g. by presence for + generating the event stream. """ - def interaction(txn): - user_list_clause = " OR ".join(["m.user_id = ?"] * len(user_id_list)) - sql = ( - "SELECT m.room_id FROM room_memberships as m " - "INNER JOIN current_state_events as c " - "ON m.event_id = c.event_id " - "WHERE m.membership = 'join' " - "AND (%(clause)s) " - # TODO(paul): We've got duplicate rows in the database somewhere - # so we have to DISTINCT m.user_id here - "GROUP BY m.room_id HAVING COUNT(DISTINCT m.user_id) = ?" - ) % {"clause": user_list_clause} - - args = list(user_id_list) - args.append(len(user_id_list)) + if len(user_id_list) < 2: + defer.returnValue(True) - txn.execute(sql, args) + deferreds = [ + self.get_rooms_for_user_where_membership_is( + u, membership_list=[Membership.JOIN], + ) + for u in user_id_list + ] + + results = yield defer.DeferredList(deferreds) + + # A list of sets of strings giving room IDs for each user + room_id_lists = [set([r.room_id for r in result[1]]) for result in results] - return len(txn.fetchall()) > 0 + # There isn't a setintersection(*list_of_sets) + ret = len(room_id_lists.pop(0).intersection(*room_id_lists)) > 0 - return self.runInteraction("user_rooms_intersect", interaction) + defer.returnValue(ret) |