fix: Load multiple olm sessions from the database at once for increased performance

This commit is contained in:
Sorunome 2020-12-30 12:47:27 +01:00
parent bbcc883777
commit add19c73a0
No known key found for this signature in database
GPG Key ID: B19471D07FC9BE9C
4 changed files with 53 additions and 31 deletions

View File

@ -358,15 +358,40 @@ class OlmManager {
return res;
}
Future<List<OlmSession>> getOlmSessions(String senderKey) async {
Future<void> getOlmSessionsForDevicesFromDatabase(
List<String> senderKeys) async {
if (client.database == null) {
return;
}
final rows = await client.database
.dbGetOlmSessionsForDevices(client.id, senderKeys)
.get();
final res = <String, List<OlmSession>>{};
for (final row in rows) {
res[row.identityKey] ??= <OlmSession>[];
final sess = OlmSession.fromDb(row, client.userID);
if (sess.isValid) {
res[row.identityKey].add(sess);
}
}
for (final entry in res.entries) {
_olmSessions[entry.key] = entry.value;
}
}
Future<List<OlmSession>> getOlmSessions(String senderKey,
{bool getFromDb = true}) async {
var sess = olmSessions[senderKey];
if (sess == null || sess.isEmpty) {
if ((getFromDb ?? true) && (sess == null || sess.isEmpty)) {
final sessions = await getOlmSessionsFromDatabase(senderKey);
if (sessions.isEmpty) {
return [];
}
sess = _olmSessions[senderKey] = sessions;
}
if (sess == null) {
return [];
}
sess.sort((a, b) => a.lastReceived == b.lastReceived
? a.sessionId.compareTo(b.sessionId)
: b.lastReceived.compareTo(a.lastReceived));
@ -475,8 +500,10 @@ class OlmManager {
}
Future<Map<String, dynamic>> encryptToDeviceMessagePayload(
DeviceKeys device, String type, Map<String, dynamic> payload) async {
final sess = await getOlmSessions(device.curve25519Key);
DeviceKeys device, String type, Map<String, dynamic> payload,
{bool getFromDb}) async {
final sess =
await getOlmSessions(device.curve25519Key, getFromDb: getFromDb);
if (sess.isEmpty) {
throw ('No olm session found for ${device.userId}:${device.deviceId}');
}
@ -509,9 +536,8 @@ class OlmManager {
var data = <String, Map<String, Map<String, dynamic>>>{};
// first check if any of our sessions we want to encrypt for are in the database
if (client.database != null) {
for (final device in deviceKeys) {
await getOlmSessions(device.curve25519Key);
}
await getOlmSessionsForDevicesFromDatabase(
deviceKeys.map((d) => d.curve25519Key).toList());
}
final deviceKeysWithoutSession = List<DeviceKeys>.from(deviceKeys);
deviceKeysWithoutSession.removeWhere((DeviceKeys deviceKeys) =>
@ -526,7 +552,8 @@ class OlmManager {
}
try {
data[device.userId][device.deviceId] =
await encryptToDeviceMessagePayload(device, type, payload);
await encryptToDeviceMessagePayload(device, type, payload,
getFromDb: false);
} catch (e, s) {
Logs().w('[LibOlm] Error encrypting to-device event', e, s);
continue;

View File

@ -2,7 +2,6 @@ import 'dart:async';
import 'dart:convert';
import 'package:moor/moor.dart';
import 'package:olm/olm.dart' as olm;
import '../../famedlysdk.dart' as sdk;
import '../../matrix_api.dart' as api;
@ -197,28 +196,6 @@ class Database extends _$Database {
return res;
}
Future<Map<String, List<olm.Session>>> getOlmSessions(
int clientId, String userId) async {
final raw = await getAllOlmSessions(clientId).get();
if (raw.isEmpty) {
return {};
}
final res = <String, List<olm.Session>>{};
for (final row in raw) {
if (!res.containsKey(row.identityKey)) {
res[row.identityKey] = [];
}
try {
var session = olm.Session();
session.unpickle(userId, row.pickle);
res[row.identityKey].add(session);
} catch (e, s) {
Logs().e('[LibOlm] Could not unpickle olm session', e, s);
}
}
return res;
}
Future<DbOutboundGroupSession> getDbOutboundGroupSession(
int clientId, String roomId) async {
final res = await dbGetOutboundGroupSession(clientId, roomId).get();

View File

@ -6281,6 +6281,23 @@ abstract class _$Database extends GeneratedDatabase {
}).map(olmSessions.mapFromRow);
}
Selectable<DbOlmSessions> dbGetOlmSessionsForDevices(
int client_id, List<String> identity_keys) {
var $arrayStartIndex = 2;
final expandedidentity_keys =
$expandVar($arrayStartIndex, identity_keys.length);
$arrayStartIndex += identity_keys.length;
return customSelect(
'SELECT * FROM olm_sessions WHERE client_id = :client_id AND identity_key IN ($expandedidentity_keys)',
variables: [
Variable.withInt(client_id),
for (var $ in identity_keys) Variable.withString($)
],
readsFrom: {
olmSessions
}).map(olmSessions.mapFromRow);
}
Future<int> storeOlmSession(int client_id, String identitiy_key,
String session_id, String pickle, int last_received) {
return customInsert(

View File

@ -183,6 +183,7 @@ getAllUserDeviceKeysKeys: SELECT * FROM user_device_keys_key WHERE client_id = :
getAllUserCrossSigningKeys: SELECT * FROM user_cross_signing_keys WHERE client_id = :client_id;
getAllOlmSessions: SELECT * FROM olm_sessions WHERE client_id = :client_id;
dbGetOlmSessions: SELECT * FROM olm_sessions WHERE client_id = :client_id AND identity_key = :identity_key;
dbGetOlmSessionsForDevices: SELECT * FROM olm_sessions WHERE client_id = :client_id AND identity_key IN :identity_keys;
storeOlmSession: INSERT OR REPLACE INTO olm_sessions (client_id, identity_key, session_id, pickle, last_received) VALUES (:client_id, :identitiy_key, :session_id, :pickle, :last_received);
getAllOutboundGroupSessions: SELECT * FROM outbound_group_sessions WHERE client_id = :client_id;
dbGetOutboundGroupSession: SELECT * FROM outbound_group_sessions WHERE client_id = :client_id AND room_id = :room_id;