From f46e76295c0715500c3b924aedbe2fa88e3f4dbe Mon Sep 17 00:00:00 2001 From: Krille Date: Mon, 11 Nov 2024 09:19:49 +0100 Subject: [PATCH] fix: BREAKING! Cache members for encrypted rooms in database This fixes a huge performance leak as for every encrypted room the whole member list is loaded every time you start the client. This also changes the default value of `cache` in this method to if the room is encrypted or not. For encrypted rooms we always want a complete member list locally. --- lib/fake_matrix_api.dart | 53 ++++++++++++++++++++++++++++++++++++---- lib/src/room.dart | 14 ++++++++++- test/room_test.dart | 27 +++++++++++--------- 3 files changed, 76 insertions(+), 18 deletions(-) diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index ff9e2f47..37f3e91e 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -1816,19 +1816,62 @@ class FakeMatrixApi extends BaseClient { '/client/v3/rooms/!localpart%3Aserver.abc/members': (var req) => { 'chunk': [ { + 'type': 'm.room.member', + 'content': {'membership': 'join', 'displayname': 'YOU'}, + 'sender': '@test:fakeServer.notExisting', + 'state_key': '@test:fakeServer.notExisting', + 'room_id': '!localpart%3Aserver.abc', + 'event_id': '§143273582443PhrSn2:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + }, + { + 'type': 'm.room.member', + 'content': { + 'membership': 'join', + 'displayname': 'Alice Margatroid', + }, + 'sender': '@alice:matrix.org', + 'state_key': '@alice:matrix.org', + 'room_id': '!localpart%3Aserver.abc', + 'event_id': '§143273582443PhrSn3:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + }, + { + 'type': 'm.room.member', + 'content': {'membership': 'invite', 'displayname': 'Bob'}, + 'sender': '@bob:example.com', + 'state_key': '@bob:example.com', + 'room_id': '!localpart%3Aserver.abc', + 'event_id': '§143273582443PhrSn4:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + }, + { + 'type': 'm.room.member', + 'content': {'membership': 'invite', 'displayname': 'Charley'}, + 'sender': '@charley:example.org', + 'state_key': '@charley:example.org', + 'room_id': '!localpart%3Aserver.abc', + 'event_id': '§143273582443PhrSn5:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + }, + { + 'type': 'm.room.member', 'content': { 'membership': 'join', 'avatar_url': 'mxc://example.org/SEsfnsuifSDFSSEF', 'displayname': 'Alice Margatroid', }, - 'type': 'm.room.member', - 'event_id': '§143273582443PhrSn:example.org', - 'room_id': '!636q39766251:example.com', 'sender': '@example:example.org', + 'state_key': '@alice:example.org', + 'room_id': '!localpart%3Aserver.abc', + 'event_id': '§143273582443PhrSn6:example.org', 'origin_server_ts': 1432735824653, 'unsigned': {'age': 1234}, - 'state_key': '@alice:example.org', - } + }, ], }, '/client/v3/pushrules/global/content/nocake': (var req) => { diff --git a/lib/src/room.dart b/lib/src/room.dart index f6671cea..10b9db30 100644 --- a/lib/src/room.dart +++ b/lib/src/room.dart @@ -1607,6 +1607,8 @@ class Room { /// [[Membership.join, Membership.invite, Membership.knock]] /// Set [cache] to `false` if you do not want to cache the users in memory /// for this session which is highly recommended for large public rooms. + /// By default users are only cached in encrypted rooms as encrypted rooms + /// need a full member list. Future> requestParticipants([ List membershipFilter = const [ Membership.join, @@ -1614,7 +1616,7 @@ class Room { Membership.knock, ], bool suppressWarning = false, - bool cache = true, + bool? cache, ]) async { if (!participantListComplete || partial) { // we aren't fully loaded, maybe the users are in the database @@ -1633,6 +1635,8 @@ class Room { return getParticipants(membershipFilter); } + cache ??= encrypted; + final memberCount = summary.mJoinedMemberCount; if (!suppressWarning && cache && memberCount != null && memberCount > 100) { Logs().w(''' @@ -1651,6 +1655,14 @@ class Room { if (cache) { for (final user in users) { setState(user); // at *least* cache this in-memory + await client.database?.storeEventUpdate( + EventUpdate( + roomID: id, + type: EventUpdateType.state, + content: user.toJson(), + ), + client, + ); } } diff --git a/test/room_test.dart b/test/room_test.dart index 37c01c9f..9572c5e8 100644 --- a/test/room_test.dart +++ b/test/room_test.dart @@ -657,14 +657,17 @@ void main() { }); test('requestParticipants', () async { - final participants = await room.requestParticipants(); - expect(participants.length, 4); - final user = participants.singleWhere((u) => u.id == '@alice:matrix.org'); - expect(user.id, '@alice:matrix.org'); - expect(user.displayName, 'Alice Margatroid'); - expect(user.membership, Membership.join); - //expect(user.avatarUrl.toString(), 'mxc://example.org/SEsfnsuifSDFSSEF'); - expect(user.room.id, '!localpart:server.abc'); + final oldParticipants = room.getParticipants(); + expect(oldParticipants.length, 4); + room.summary.mJoinedMemberCount = 5; + final fetchedParticipants = await room.requestParticipants( + const [Membership.join, Membership.invite, Membership.knock], + true, + true, + ); + final newParticipants = room.getParticipants(); + expect(oldParticipants.length < newParticipants.length, true); + expect(fetchedParticipants.length, newParticipants.length); }); test('calcEncryptionHealthState', () async { @@ -823,7 +826,7 @@ void main() { test('getParticipants', () async { var userList = room.getParticipants(); - expect(userList.length, 4); + expect(userList.length, 5); // add new user room.setState( Event( @@ -837,8 +840,8 @@ void main() { ), ); userList = room.getParticipants(); - expect(userList.length, 5); - expect(userList[4].displayName, 'alice'); + expect(userList.length, 6); + expect(userList[5].displayName, 'alice'); }); test('addToDirectChat', () async { @@ -1660,7 +1663,7 @@ void main() { matrixToLink = await room.matrixToInviteLink(); expect( matrixToLink.toString(), - 'https://matrix.to/#/!localpart%3Aserver.abc?via=fakeServer.notExisting&via=matrix.org&via=test.abc', + 'https://matrix.to/#/!localpart%3Aserver.abc?via=fakeServer.notExisting&via=matrix.org&via=example.org', ); });