refactor: Restructure states box and use dedicated members hive box

More description about this here: https://gitlab.com/famedly/company/frontend/frontend-issue-inbox/-/issues/40
This commit is contained in:
Christian Pauly 2021-07-08 14:39:45 +02:00 committed by Krille Fear
parent 1e45ed1793
commit e86fd7cc07
1 changed files with 57 additions and 27 deletions

View File

@ -18,17 +18,20 @@ import 'package:hive/hive.dart';
/// ///
/// This database does not support file caching! /// This database does not support file caching!
class FamedlySdkHiveDatabase extends DatabaseApi { class FamedlySdkHiveDatabase extends DatabaseApi {
static const int version = 2; static const int version = 3;
final String name; final String name;
Box _clientBox; Box _clientBox;
Box _accountDataBox; Box _accountDataBox;
Box _roomsBox; Box _roomsBox;
Box _toDeviceQueueBox; Box _toDeviceQueueBox;
/// Key is a tuple as MultiKey(roomId, type, stateKey) where stateKey can be /// Key is a tuple as MultiKey(roomId, type) where stateKey can be
/// an empty string. /// an empty string.
LazyBox _roomStateBox; LazyBox _roomStateBox;
/// Key is a tuple as MultiKey(roomId, userId)
LazyBox _roomMembersBox;
/// Key is a tuple as MultiKey(roomId, type) /// Key is a tuple as MultiKey(roomId, type)
LazyBox _roomAccountDataBox; LazyBox _roomAccountDataBox;
LazyBox _inboundGroupSessionsBox; LazyBox _inboundGroupSessionsBox;
@ -58,6 +61,7 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
String get _roomsBoxName => '$name.box.rooms'; String get _roomsBoxName => '$name.box.rooms';
String get _toDeviceQueueBoxName => '$name.box.to_device_queue'; String get _toDeviceQueueBoxName => '$name.box.to_device_queue';
String get _roomStateBoxName => '$name.box.room_states'; String get _roomStateBoxName => '$name.box.room_states';
String get _roomMembersBoxName => '$name.box.room_members';
String get _roomAccountDataBoxName => '$name.box.room_account_data'; String get _roomAccountDataBoxName => '$name.box.room_account_data';
String get _inboundGroupSessionsBoxName => '$name.box.inbound_group_session'; String get _inboundGroupSessionsBoxName => '$name.box.inbound_group_session';
String get _outboundGroupSessionsBoxName => String get _outboundGroupSessionsBoxName =>
@ -85,6 +89,7 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
action(_accountDataBox), action(_accountDataBox),
action(_roomsBox), action(_roomsBox),
action(_roomStateBox), action(_roomStateBox),
action(_roomMembersBox),
action(_toDeviceQueueBox), action(_toDeviceQueueBox),
action(_roomAccountDataBox), action(_roomAccountDataBox),
action(_inboundGroupSessionsBox), action(_inboundGroupSessionsBox),
@ -116,6 +121,10 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
_roomStateBoxName, _roomStateBoxName,
encryptionCipher: encryptionCipher, encryptionCipher: encryptionCipher,
); );
_roomMembersBox = await Hive.openLazyBox(
_roomMembersBoxName,
encryptionCipher: encryptionCipher,
);
_toDeviceQueueBox = await Hive.openBox( _toDeviceQueueBox = await Hive.openBox(
_toDeviceQueueBoxName, _toDeviceQueueBoxName,
encryptionCipher: encryptionCipher, encryptionCipher: encryptionCipher,
@ -197,6 +206,7 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
await _roomsBox.deleteAll(_roomsBox.keys); await _roomsBox.deleteAll(_roomsBox.keys);
await _accountDataBox.deleteAll(_accountDataBox.keys); await _accountDataBox.deleteAll(_accountDataBox.keys);
await _roomStateBox.deleteAll(_roomStateBox.keys); await _roomStateBox.deleteAll(_roomStateBox.keys);
await _roomMembersBox.deleteAll(_roomMembersBox.keys);
await _eventsBox.deleteAll(_eventsBox.keys); await _eventsBox.deleteAll(_eventsBox.keys);
await _timelineFragmentsBox.deleteAll(_timelineFragmentsBox.keys); await _timelineFragmentsBox.deleteAll(_timelineFragmentsBox.keys);
await _outboundGroupSessionsBox.deleteAll(_outboundGroupSessionsBox.keys); await _outboundGroupSessionsBox.deleteAll(_outboundGroupSessionsBox.keys);
@ -236,6 +246,11 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
if (multiKey.parts.first != roomId) continue; if (multiKey.parts.first != roomId) continue;
await _roomStateBox.delete(key); await _roomStateBox.delete(key);
} }
for (final key in _roomMembersBox.keys) {
final multiKey = MultiKey.fromString(key);
if (multiKey.parts.first != roomId) continue;
await _roomMembersBox.delete(key);
}
for (final key in _roomAccountDataBox.keys) { for (final key in _roomAccountDataBox.keys) {
final multiKey = MultiKey.fromString(key); final multiKey = MultiKey.fromString(key);
if (multiKey.parts.first != roomId) continue; if (multiKey.parts.first != roomId) continue;
@ -405,8 +420,8 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
} }
// Load members // Load members
for (final userId in membersToPostload) { for (final userId in membersToPostload) {
final state = await _roomStateBox final state =
.get(MultiKey(room.id, EventTypes.RoomMember, userId).toString()); await _roomMembersBox.get(MultiKey(room.id, userId).toString());
if (state == null) { if (state == null) {
Logs().w('Unable to post load member $userId'); Logs().w('Unable to post load member $userId');
continue; continue;
@ -417,10 +432,15 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
// Get the "important" room states. All other states will be loaded once // Get the "important" room states. All other states will be loaded once
// `getUnimportantRoomStates()` is called. // `getUnimportantRoomStates()` is called.
for (final type in importantRoomStates) { for (final type in importantRoomStates) {
final state = final Map states =
await _roomStateBox.get(MultiKey(room.id, type, '').toString()); await _roomStateBox.get(MultiKey(room.id, type).toString());
if (state == null) continue; if (states == null) continue;
room.setState(Event.fromJson(convertToJson(state), room)); final stateEvents = states.values
.map((raw) => Event.fromJson(convertToJson(raw), room))
.toList();
for (final state in stateEvents) {
room.setState(state);
}
} }
// Add to the list and continue. // Add to the list and continue.
@ -467,18 +487,20 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
final tuple = MultiKey.fromString(key); final tuple = MultiKey.fromString(key);
return tuple.parts.first == room.id && !events.contains(tuple.parts[1]); return tuple.parts.first == room.id && !events.contains(tuple.parts[1]);
}); });
return await Future.wait(
keys.map( final unimportantEvents = <Event>[];
(key) async => for (final key in keys) {
Event.fromJson(convertToJson(await _roomStateBox.get(key)), room), final Map states = await _roomStateBox.get(key);
), unimportantEvents.addAll(
); states.values.map((raw) => Event.fromJson(convertToJson(raw), room)));
}
return unimportantEvents;
} }
@override @override
Future<User> getUser(int clientId, String userId, Room room) async { Future<User> getUser(int clientId, String userId, Room room) async {
final state = await _roomStateBox final state =
.get(MultiKey(room.id, EventTypes.RoomMember, userId).toString()); await _roomMembersBox.get(MultiKey(room.id, userId).toString());
if (state == null) return null; if (state == null) return null;
return Event.fromJson(convertToJson(state), room).asUser; return Event.fromJson(convertToJson(state), room).asUser;
} }
@ -518,11 +540,10 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
@override @override
Future<List<User>> getUsers(int clientId, Room room) async { Future<List<User>> getUsers(int clientId, Room room) async {
final users = <User>[]; final users = <User>[];
for (final key in _roomStateBox.keys) { for (final key in _roomMembersBox.keys) {
final statesKey = MultiKey.fromString(key); final statesKey = MultiKey.fromString(key);
if (statesKey.parts[0] != room.id || if (statesKey.parts[0] != room.id) continue;
statesKey.parts[1] != EventTypes.RoomMember) continue; final state = await _roomMembersBox.get(key);
final state = await _roomStateBox.get(key);
users.add(Event.fromJson(convertToJson(state), room).asUser); users.add(Event.fromJson(convertToJson(state), room).asUser);
} }
return users; return users;
@ -798,13 +819,22 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
// Store a common state event // Store a common state event
if ({EventUpdateType.timeline, EventUpdateType.state} if ({EventUpdateType.timeline, EventUpdateType.state}
.contains(eventUpdate.type)) { .contains(eventUpdate.type)) {
await _roomStateBox.put( if (eventUpdate.content['type'] == EventTypes.RoomMember) {
await _roomMembersBox.put(
MultiKey( MultiKey(
eventUpdate.roomID, eventUpdate.roomID,
eventUpdate.content['type'], eventUpdate.content['state_key'],
eventUpdate.content['state_key'] ?? '',
).toString(), ).toString(),
eventUpdate.content); eventUpdate.content);
} else {
final key = MultiKey(
eventUpdate.roomID,
eventUpdate.content['type'],
).toString();
final Map stateMap = await _roomStateBox.get(key) ?? {};
stateMap[eventUpdate.content['state_key']] = eventUpdate.content;
await _roomStateBox.put(key, stateMap);
}
} }
// Store a room account data event // Store a room account data event