-
Notifications
You must be signed in to change notification settings - Fork 354
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Weird side effects with DriftIsolate.spawn
#2775
Comments
I can reproduce this issue with a very small string ( import 'dart:convert';
import 'dart:io';
import 'dart:isolate';
import 'package:drift/drift.dart';
import 'package:drift/isolate.dart';
import 'package:drift/native.dart';
DatabaseConnection _backgroundConnection() {
return DatabaseConnection(NativeDatabase.memory());
}
class DatabaseImplementation {
@override
Future<DatabaseConnection> openInMemory() async {
return DriftIsolate.spawn(_backgroundConnection)
.then((value) => value.connect());
}
}
class MyDatabase extends GeneratedDatabase {
final Future<String> Function()? onCreateStatements;
MyDatabase.lazy(
Future<QueryExecutor> Function() e, {
this.onCreateStatements,
}) : super(LazyDatabase(e));
@override
Iterable<TableInfo<Table, dynamic>> get allTables => const Iterable.empty();
@override
int get schemaVersion => 1;
@override
MigrationStrategy get migration => MigrationStrategy(
onCreate: (Migrator m) async {
await m.createAll();
if (onCreateStatements != null) {
await onCreateStatements!().then((m.database.connection.runCustom));
}
},
);
}
void main() async {
final file = File('preset_data.sql.gz');
final db = MyDatabase.lazy(
() async => DatabaseImplementation().openInMemory(),
onCreateStatements: () async => file.readAsBytes().then(
(byteData) async =>
Isolate.run(() => utf8.decode(gzip.decode(byteData))),
),
);
print(await db.customSelect('select 1').get());
} Interestingly, using |
Oh wait I know what's going wrong. While a migration is running, the rest of the database is blocked. This is because we only open a database and start the migration in response to the first query, which obviously shouldn't start to run before the migration has completed. But when you're using Using Using final statements = await onCreateStatements!();
m.database.connection.runCustom(statements); works because you're not awaiting |
Thank you a lot @simolus3! Indeed,
And I'am executing thousands at once. But now rethinking it this warning is probably because of the parameter binding (which I'm not using)? |
Yes, it shouldn't be a problem in this case - and |
Today I migrated one of my databases to run in the background with
DriftIsolate.spawn
. This database getting freshly created in memory every app-start and filled with data which is shipped as an asset.To spin up the database I do something like this:
I used to have following initialization:
The migration worked completely fine when using without isolate. However, with isolate the above is completely faulted. There are no exceptions thrown nor any other odds are happening.
The following future will never finish, and I have no explanation why:
await onCreateStatements!().then((m.database.connection.runCustom));
Funny thing is, this is working without problems:
Statements is a string with ~7MB in size, so its pretty huge.
So, now after I fixed this issue, following is messed up:
await (m.database as PresetDatabase).createSearchIndex();
Which is defined as this:
It will return 10 affected rowids, but it should insert ~170k rows.
I also have a fix for that, calling it after database creation like:
Unfortunately I don't have the time today to provide a complete example. I can follow up with that following days if required.
Are there any explanations? I also tested it in release mode since I experienced bugs with isolates in debug in past flutter releases. However, these bugs persist in release as well.
The text was updated successfully, but these errors were encountered: