feat: Make waiting on init db optional

This can improve the start-up time of apps.
The three big db reads on init are
loading account data, rooms and
device keys.
This makes it now possible to let
them run parallel
(while it may depend on platform
if this has any effect)
and the init() method can skip
awaiting them. They will
be at least awaited before handling
the first received sync.
So the app can already display the
room list before device keys are
loaded and request the first sync
from the server before anything
else is loaded from the DB.
This commit is contained in:
Krille Fear 2021-11-09 12:37:44 +01:00
parent e61faec722
commit 475e810523
2 changed files with 27 additions and 3 deletions

View File

@ -893,6 +893,10 @@ class Client extends MatrixApi {
/// If one of [newToken], [newUserID], [newDeviceID], [newDeviceName] is set then /// If one of [newToken], [newUserID], [newDeviceID], [newDeviceName] is set then
/// all of them must be set! If you don't set them, this method will try to /// all of them must be set! If you don't set them, this method will try to
/// get them from the database. /// get them from the database.
///
/// Set [waitForFirstSync] and [waitUntilLoadCompletedLoaded] to false to speed this
/// up. You can then wait for `roomsLoading`, `accountDataLoading` and
/// `userDeviceKeysLoading` where it is necessary.
Future<void> init({ Future<void> init({
String? newToken, String? newToken,
Uri? newHomeserver, Uri? newHomeserver,
@ -901,6 +905,7 @@ class Client extends MatrixApi {
String? newDeviceID, String? newDeviceID,
String? newOlmAccount, String? newOlmAccount,
bool waitForFirstSync = true, bool waitForFirstSync = true,
bool waitUntilLoadCompletedLoaded = true,
}) async { }) async {
if ((newToken != null || if ((newToken != null ||
newUserID != null || newUserID != null ||
@ -1012,11 +1017,22 @@ class Client extends MatrixApi {
encryption?.pickledOlmAccount, encryption?.pickledOlmAccount,
); );
} }
_userDeviceKeys = await database.getUserDeviceKeys(this); userDeviceKeysLoading = database
_rooms = await database.getRoomList(this); .getUserDeviceKeys(this)
.then((keys) => _userDeviceKeys = keys);
roomsLoading = database.getRoomList(this).then((rooms) {
_rooms = rooms;
_sortRooms(); _sortRooms();
accountData = await database.getAccountData(); });
_sortRooms();
accountDataLoading =
database.getAccountData().then((data) => accountData = data);
presences.clear(); presences.clear();
if (waitUntilLoadCompletedLoaded) {
await userDeviceKeysLoading;
await roomsLoading;
await accountDataLoading;
}
} }
_initLock = false; _initLock = false;
_loginState = LoginState.loggedIn; _loginState = LoginState.loggedIn;
@ -1154,6 +1170,9 @@ class Client extends MatrixApi {
final database = this.database; final database = this.database;
if (database != null) { if (database != null) {
await userDeviceKeysLoading;
await roomsLoading;
await accountDataLoading;
_currentTransaction = database.transaction(() async { _currentTransaction = database.transaction(() async {
await _handleSync(syncResp); await _handleSync(syncResp);
if (prevBatch != syncResp.nextBatch) { if (prevBatch != syncResp.nextBatch) {
@ -1648,6 +1667,10 @@ class Client extends MatrixApi {
_sortLock = false; _sortLock = false;
} }
Future? userDeviceKeysLoading;
Future? roomsLoading;
Future? accountDataLoading;
/// A map of known device keys per user. /// A map of known device keys per user.
Map<String, DeviceKeysList> get userDeviceKeys => _userDeviceKeys; Map<String, DeviceKeysList> get userDeviceKeys => _userDeviceKeys;
Map<String, DeviceKeysList> _userDeviceKeys = {}; Map<String, DeviceKeysList> _userDeviceKeys = {};

View File

@ -1882,6 +1882,7 @@ class Room {
/// Returns all known device keys for all participants in this room. /// Returns all known device keys for all participants in this room.
Future<List<DeviceKeys>> getUserDeviceKeys() async { Future<List<DeviceKeys>> getUserDeviceKeys() async {
await client.userDeviceKeysLoading;
final deviceKeys = <DeviceKeys>[]; final deviceKeys = <DeviceKeys>[];
final users = await requestParticipants(); final users = await requestParticipants();
for (final user in users) { for (final user in users) {