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);
|
final statement = CustomSelectStatement(query, variables, tables, this);
|
||||||
return createStream(statement.constructFetcher());
|
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.
|
/// A base class for all generated databases.
|
||||||
|
@ -183,30 +209,4 @@ abstract class GeneratedDatabase extends DatabaseConnectionUser
|
||||||
final migrator = _createMigrator(executor);
|
final migrator = _createMigrator(executor);
|
||||||
return migration.onUpgrade(migrator, from, to);
|
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();
|
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
|
/// Stream query store that doesn't allow creating new streams and dispatches
|
||||||
|
|
|
@ -24,6 +24,16 @@ void main() {
|
||||||
verify(executor.transactions.send());
|
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 {
|
test('transactions notify about table udpates after completing', () async {
|
||||||
when(executor.transactions.runUpdate(any, any))
|
when(executor.transactions.runUpdate(any, any))
|
||||||
.thenAnswer((_) => Future.value(2));
|
.thenAnswer((_) => Future.value(2));
|
||||||
|
|
Loading…
Reference in New Issue