From 9142dcbeec0d106429df8ab1117d0c4110faf31d Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Wed, 26 Aug 2020 09:38:14 +0200 Subject: [PATCH] fix: Database error handling --- lib/src/client.dart | 8 +-- lib/src/database/database.dart | 118 ++++++++++++++++++++------------- 2 files changed, 75 insertions(+), 51 deletions(-) diff --git a/lib/src/client.dart b/lib/src/client.dart index a01173c..56e6aa8 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -502,7 +502,7 @@ class Client extends MatrixApi { StreamController.broadcast(); /// Synchronization erros are coming here. - final StreamController onSyncError = StreamController.broadcast(); + final StreamController onSyncError = StreamController.broadcast(); /// Synchronization erros are coming here. final StreamController onOlmError = @@ -725,7 +725,7 @@ class Client extends MatrixApi { return; } Logs.error('Error during processing events: ' + e.toString(), s); - onSyncError.add(SyncError( + onSyncError.add(SdkError( exception: e is Exception ? e : Exception(e), stackTrace: s)); await Future.delayed(Duration(seconds: syncErrorTimeoutSec), _sync); } @@ -1478,8 +1478,8 @@ class Client extends MatrixApi { } } -class SyncError { +class SdkError { Exception exception; StackTrace stackTrace; - SyncError({this.exception, this.stackTrace}); + SdkError({this.exception, this.stackTrace}); } diff --git a/lib/src/database/database.dart b/lib/src/database/database.dart index 9ac84df..81dff83 100644 --- a/lib/src/database/database.dart +++ b/lib/src/database/database.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:convert'; import 'package:moor/moor.dart'; @@ -6,6 +7,7 @@ import 'package:olm/olm.dart' as olm; import '../../famedlysdk.dart' as sdk; import '../../matrix_api.dart' as api; import '../../matrix_api.dart'; +import '../client.dart'; import '../room.dart'; import '../utils/logs.dart'; @@ -57,61 +59,83 @@ class Database extends _$Database { int get maxFileSize => 1 * 1024 * 1024; + /// Update errors are coming here. + final StreamController onError = StreamController.broadcast(); + @override MigrationStrategy get migration => MigrationStrategy( - onCreate: (Migrator m) { - return m.createAll(); + onCreate: (Migrator m) async { + try { + await m.createAll(); + } catch (e, s) { + Logs.error(e, s); + onError.add(SdkError(exception: e, stackTrace: s)); + rethrow; + } }, onUpgrade: (Migrator m, int from, int to) async { - // this appears to be only called once, so multiple consecutive upgrades have to be handled appropriately in here - if (from == 1) { - await m.createIndexIfNotExists(userDeviceKeysIndex); - await m.createIndexIfNotExists(userDeviceKeysKeyIndex); - await m.createIndexIfNotExists(olmSessionsIndex); - await m.createIndexIfNotExists(outboundGroupSessionsIndex); - await m.createIndexIfNotExists(inboundGroupSessionsIndex); - await m.createIndexIfNotExists(roomsIndex); - await m.createIndexIfNotExists(eventsIndex); - await m.createIndexIfNotExists(roomStatesIndex); - await m.createIndexIfNotExists(accountDataIndex); - await m.createIndexIfNotExists(roomAccountDataIndex); - await m.createIndexIfNotExists(presencesIndex); - from++; - } - if (from == 2) { - await m.deleteTable('outbound_group_sessions'); - await m.createTable(outboundGroupSessions); - from++; - } - if (from == 3) { - await m.createTableIfNotExists(userCrossSigningKeys); - await m.createTableIfNotExists(ssssCache); - // mark all keys as outdated so that the cross signing keys will be fetched - await m.issueCustomQuery( - 'UPDATE user_device_keys SET outdated = true'); - from++; - } - if (from == 4) { - await m.addColumnIfNotExists(olmSessions, olmSessions.lastReceived); - from++; - } - if (from == 5) { - await m.addColumnIfNotExists( - inboundGroupSessions, inboundGroupSessions.uploaded); - await m.addColumnIfNotExists( - inboundGroupSessions, inboundGroupSessions.senderKey); - await m.addColumnIfNotExists( - inboundGroupSessions, inboundGroupSessions.senderClaimedKeys); - from++; + try { + // this appears to be only called once, so multiple consecutive upgrades have to be handled appropriately in here + if (from == 1) { + await m.createIndexIfNotExists(userDeviceKeysIndex); + await m.createIndexIfNotExists(userDeviceKeysKeyIndex); + await m.createIndexIfNotExists(olmSessionsIndex); + await m.createIndexIfNotExists(outboundGroupSessionsIndex); + await m.createIndexIfNotExists(inboundGroupSessionsIndex); + await m.createIndexIfNotExists(roomsIndex); + await m.createIndexIfNotExists(eventsIndex); + await m.createIndexIfNotExists(roomStatesIndex); + await m.createIndexIfNotExists(accountDataIndex); + await m.createIndexIfNotExists(roomAccountDataIndex); + await m.createIndexIfNotExists(presencesIndex); + from++; + } + if (from == 2) { + await m.deleteTable('outbound_group_sessions'); + await m.createTable(outboundGroupSessions); + from++; + } + if (from == 3) { + await m.createTableIfNotExists(userCrossSigningKeys); + await m.createTableIfNotExists(ssssCache); + // mark all keys as outdated so that the cross signing keys will be fetched + await m.issueCustomQuery( + 'UPDATE user_device_keys SET outdated = true'); + from++; + } + if (from == 4) { + await m.addColumnIfNotExists( + olmSessions, olmSessions.lastReceived); + from++; + } + if (from == 5) { + await m.addColumnIfNotExists( + inboundGroupSessions, inboundGroupSessions.uploaded); + await m.addColumnIfNotExists( + inboundGroupSessions, inboundGroupSessions.senderKey); + await m.addColumnIfNotExists( + inboundGroupSessions, inboundGroupSessions.senderClaimedKeys); + from++; + } + } catch (e, s) { + Logs.error(e, s); + onError.add(SdkError(exception: e, stackTrace: s)); + rethrow; } }, beforeOpen: (_) async { - if (executor.dialect == SqlDialect.sqlite) { - final ret = await customSelect('PRAGMA journal_mode=WAL').get(); - if (ret.isNotEmpty) { - Logs.info('[Moor] Switched database to mode ' + - ret.first.data['journal_mode'].toString()); + try { + if (executor.dialect == SqlDialect.sqlite) { + final ret = await customSelect('PRAGMA journal_mode=WAL').get(); + if (ret.isNotEmpty) { + Logs.info('[Moor] Switched database to mode ' + + ret.first.data['journal_mode'].toString()); + } } + } catch (e, s) { + Logs.error(e, s); + onError.add(SdkError(exception: e, stackTrace: s)); + rethrow; } }, );