mirror of https://github.com/AMT-Cheif/drift.git
Warn when a database class isn't used as a singleton
This commit is contained in:
parent
22c692c69e
commit
c0aa88f4d0
|
@ -14,6 +14,8 @@ abstract class TestExecutor {
|
|||
}
|
||||
|
||||
void runAllTests(TestExecutor executor) {
|
||||
moorRuntimeOptions.dontWarnAboutMultipleDatabases = true;
|
||||
|
||||
tearDown(() async {
|
||||
await executor.deleteData();
|
||||
});
|
||||
|
|
|
@ -1,5 +1,14 @@
|
|||
part of 'runtime_api.dart';
|
||||
|
||||
/// Keep track of how many databases have been opened for a given database
|
||||
/// type.
|
||||
/// We get a number of error reports of "moor not generating tables" that have
|
||||
/// their origin in users opening multiple instances of their database. This
|
||||
/// can cause a race conditions when the second [GeneratedDatabase] is opening a
|
||||
/// underlying [DatabaseConnection] that is already opened but doesn't have the
|
||||
/// tables created.
|
||||
Map<Type, int> _openedDbCount = {};
|
||||
|
||||
/// A base class for all generated databases.
|
||||
abstract class GeneratedDatabase extends DatabaseConnectionUser
|
||||
with QueryEngine {
|
||||
|
@ -33,12 +42,38 @@ abstract class GeneratedDatabase extends DatabaseConnectionUser
|
|||
{StreamQueryStore streamStore})
|
||||
: super(types, executor, streamQueries: streamStore) {
|
||||
executor?.databaseInfo = this;
|
||||
assert(_handleInstantiated());
|
||||
}
|
||||
|
||||
/// Used by generated code to connect to a database that is already open.
|
||||
GeneratedDatabase.connect(DatabaseConnection connection)
|
||||
: super.fromConnection(connection) {
|
||||
connection?.executor?.databaseInfo = this;
|
||||
assert(_handleInstantiated());
|
||||
}
|
||||
|
||||
bool _handleInstantiated() {
|
||||
if (!_openedDbCount.containsKey(runtimeType) ||
|
||||
moorRuntimeOptions.dontWarnAboutMultipleDatabases) {
|
||||
_openedDbCount[runtimeType] = 1;
|
||||
return true;
|
||||
}
|
||||
final count = ++_openedDbCount[runtimeType];
|
||||
if (count > 1) {
|
||||
print(
|
||||
'WARNING (moor): It looks like you\'ve created the database '
|
||||
'$runtimeType multiple times. When these two databases use the same '
|
||||
'QueryExecutor, race conditions will ocur and might corrupt the '
|
||||
'database. \n'
|
||||
'Try to follow the advice at https://moor.simonbinder.eu/faq/#using-the-database '
|
||||
'or, if you know what you\'re doing, set moorRuntimeOptions.dontWarnAboutMultipleDatabases = true\n'
|
||||
'Here is the stacktrace from when the database was opened a second '
|
||||
'time:\n${StackTrace.current}\n'
|
||||
'This warning will only appear on debug builds.',
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Creates a [Migrator] with the provided query executor. Migrators generate
|
||||
|
@ -89,5 +124,6 @@ abstract class GeneratedDatabase extends DatabaseConnectionUser
|
|||
/// Closes this database and releases associated resources.
|
||||
Future<void> close() async {
|
||||
await executor.close();
|
||||
_openedDbCount[runtimeType]--;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,3 +9,16 @@ part 'connection.dart';
|
|||
part 'db_base.dart';
|
||||
part 'dao_base.dart';
|
||||
part 'query_engine.dart';
|
||||
|
||||
/// Defines additional runtime behavior for moor. Changing the fields of this
|
||||
/// class is rarely necessary.
|
||||
class MoorRuntimeOptions {
|
||||
/// Don't warn when a database class isn't used as singleton.
|
||||
bool dontWarnAboutMultipleDatabases = false;
|
||||
}
|
||||
|
||||
/// Stores the [MoorRuntimeOptions] describing global moor behavior across
|
||||
/// databases.
|
||||
///
|
||||
/// Note that is is adapting this behavior is rarely needed.
|
||||
MoorRuntimeOptions moorRuntimeOptions = MoorRuntimeOptions();
|
||||
|
|
|
@ -7,7 +7,9 @@ part 'custom_tables.g.dart';
|
|||
queries: {'writeConfig': 'REPLACE INTO config VALUES (:key, :value)'},
|
||||
)
|
||||
class CustomTablesDb extends _$CustomTablesDb {
|
||||
CustomTablesDb(QueryExecutor e) : super(e);
|
||||
CustomTablesDb(QueryExecutor e) : super(e) {
|
||||
moorRuntimeOptions.dontWarnAboutMultipleDatabases = true;
|
||||
}
|
||||
|
||||
@override
|
||||
int get schemaVersion => 1;
|
||||
|
|
|
@ -99,8 +99,12 @@ class CustomConverter extends TypeConverter<MyCustomObject, String> {
|
|||
},
|
||||
)
|
||||
class TodoDb extends _$TodoDb {
|
||||
TodoDb(QueryExecutor e) : super(e);
|
||||
TodoDb.connect(DatabaseConnection connection) : super.connect(connection);
|
||||
TodoDb(QueryExecutor e) : super(e) {
|
||||
moorRuntimeOptions.dontWarnAboutMultipleDatabases = true;
|
||||
}
|
||||
TodoDb.connect(DatabaseConnection connection) : super.connect(connection) {
|
||||
moorRuntimeOptions.dontWarnAboutMultipleDatabases = true;
|
||||
}
|
||||
|
||||
@override
|
||||
MigrationStrategy get migration => MigrationStrategy();
|
||||
|
|
|
@ -32,6 +32,8 @@ class _FakeDb extends GeneratedDatabase {
|
|||
}
|
||||
|
||||
void main() {
|
||||
moorRuntimeOptions.dontWarnAboutMultipleDatabases = true;
|
||||
|
||||
test('status of OpeningDetails', () {
|
||||
expect(const OpeningDetails(null, 1).wasCreated, true);
|
||||
expect(const OpeningDetails(2, 4).wasCreated, false);
|
||||
|
|
Loading…
Reference in New Issue