6177214e-ce7c-49e3-99de-ff9721b26f63 — Commit 0a45930d

AuthorEdmir Suljic<esu@dwarf.dk>
Date2025-10-27 10:16:12 +0100
Updated db issue

Changed files

comwell_key_app/lib/database/comwell_db.dart       |  46 +++------
 .../overview/repository/overview_repository.dart   |   7 +-
 .../lib/profile/profile_repository.dart            |   7 +-
 comwell_key_app/lib/utils/database_recovery.dart   | 108 ---------------------
 comwell_key_app/lib/utils/locator.dart             |  11 ---
 5 files changed, 16 insertions(+), 163 deletions(-)

Diff

diff --git a/comwell_key_app/lib/database/comwell_db.dart b/comwell_key_app/lib/database/comwell_db.dart
index d7c2d620..0562d61b 100644
--- a/comwell_key_app/lib/database/comwell_db.dart
+++ b/comwell_key_app/lib/database/comwell_db.dart
@@ -21,9 +21,17 @@ part '../.generated/database/comwell_db.g.dart';
final secureStorage = SecureStorage();
-@DriftDatabase(
- tables: [BookingEntity, UserEntity, NotificationPermissionEntity, UpsaleEntity],
- daos: [BookingsDao, UserDAO, NotificationPermissionDAO, UpsalesDAO])
+@DriftDatabase(tables: [
+ BookingEntity,
+ UserEntity,
+ NotificationPermissionEntity,
+ UpsaleEntity
+], daos: [
+ BookingsDao,
+ UserDAO,
+ NotificationPermissionDAO,
+ UpsalesDAO
+])
class ComwellDatabase extends _$ComwellDatabase {
static const String _cipherKey = "sql_cipher";
static const String _dbFileName = "comwell.db.enc";
@@ -37,13 +45,9 @@ class ComwellDatabase extends _$ComwellDatabase {
MigrationStrategy get migration => destructiveFallback;
Future<void> deleteDatabase() async {
- await close();
- final supportDir = await getApplicationSupportDirectory();
- final databaseDir = File(p.join(supportDir.path, _dbFileName));
- final exists = await databaseDir.exists();
- if (exists) {
- await databaseDir.delete();
- }
+ await bookingsDao.delete(bookingEntity).go();
+ await userDAO.delete(userEntity).go();
+ await notificationPermissionDAO.delete(notificationPermissionEntity).go();
}
/// Reset the database singleton in the locator
@@ -51,28 +55,6 @@ class ComwellDatabase extends _$ComwellDatabase {
// This will be called from locator to reset the singleton
}
- /// Force database recreation by deleting and recreating the database file
- static Future<void> forceRecreate() async {
- final supportDir = await getApplicationSupportDirectory();
- final databaseDir = File(p.join(supportDir.path, _dbFileName));
- final exists = await databaseDir.exists();
- if (exists) {
- await databaseDir.delete();
- }
- }
-
- /// Complete database reset including cipher key for corrupted databases
- static Future<void> forceRecreateWithCipherReset() async {
- final supportDir = await getApplicationSupportDirectory();
- final databaseDir = File(p.join(supportDir.path, _dbFileName));
- final exists = await databaseDir.exists();
- if (exists) {
- await databaseDir.delete();
- }
-
- // Clear the corrupted cipher key to force generation of a new one
- await secureStorage.delete(_cipherKey);
- }
static Future<String> getCipher() async {
final cipher = await secureStorage.read(_cipherKey);
diff --git a/comwell_key_app/lib/overview/repository/overview_repository.dart b/comwell_key_app/lib/overview/repository/overview_repository.dart
index f485dddb..0400eebe 100644
--- a/comwell_key_app/lib/overview/repository/overview_repository.dart
+++ b/comwell_key_app/lib/overview/repository/overview_repository.dart
@@ -10,7 +10,6 @@ import 'package:comwell_key_app/services/mappers/booking_mapper.dart';
import 'package:comwell_key_app/services/mappers/bookings_mapper.dart';
import 'package:comwell_key_app/services/models/booking_dto.dart';
import 'package:comwell_key_app/utils/locator.dart';
-import 'package:comwell_key_app/utils/database_recovery.dart';
class OverviewRepository {
final api = Api();
@@ -25,11 +24,7 @@ class OverviewRepository {
final user = await profileRepository.fetchProfileSettings();
final rooms = await chooseShareRoomRepository.getMockRooms();
-
- await DatabaseRecovery.executeWithRecovery(
- () => locator<ComwellDatabase>().bookingsDao.insertBookings(response),
- 'save bookings to database',
- );
+
return response.toBookings(user.id, rooms);
} catch (e) {
diff --git a/comwell_key_app/lib/profile/profile_repository.dart b/comwell_key_app/lib/profile/profile_repository.dart
index 79232ee7..5983ac16 100644
--- a/comwell_key_app/lib/profile/profile_repository.dart
+++ b/comwell_key_app/lib/profile/profile_repository.dart
@@ -8,9 +8,8 @@ import 'package:comwell_key_app/services/mappers/booking_mapper.dart';
import 'package:comwell_key_app/services/mappers/user_mapper.dart';
import 'package:comwell_key_app/services/models/bookings_dto.dart';
import 'package:comwell_key_app/services/models/user_dto.dart';
-import 'package:comwell_key_app/utils/json.dart';
+import 'package:comwell_key_app/utils/json.dart';
import 'package:comwell_key_app/utils/locator.dart';
-import 'package:comwell_key_app/utils/database_recovery.dart';
import 'package:comwell_key_app/utils/secure_storage.dart';
import 'package:comwell_key_app/utils/seos_repository.dart';
import 'package:flutter/material.dart';
@@ -86,10 +85,6 @@ class ProfileRepository {
final userDto = UserDto.fromJson(data);
final user = userDto.toUser();
- await DatabaseRecovery.executeWithRecoverySafe(
- () => locator<ComwellDatabase>().userDAO.saveUser(userDto),
- 'save user to database',
- );
return user;
} catch (e) {
diff --git a/comwell_key_app/lib/utils/database_recovery.dart b/comwell_key_app/lib/utils/database_recovery.dart
deleted file mode 100644
index 53f1be40..00000000
--- a/comwell_key_app/lib/utils/database_recovery.dart
+++ /dev/null
@@ -1,108 +0,0 @@
-import 'package:comwell_key_app/utils/locator.dart';
-
-/// Utility class for handling database corruption recovery
-class DatabaseRecovery {
- /// Executes a database operation with automatic corruption recovery
- ///
- /// This function will automatically detect database corruption errors and
- /// attempt recovery by resetting the database and cipher key if needed.
- ///
- /// [operation] - The database operation to execute
- /// [operationName] - Human-readable name for logging purposes
- ///
- /// Returns the result of the operation or throws an exception if recovery fails
- static Future<T> executeWithRecovery<T>(
- Future<T> Function() operation,
- String operationName,
- ) async {
- try {
- return await operation();
- } catch (dbError) {
- final errorString = dbError.toString();
-
- if (errorString.contains("Can't re-open a database after closing")) {
- // Database connection issue - try regular reset
- try {
- resetDatabase();
- await Future<void>.delayed(const Duration(milliseconds: 100));
- return await operation();
- } catch (retryError) {
- throw Exception('Failed to execute $operationName after database reset: $retryError');
- }
- } else if (errorString.contains("file is not a database") ||
- errorString.contains("SqliteException(26)") ||
- errorString.contains("database disk image is malformed")) {
- // Database corruption - reset with cipher key reset
- try {
- resetDatabaseWithCipherReset();
- await Future<void>.delayed(const Duration(milliseconds: 200));
- return await operation();
- } catch (retryError) {
- throw Exception('Failed to execute $operationName after cipher reset: $retryError');
- }
- } else {
- // Other database errors - retry once with delay
- try {
- await Future<void>.delayed(const Duration(milliseconds: 100));
- return await operation();
- } catch (retryError) {
- throw Exception('Failed to execute $operationName: $retryError');
- }
- }
- }
- }
-
- /// Executes a database operation with automatic corruption recovery (non-throwing version)
- ///
- /// This function will automatically detect database corruption errors and
- /// attempt recovery by resetting the database and cipher key if needed.
- /// If recovery fails, it will log the error and return null instead of throwing.
- ///
- /// [operation] - The database operation to execute
- /// [operationName] - Human-readable name for logging purposes
- ///
- /// Returns the result of the operation or null if recovery fails
- static Future<T?> executeWithRecoverySafe<T>(
- Future<T> Function() operation,
- String operationName,
- ) async {
- try {
- return await operation();
- } catch (dbError) {
- final errorString = dbError.toString();
-
- if (errorString.contains("Can't re-open a database after closing")) {
- // Database connection issue - try regular reset
- try {
- resetDatabase();
- await Future<void>.delayed(const Duration(milliseconds: 100));
- return await operation();
- } catch (retryError) {
- print("Database reset and retry failed for $operationName: $retryError");
- return null;
- }
- } else if (errorString.contains("file is not a database") ||
- errorString.contains("SqliteException(26)") ||
- errorString.contains("database disk image is malformed")) {
- // Database corruption - reset with cipher key reset
- try {
- resetDatabaseWithCipherReset();
- await Future<void>.delayed(const Duration(milliseconds: 200));
- return await operation();
- } catch (retryError) {
- print("Database cipher reset and retry failed for $operationName: $retryError");
- return null;
- }
- } else {
- // Other database errors - retry once with delay
- try {
- await Future<void>.delayed(const Duration(milliseconds: 100));
- return await operation();
- } catch (retryError) {
- print("Database retry failed for $operationName: $retryError");
- return null;
- }
- }
- }
- }
-}
diff --git a/comwell_key_app/lib/utils/locator.dart b/comwell_key_app/lib/utils/locator.dart
index 8c8545c6..091fbde2 100644
--- a/comwell_key_app/lib/utils/locator.dart
+++ b/comwell_key_app/lib/utils/locator.dart
@@ -41,17 +41,6 @@ void resetDatabase() async {
if (locator.isRegistered<ComwellDatabase>()) {
locator.unregister<ComwellDatabase>();
}
- // Force database recreation to ensure new schema is applied
- await ComwellDatabase.forceRecreate();
- registerDatabase();
-}
-
-void resetDatabaseWithCipherReset() async {
- if (locator.isRegistered<ComwellDatabase>()) {
- locator.unregister<ComwellDatabase>();
- }
- // Force database recreation with cipher key reset for corrupted databases
- await ComwellDatabase.forceRecreateWithCipherReset();
registerDatabase();
}