Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Expose whether a room is a space in the Admin API #11934

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/11934.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Expose the `type` property of a room in the _List Room_ and _Room Details_ API.
34 changes: 28 additions & 6 deletions synapse/storage/databases/main/room.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# 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.

import json
import logging
from abc import abstractmethod
from enum import Enum
Expand Down Expand Up @@ -162,16 +162,18 @@ def get_room_with_stats_txn(
txn: LoggingTransaction, room_id: str
) -> Optional[Dict[str, Any]]:
sql = """
SELECT room_id, state.name, state.canonical_alias, curr.joined_members,
SELECT rooms.room_id, state.name, state.canonical_alias, curr.joined_members,
curr.local_users_in_room AS joined_local_members, rooms.room_version AS version,
rooms.creator, state.encryption, state.is_federatable AS federatable,
rooms.is_public AS public, state.join_rules, state.guest_access,
state.history_visibility, curr.current_state_events AS state_events,
state.avatar, state.topic
state.avatar, state.topic, json.json
FROM rooms
INNER JOIN event_json json USING (room_id)
INNER JOIN state_events events USING (event_id)
LEFT JOIN room_stats_state state USING (room_id)
LEFT JOIN room_stats_current curr USING (room_id)
WHERE room_id = ?
WHERE rooms.room_id = ? AND events.type = 'm.room.create'
"""
txn.execute(sql, [room_id])
# Catch error if sql returns empty result to return "None" instead of an error
Expand All @@ -182,12 +184,23 @@ def get_room_with_stats_txn(

res["federatable"] = bool(res["federatable"])
res["public"] = bool(res["public"])
res["type"] = self._get_type_from_event_json(res["json"])
del res["json"]
return res

return await self.db_pool.runInteraction(
"get_room_with_stats", get_room_with_stats_txn, room_id
)

def _get_type_from_event_json(self, event_json_str: Optional[str]) -> Optional[str]:
type_ = None
if event_json_str:
event_json = json.loads(event_json_str)
content = event_json.get("content")
if content:
type_ = content.get("type")
return type_

async def get_public_room_ids(self) -> List[str]:
return await self.db_pool.simple_select_onecol(
table="rooms",
Expand Down Expand Up @@ -540,23 +553,31 @@ async def get_rooms_paginate(
# Flip the boolean
order_by_asc = not order_by_asc

if where_statement:
info_where_statement = where_statement + " AND events.type='m.room.create'"
else:
info_where_statement = "WHERE events.type='m.room.create'"

# Create one query for getting the limited number of events that the user asked
# for, and another query for getting the total number of events that could be
# returned. Thus allowing us to see if there are more events to paginate through
info_sql = """
SELECT state.room_id, state.name, state.canonical_alias, curr.joined_members,
curr.local_users_in_room, rooms.room_version, rooms.creator,
state.encryption, state.is_federatable, rooms.is_public, state.join_rules,
state.guest_access, state.history_visibility, curr.current_state_events
state.guest_access, state.history_visibility, curr.current_state_events,
json.json
FROM room_stats_state state
INNER JOIN room_stats_current curr USING (room_id)
INNER JOIN rooms USING (room_id)
INNER JOIN event_json json USING (room_id)
INNER JOIN state_events events USING (event_id)
Comment on lines +573 to +574
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a comparison of costs on my small database for get_rooms_paginate.
It seems to be a big growth. I think we need some discussion to this: #11904 (comment)

explain
SELECT state.room_id, state.name, state.canonical_alias, curr.joined_members,
  curr.local_users_in_room, rooms.room_version, rooms.creator,
  state.encryption, state.is_federatable, rooms.is_public, state.join_rules,
  state.guest_access, state.history_visibility, curr.current_state_events
FROM room_stats_state state
INNER JOIN room_stats_current curr USING (room_id)
INNER JOIN rooms USING (room_id);
                                      QUERY PLAN
--------------------------------------------------------------------------------------
 Hash Join  (cost=11.31..16.20 rows=112 width=218)
   Hash Cond: (state.room_id = curr.room_id)
   ->  Hash Join  (cost=5.57..10.14 rows=114 width=262)
         Hash Cond: (state.room_id = rooms.room_id)
         ->  Seq Scan on room_stats_state state  (cost=0.00..4.24 rows=124 width=159)
         ->  Hash  (cost=4.14..4.14 rows=114 width=103)
               ->  Seq Scan on rooms  (cost=0.00..4.14 rows=114 width=103)
   ->  Hash  (cost=4.22..4.22 rows=122 width=67)
         ->  Seq Scan on room_stats_current curr  (cost=0.00..4.22 rows=122 width=67)
explain
SELECT state.room_id, state.name, state.canonical_alias, curr.joined_members,
  curr.local_users_in_room, rooms.room_version, rooms.creator,
  state.encryption, state.is_federatable, rooms.is_public, state.join_rules,
  state.guest_access, state.history_visibility, curr.current_state_events,
  json.json
FROM room_stats_state state
INNER JOIN room_stats_current curr USING (room_id)
INNER JOIN rooms USING (room_id)
INNER JOIN event_json json USING (room_id)
INNER JOIN state_events events USING (event_id);
                                              QUERY PLAN
-------------------------------------------------------------------------------------------------------
 Hash Join  (cost=639.49..5749.86 rows=8125 width=1289)
   Hash Cond: (state.room_id = curr.room_id)
   ->  Hash Join  (cost=633.74..5721.66 rows=8270 width=1389)
         Hash Cond: (state.room_id = rooms.room_id)
         ->  Hash Join  (cost=628.18..5691.67 rows=8995 width=1286)
               Hash Cond: (json.room_id = state.room_id)
               ->  Hash Join  (cost=622.39..5661.45 rows=8995 width=1127)
                     Hash Cond: (json.event_id = events.event_id)
                     ->  Seq Scan on event_json json  (cost=0.00..4982.49 rows=21549 width=1172)
                     ->  Hash  (cost=509.95..509.95 rows=8995 width=45)
                           ->  Seq Scan on state_events events  (cost=0.00..509.95 rows=8995 width=45)
               ->  Hash  (cost=4.24..4.24 rows=124 width=159)
                     ->  Seq Scan on room_stats_state state  (cost=0.00..4.24 rows=124 width=159)
         ->  Hash  (cost=4.14..4.14 rows=114 width=103)
               ->  Seq Scan on rooms  (cost=0.00..4.14 rows=114 width=103)
   ->  Hash  (cost=4.22..4.22 rows=122 width=67)
         ->  Seq Scan on room_stats_current curr  (cost=0.00..4.22 rows=122 width=67)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dklimpel I guess, one should more efficiently store the room type when the room is created. However, I did not dare such a big change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, this would not be downwards compatible

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it is possible to do this downwards compatible. But then it is not a "good first issue".
You need:

  • a database update to extend the table with a new column
  • update the function, which writes new rooms to database
  • a background job to update database for all existing / old rooms

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, maybe I will do so in a month or so. I am a student and currently we have exam phase.

{where}
ORDER BY {order_by} {direction}, state.room_id {direction}
LIMIT ?
OFFSET ?
""".format(
where=where_statement,
where=info_where_statement,
order_by=order_by_column,
direction="ASC" if order_by_asc else "DESC",
)
Expand Down Expand Up @@ -597,6 +618,7 @@ def _get_rooms_paginate_txn(
"guest_access": room[11],
"history_visibility": room[12],
"state_events": room[13],
"type": self._get_type_from_event_json(room[14]),
}
)

Expand Down