Skip to content

Commit ea5c6b3

Browse files
committed
Improve code
1 parent f702026 commit ea5c6b3

File tree

5 files changed

+260
-174
lines changed

5 files changed

+260
-174
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import 'package:flutter/foundation.dart' show kIsWeb;
2+
3+
import '../core/log.dart';
4+
import '../model/local_db_error_model.dart';
5+
import '../utils/system_utils.dart';
6+
import 'package:result_controller/result_controller.dart';
7+
import 'database_interface.dart';
8+
import 'database_mock.dart';
9+
import 'database_native.dart';
10+
import 'database_web_import.dart';
11+
12+
/// Elegant database manager that handles connections on-demand
13+
/// without singleton pattern complexity
14+
class DatabaseManager {
15+
static String? _currentDatabaseName;
16+
17+
/// Connect to or create database with given name (safe Result-based version)
18+
static Future<Result<DatabaseInterface, ErrorLocalDb>> _safeGetConnection(String databaseName) async {
19+
_currentDatabaseName = databaseName;
20+
21+
final DatabaseInterface database = _createDatabaseInstance();
22+
23+
// Use Result-based initialization if available
24+
await database.initialize(databaseName);
25+
26+
Log.i('✅ Connected to database: $databaseName on ${database.platformName}');
27+
return Ok(database);
28+
}
29+
30+
/// Factory method to create appropriate database instance
31+
static DatabaseInterface _createDatabaseInstance() {
32+
if (SystemUtils.isTest) {
33+
return DatabaseMock();
34+
}
35+
36+
if (kIsWeb) {
37+
return DatabaseWeb.instance;
38+
}
39+
40+
return DatabaseNative();
41+
}
42+
43+
/// Execute a database operation with automatic connection management
44+
static Future<Result<T, ErrorLocalDb>> execute<T>(
45+
String databaseName,
46+
Future<Result<T, ErrorLocalDb>> Function(DatabaseInterface db) operation,
47+
) async {
48+
final connectionResult = await _safeGetConnection(databaseName);
49+
50+
return connectionResult.when(
51+
ok: (db) async {
52+
final operationResult = await operation(db);
53+
await db.closeDatabase();
54+
return operationResult;
55+
},
56+
err: (error) => Err(error),
57+
);
58+
}
59+
60+
/// Get current database name (useful for debugging)
61+
static String? get currentDatabaseName => _currentDatabaseName;
62+
63+
/// Check if database exists on disk
64+
static Future<bool> databaseExists(String databaseName) async {
65+
if (kIsWeb) {
66+
// For web, we can't check file existence, assume it exists if we have a name stored
67+
return _currentDatabaseName == databaseName;
68+
}
69+
70+
try {
71+
// For native platforms, check if database file exists
72+
final db = DatabaseNative();
73+
return await db.ensureConnectionValid();
74+
} catch (e) {
75+
return false;
76+
}
77+
}
78+
}

lib/src/database/database_mock.dart

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@ import 'database_interface.dart';
2121
/// - Data validation and sanitization
2222
/// - Thread-safe operations
2323
class DatabaseMock implements DatabaseInterface {
24-
DatabaseMock._();
25-
26-
static final DatabaseMock instance = DatabaseMock._();
2724

2825
// In-memory storage
2926
final Map<String, LocalDbModel> _storage = {};

lib/src/database/database_native.dart

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ class DatabaseConnection {
4343
class ConnectionPool {
4444
static final Map<String, DatabaseConnection> _connections = {};
4545
static int _currentGeneration = 1;
46+
// Persist the last used database name across hot restarts
47+
static String? _lastUsedDatabaseName;
4648

4749
static DatabaseConnection? getConnection(String dbName) {
4850
final connection = _connections[dbName];
@@ -55,6 +57,7 @@ class ConnectionPool {
5557

5658
static void storeConnection(String dbName, DatabaseConnection connection) {
5759
_connections[dbName] = connection;
60+
_lastUsedDatabaseName = dbName; // Remember the last used database name
5861
}
5962

6063
static void invalidateConnection(String dbName) {
@@ -78,6 +81,9 @@ class ConnectionPool {
7881
static void incrementGeneration() => _currentGeneration++;
7982

8083
static int get connectionCount => _connections.length;
84+
85+
// Getter for last used database name (survives hot restart)
86+
static String? get lastUsedDatabaseName => _lastUsedDatabaseName;
8187
}
8288

8389
/// Typedef for the rust functions
@@ -93,9 +99,6 @@ typedef PointerListFFICallBack = Pointer<Utf8> Function(Pointer<AppDbState>);
9399
/// Native database implementation using FFI and Rust backend
94100
/// This implementation is used for mobile and desktop platforms
95101
class DatabaseNative implements DatabaseInterface {
96-
DatabaseNative._();
97-
98-
static final DatabaseNative instance = DatabaseNative._();
99102

100103
Result<DynamicLibrary, String>? _lib;
101104
Pointer<AppDbState>? _dbInstance;
@@ -411,13 +414,25 @@ class DatabaseNative implements DatabaseInterface {
411414
}
412415
}
413416

414-
if (_dbInstance == null || _dbInstance == nullptr) {
415-
Log.w(
416-
'Database connection invalid (null pointer), attempting to reinitialize...',
417-
);
417+
// Check if we have a database name stored (indicates previous initialization)
418+
final dbNameToRestore = _lastDatabaseName ?? ConnectionPool.lastUsedDatabaseName;
419+
if (dbNameToRestore != null && (_dbInstance == null || _dbInstance == nullptr)) {
420+
Log.i('🔄 Hot restart detected - attempting to reconnect to existing database: $dbNameToRestore');
421+
422+
// Restore the database name for the instance
423+
if (_lastDatabaseName == null) {
424+
_lastDatabaseName = dbNameToRestore;
425+
Log.i('🔄 Restored database name from connection pool: $dbNameToRestore');
426+
}
427+
418428
return await _attemptReinitialization();
419429
}
420430

431+
if (_dbInstance == null || _dbInstance == nullptr) {
432+
Log.w('Database connection invalid (null pointer), no previous database name stored');
433+
return false;
434+
}
435+
421436
// Check connection pool first
422437
if (_lastDatabaseName != null) {
423438
final poolConnection = ConnectionPool.getConnection(_lastDatabaseName!);

0 commit comments

Comments
 (0)