Open paldepind opened 9 months ago
Can you try to use an explicit drift isolate and pass isolateDebugLog: true
to connect()
? Having those logs would be very useful to narrow this down.
The QueryStream.fetchAndEmitData
in the stack trace seems suspicious, is it possible that there is a stream query being listened to at that point?
Thanks a lot for the response. I really appreciate it.
The
QueryStream.fetchAndEmitData
in the stack trace seems suspicious, is it possible that there is a stream query being listened to at that point?
My app uses stream queries that execute when the app is opened. But I'm surprised if they seem to be running concurrently with the code in beforeOpen
as I would expect that to run before any queries.
Can you try to use an explicit drift isolate and pass
isolateDebugLog: true
toconnect()
? Having those logs would be very useful to narrow this down.
I tried to do that. It made the error go away and all the deletes went through immediately. Below are the changes that I made to my code, based on the docs that you linked to. Of course it's nice that the deletes no go through, but still, I would have expected the original code to work as well.
class MyDatabase extends _$MyDatabase {
- MyDatabase() : super(_openConnection());
+ MyDatabase([QueryExecutor? executor]) : super(executor ?? _openConnection());
- var db = MyDatabase();
+ final db = MyDatabase(
+ DatabaseConnection.delayed(Future.sync(() async {
+ final isolate = await createIsolateWithSpawn();
+ return isolate.connect(singleClientMode: true, isolateDebugLog: true);
+ })),
+ );
+Future<DriftIsolate> createIsolateWithSpawn() async {
+ final token = RootIsolateToken.instance!;
+ return await DriftIsolate.spawn(() {
+ BackgroundIsolateBinaryMessenger.ensureInitialized(token);
+ return LazyDatabase(() async {
+ final dbFolder = await getApplicationDocumentsDirectory();
+ final file = File(p.join(dbFolder.path, 'my-app-database.sqlite'));
+ return NativeDatabase(file);
+ });
+ });
+}
Here is the log output I got after isolateDebugLog: true
. But since the error did not occur with this I suspect that the log is not terribly useful.
Thanks for providing the details! But the log output looks just like what I would expect it to look like, nothing stands out unfortunately.
I would have expected the original code to work as well.
Yeah, me too. And _openConnection()
has just been using path provider + NativeDatabase.createInBackground
before or has there been some custom setup in there?
Yes, my _openConnection
is very normal I think:
LazyDatabase _openConnection() {
// the LazyDatabase util lets us find the right location for the file async.
return LazyDatabase(() async {
// put the database file, called db.sqlite here, into the documents folder
// for your app.
final dbFolder = await getApplicationDocumentsDirectory();
final file = File(p.join(dbFolder.path, 'deep-time-database.sqlite'));
return NativeDatabase.createInBackground(file);
});
}
Based on your comment above I removed a stream query that is initiated on the first page of my app. With this query removed all the deletes (the original code without explicit isolate creation) go through without errors. So it seems to be related to the stream query running in parallel with the code in beforeOpen
. Is guess this should not happen as queries should wait till the beforeOpen
is done?
I think I'm beginning to form a theory for this, but I couldn't reproduce this yet.
Is guess this should not happen as queries should wait till the
beforeOpen
is done?
Definitely! Stream queries have a mechanism to cancel pending work it goes stale or if there aren't any subscriptions left. I wonder if this could have happened because listening to the stream is what caused the database to be opened, but then the subscription got cancelled before the database is fully open. That still shouldn't interfere with other statements though.
If you bring the stream query back, but do this immediately after constructing your database, does the error still happen?
var db = MyDatabase();
db.customSelect('select 1').get();
You don't even need to await that, it would just be interesting to know what happens when that runs before the stream is listened to.
Hi again. Sorry for the delayed response, I somehow missed your reply.
If you bring the stream query back, but do this immediately after constructing your database, does the error still happen?
No, that fixes the error! With db.customSelect('select 1').get();
right after construction of MyDatabase
everything works flawlessly and if I remove it again the error returns.
Hey this is happening for us too! The fix works, but it would be nice to have this fixed :)
I agree - but I still couldn't find a way to reproduce this locally. I think I've also made improvements on this in b3e2aa739fc41b69560936584234f1022ad8c6ab which my be related. Which drift version are you using?
I've also made some other changes to my full app (migrations and some logic changes), but anyway, I was on 2.18.0 and now on 2.20.0 I do not need the db.customSelect('select 1').get();
workaround anymore.
We're on 2.18.0 at the moment, I'll see if we can update
Update:
We did need the above-mentioned workaround again, but only for a new table in our DB. Not sure what it has that is different from all of the others in this case. But this time I got no Operation was cancelled
message, only the delete would not complete. Took me some time to remember that this issue was related to deletes. Noticed when setting the isolateDebugLog
fixed it.
I'm trying to delete some rows that break a foreign key constraint.
My code is doing the following: In the
beforeOpen
function forMigrationStrategy
I'm finding all the offending rows usingPRAGMA foreign_key_check
and then attempting to delete the rows in a for loop. The first delete works fine, but the second delete throws the error below. If I restart my app another delete will go through, and the second will trigger the error again.I don't know what the error is supposed to mean and can't find anything in the documentation about cancelling operations. But, it seems that the first delete is doing something that causes any subsequent query to fail with that error (I've tried with select queries and they give the same error).
Here is the full code:
Let me know if there's more information that is useful to debug this.