fix: Load multiple olm sessions from the database at once for increased performance
This commit is contained in:
parent
bbcc883777
commit
add19c73a0
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue