drift
drift copied to clipboard
MultiExecutor is not working now.
I forgot from which version, our app sometimes encounters the error Unhandled Exception: Operation was cancelled, but recently it has become more and more frequent. We finally found out that it was caused by MultiExecutor, but we really need parallel queries (some queries are too slow).
Below is our code for creating the database.
Future<Database> connectToDatabase({
bool fromMainIsolate = false,
}) async {
const writePortName = 'write';
const readPortName = 'read';
final isolates = await Future.wait([
_crateIsolate(
writePortName,
fromMainIsolate: fromMainIsolate,
).then((value) => value.connect()),
...List.generate(
4,
(index) => _crateIsolate(
'$readPortName$index',
fromMainIsolate: fromMainIsolate,
).then((value) => value.connect())),
]);
final executor = isolates[0].withExecutor(MultiExecutor.withReadPool(
reads: isolates.skip(1).toList(),
write: isolates[0],
));
return Database(executor);
}
Future<DriftIsolate> _crateIsolate(
String name, {
bool fromMainIsolate = true,
}) async {
if (fromMainIsolate) {
// Remove port if it exists. to avoid port leak on hot reload.
IsolateNameServer.removePortNameMapping(name);
}
final existedSendPort = IsolateNameServer.lookupPortByName(name);
if (existedSendPort == null) {
assert(fromMainIsolate, 'Isolate should be created from main isolate');
final directory = (await getApplicationDocumentsDirectory()).path;
String path = p.join(directory, 'db.sqlite');
final dbFile = File(path);
final driftIsolate = await DriftIsolate.spawn(
() => LazyDatabase(() => NativeDatabase(dbFile, setup: (rawDb) {
rawDb
..execute('PRAGMA journal_mode=WAL;')
..execute('PRAGMA foreign_keys=ON;')
..execute('PRAGMA synchronous=NORMAL;');
})));
IsolateNameServer.registerPortWithName(driftIsolate.connectPort, name);
return driftIsolate;
} else {
return DriftIsolate.fromConnectPort(existedSendPort, serialize: false);
}
}
stack trace:
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Operation was cancelled
#0 checkIfCancelled (package:drift/src/runtime/cancellation_zone.dart:91:5)
#1 _BaseExecutor._runRequest (package:drift/src/remote/client_impl.dart:87:5)
#2 _BaseExecutor.runSelect (package:drift/src/remote/client_impl.dart:130:26)
#3 DatabaseConnection.runSelect (package:drift/src/runtime/api/connection.dart:108:16)
#4 _QueryExecutorPool._run (package:drift/src/runtime/executor/connection_pool.dart:97:10)
#5 _QueryExecutorPool.runSelect (package:drift/src/runtime/executor/connection_pool.dart:77:5)
#6 _MultiExecutorImpl.runSelect (package:drift/src/runtime/executor/connection_pool.dart:146:26)
#7 SimpleSelectStatement._getRaw.<anonymous closure> (package:drift/src/runtime/query_builder/statements/select/select.dart:68:16)
#8 DatabaseConnectionUser.doWhenOpened.<anonymous closure> (package:drift/src/runtime/api/connection_user.dart:162:64)
#9 _rootRunUnary (dart:async/zone.dart:1406:47)
#10 _CustomZone.runUnary (dart:async/zone.dart:1307:19)
<asynchronous suspension>
#11 NonNullableCancellationExtension.resultOrNullIfCancelled (package:drift/src/runtime/cancellation_zone.dart:62:24)
<asynchronous suspension>
#12 QueryStream.fetchAndEmitData (package:drift/src/runtime/executor/stream_queries.dart:315:20)
<asynchronous suspension>
demo: https://github.com/YeungKC/drift_issue_2323
Thanks for the report! I'll need to investigate this further, do you get a stack trace for the Operation was cancelled errors?
I updated demo and stack trace. Please check it.
@simolus3
This is very important to us. Do you have any ideas?
@YeungKC Sorry for the delay! Your example works with b137b4065e5e4b3e6a7eeab844c6c77bdf6ab95b, can you check if that also fixes the problem in your app?
@simolus3
The commit works fine in the demo without any CancellationException, but it is still occurring in our project which is much more complex.
I am still trying to reproduce it in the demo.
There has been no activity in this issue for over a year and no reproducible bug exists.