From edb219ecfece6af744ec0dedd17326b46f5fec45 Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Wed, 31 Mar 2021 23:09:23 +0200 Subject: [PATCH] Use Future.delayed in cancellation zones only --- moor/CHANGELOG.md | 2 +- moor/lib/src/runtime/cancellation_zone.dart | 3 +++ moor/lib/src/runtime/executor/helpers/engines.dart | 11 +++++++++-- moor/lib/src/runtime/remote/server_impl.dart | 5 ----- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/moor/CHANGELOG.md b/moor/CHANGELOG.md index c7d46afb..97cd8eea 100644 --- a/moor/CHANGELOG.md +++ b/moor/CHANGELOG.md @@ -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 diff --git a/moor/lib/src/runtime/cancellation_zone.dart b/moor/lib/src/runtime/cancellation_zone.dart index b5996d45..11bea0d8 100644 --- a/moor/lib/src/runtime/cancellation_zone.dart +++ b/moor/lib/src/runtime/cancellation_zone.dart @@ -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() { diff --git a/moor/lib/src/runtime/executor/helpers/engines.dart b/moor/lib/src/runtime/executor/helpers/engines.dart index 0cd47eb8..3bb5c68d 100644 --- a/moor/lib/src/runtime/executor/helpers/engines.dart +++ b/moor/lib/src/runtime/executor/helpers/engines.dart @@ -22,8 +22,15 @@ mixin _ExecutorWithQueryDelegate on QueryExecutor { Future _synchronized(Future 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 { diff --git a/moor/lib/src/runtime/remote/server_impl.dart b/moor/lib/src/runtime/remote/server_impl.dart index 78d5195e..c010bf10 100644 --- a/moor/lib/src/runtime/remote/server_impl.dart +++ b/moor/lib/src/runtime/remote/server_impl.dart @@ -121,11 +121,6 @@ class ServerImplementation implements MoorServer { Future _runQuery(StatementMethod method, String sql, List 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) {