You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If we update multiple tables in a transaction and we're listening to both tables updates, sometimes they don't emit the updates synchronously in the same frame.
This would cause issues if we merge both streams using combineLatest2 like in Selecting a cart example and we expect the updates to be emitted in the same time (i.e: the cart must have items with it in our use case, so there can't be a cart with no items).
Minimal example: database.dart:
import'package:drift/drift.dart';
import'package:drift_flutter/drift_flutter.dart';
part'database.g.dart';
classTodoItemsextendsTable {
IntColumnget id =>integer().autoIncrement()();
TextColumnget title =>text()();
IntColumnget category =>integer().nullable().references(TodoCategory, #id)();
}
classTodoCategoryextendsTable {
IntColumnget id =>integer().autoIncrement()();
TextColumnget description =>text()();
}
@DriftDatabase(tables: [TodoItems, TodoCategory])
classAppDatabaseextends_$AppDatabase {
// After generating code, this class needs to define a schemaVersion getter// and a constructor telling drift where the database should be stored.// These are described in the getting started guide: https://drift.simonbinder.eu/getting-started/#openAppDatabase() :super(_openConnection());
@overrideintget schemaVersion =>1;
staticQueryExecutor_openConnection() {
// driftDatabase from package:drift_flutter stores the database in// getApplicationDocumentsDirectory().returndriftDatabase(name:'my_database');
}
}
Thank you for the detailed description, this is a good catch!
When a transaction completes, drift invalidates all queries on any table affected by the transaction. When there are lots of pending queries, they might take a while to complete and since they're running on a background isolate, it's perfectly valid for them to complete at different times.
I know that this can violate some correctness assumptions, but generally is working as intended (since you're not running the queries in a transaction, they can yield inconsistent results).
The problem is that drift makes it really hard to get this right (as is evident by the docs showing a broken example). I think we should have an API to express a "these n streams must always emit consistent results" wish by the user, since doing this across all streams by default would make them quite slow.
Maybe it could look something like this:
late categories, todos;
final stream = database.streamGroup((builder) {
categories = builder.add(database.managers.todoCategory.watch());
todos = builder.add(database.managers.todoItems.watch());
});
return stream.watch((results) {
return (todoCategories: results[categories], todoItems: results[todos]);
});
That API design isn't great, but we need something that's reasonably type safe, supports an arbitrary amount of streams and delivers all updates from the source stream in a single stream (I'm not sure if emitting them in the same frame from different streams is a sound design, e.g. what happens if you pause some of the streams. It introduces a weird synchronous pairing between different streams).
Let me know if you have ideas on how to solve this as well, but I don't see a way to not make this opt-in for some streams since it comes with a performance penalty for managing the transaction.
If we update multiple tables in a transaction and we're listening to both tables updates, sometimes they don't emit the updates synchronously in the same frame.
This would cause issues if we merge both streams using
combineLatest2
like in Selecting a cart example and we expect the updates to be emitted in the same time (i.e: the cart must have items with it in our use case, so there can't be a cart with no items).Minimal example:
database.dart
:main.dart
:Demonstration video:
Screen.Recording.2024-11-13.at.8.41.23.PM.mp4
Furthermore, Testing
combineLatest2
without drift seems to work as expected (emits values in the same frame):The text was updated successfully, but these errors were encountered: