Use Future.delayed in cancellation zones only

This commit is contained in:
Simon Binder 2021-03-31 23:09:23 +02:00
parent 04a8bb5694
commit edb219ecfe
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
4 changed files with 13 additions and 8 deletions

View File

@ -1,7 +1,7 @@
## 4.3.0-dev
- On supported platforms, cancel ongoing stream selects when the stream is disposed
- At the moment, `moor/ffi` on a background isolate supports this feature
- At the moment, `moor/ffi` and isolate databases are supported
## 4.2.1

View File

@ -65,6 +65,9 @@ class CancellationException implements Exception {
}
}
/// Returns true if we're currently in a zone that can be cancelled.
bool get isInCancellationZone => Zone.current[_key] != null;
/// Checks whether the active zone is a cancellation zone that has been
/// cancelled. If it is, a [CancellationException] will be thrown.
void checkIfCancelled() {

View File

@ -22,8 +22,15 @@ mixin _ExecutorWithQueryDelegate on QueryExecutor {
Future<T> _synchronized<T>(Future<T> Function() action) {
if (isSequential) {
return _lock.synchronized(() {
checkIfCancelled();
return _lock.synchronized(() async {
if (isInCancellationZone) {
// Popular sequential database implementations (especially moor/ffi)
// are synchronous. Wait for one event loop iteration to give
// cancellations time to come in.
await Future.delayed(Duration.zero);
checkIfCancelled();
}
return action();
});
} else {

View File

@ -121,11 +121,6 @@ class ServerImplementation implements MoorServer {
Future<dynamic> _runQuery(StatementMethod method, String sql,
List<Object?> args, int? transactionId) async {
// Wait for one event loop iteration until we run the request. This helps
// with cancellations for synchronous database implementations like moor/ffi
// since we don't have a chance to react to cancellation requests otherwise.
await Future.delayed(Duration.zero);
final executor = await _loadExecutor(transactionId);
switch (method) {