mirror of https://github.com/AMT-Cheif/drift.git
Allow transactions in DAOs
This commit is contained in:
parent
2e808c6ead
commit
f3a0f5f230
|
@ -139,6 +139,32 @@ mixin QueryEngine on DatabaseConnectionUser {
|
|||
final statement = CustomSelectStatement(query, variables, tables, this);
|
||||
return createStream(statement.constructFetcher());
|
||||
}
|
||||
|
||||
/// Executes [action] in a transaction, which means that all its queries and
|
||||
/// updates will be called atomically.
|
||||
///
|
||||
/// Please be aware of the following limitations of transactions:
|
||||
/// 1. Inside a transaction, auto-updating streams cannot be created. This
|
||||
/// operation will throw at runtime. The reason behind this is that a
|
||||
/// stream might have a longer lifespan than a transaction, but it still
|
||||
/// needs to know about the transaction because the data in a transaction
|
||||
/// might be different than that of the "global" database instance.
|
||||
/// 2. Nested transactions are not supported. Calling
|
||||
/// [GeneratedDatabase.transaction] on the [QueryEngine] passed to the [action]
|
||||
/// will throw.
|
||||
/// 3. The code inside [action] must not call any method of this
|
||||
/// [GeneratedDatabase]. Doing so will cause a dead-lock. Instead, all
|
||||
/// queries and updates must be sent to the [QueryEngine] passed to the
|
||||
/// [action] function.
|
||||
Future transaction(Future Function(QueryEngine transaction) action) async {
|
||||
final transaction = Transaction(this, executor.beginTransaction());
|
||||
|
||||
try {
|
||||
await action(transaction);
|
||||
} finally {
|
||||
await transaction.complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A base class for all generated databases.
|
||||
|
@ -183,30 +209,4 @@ abstract class GeneratedDatabase extends DatabaseConnectionUser
|
|||
final migrator = _createMigrator(executor);
|
||||
return migration.onUpgrade(migrator, from, to);
|
||||
}
|
||||
|
||||
/// Executes [action] in a transaction, which means that all its queries and
|
||||
/// updates will be called atomically.
|
||||
///
|
||||
/// Please be aware of the following limitations of transactions:
|
||||
/// 1. Inside a transaction, auto-updating streams cannot be created. This
|
||||
/// operation will throw at runtime. The reason behind this is that a
|
||||
/// stream might have a longer lifespan than a transaction, but it still
|
||||
/// needs to know about the transaction because the data in a transaction
|
||||
/// might be different than that of the "global" database instance.
|
||||
/// 2. Nested transactions are not supported. Calling
|
||||
/// [GeneratedDatabase.transaction] on the [QueryEngine] passed to the [action]
|
||||
/// will throw.
|
||||
/// 3. The code inside [action] must not call any method of this
|
||||
/// [GeneratedDatabase]. Doing so will cause a dead-lock. Instead, all
|
||||
/// queries and updates must be sent to the [QueryEngine] passed to the
|
||||
/// [action] function.
|
||||
Future transaction(Future Function(QueryEngine transaction) action) async {
|
||||
final transaction = Transaction(this, executor.beginTransaction());
|
||||
|
||||
try {
|
||||
await action(transaction);
|
||||
} finally {
|
||||
await transaction.complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,12 @@ class Transaction extends DatabaseConnectionUser with QueryEngine {
|
|||
|
||||
await streams.dispatchUpdates();
|
||||
}
|
||||
|
||||
@override
|
||||
Future transaction(Function action) async {
|
||||
throw StateError('Tried to call transaction() in a transaction. This is'
|
||||
'not supported');
|
||||
}
|
||||
}
|
||||
|
||||
/// Stream query store that doesn't allow creating new streams and dispatches
|
||||
|
|
|
@ -24,6 +24,16 @@ void main() {
|
|||
verify(executor.transactions.send());
|
||||
});
|
||||
|
||||
test('transactions cannot be nested', () {
|
||||
expect(() async {
|
||||
await db.transaction((t) async {
|
||||
await t.transaction((t2) {
|
||||
fail('nested transactions were allowed');
|
||||
});
|
||||
});
|
||||
}, throwsStateError);
|
||||
});
|
||||
|
||||
test('transactions notify about table udpates after completing', () async {
|
||||
when(executor.transactions.runUpdate(any, any))
|
||||
.thenAnswer((_) => Future.value(2));
|
||||
|
|
Loading…
Reference in New Issue