drift icon indicating copy to clipboard operation
drift copied to clipboard

MultiExecutor is not working now.

Open YeungKC opened this issue 2 years ago • 5 comments

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

YeungKC avatar Feb 20 '23 13:02 YeungKC

Thanks for the report! I'll need to investigate this further, do you get a stack trace for the Operation was cancelled errors?

simolus3 avatar Feb 20 '23 21:02 simolus3

I updated demo and stack trace. Please check it.

YeungKC avatar Feb 21 '23 02:02 YeungKC

@simolus3

This is very important to us. Do you have any ideas?

YeungKC avatar Feb 27 '23 07:02 YeungKC

@YeungKC Sorry for the delay! Your example works with b137b4065e5e4b3e6a7eeab844c6c77bdf6ab95b, can you check if that also fixes the problem in your app?

simolus3 avatar Feb 27 '23 16:02 simolus3

@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.

YeungKC avatar Feb 28 '23 03:02 YeungKC

There has been no activity in this issue for over a year and no reproducible bug exists.

dickermoshe avatar Aug 16 '24 16:08 dickermoshe