refactor: Remove database transaction workaround
The workaround was from the time when we have used sqflite or when Hive had bugs. But now HiveCollections already supports transactions in Dart zones and concurrent write operations shouldn't be a problem anymore.
This commit is contained in:
parent
9d9b1e38ec
commit
7a5b013c92
|
|
@ -308,7 +308,7 @@ abstract class DatabaseApi {
|
|||
|
||||
Future<dynamic> close();
|
||||
|
||||
Future<T> transaction<T>(Future<T> Function() action);
|
||||
Future<void> transaction(Future<void> Function() action);
|
||||
|
||||
Future<String> exportDump();
|
||||
|
||||
|
|
|
|||
|
|
@ -1310,61 +1310,9 @@ class HiveCollectionsDatabase extends DatabaseApi {
|
|||
return;
|
||||
}
|
||||
|
||||
Completer<void>? _transactionLock;
|
||||
final _transactionZones = <Zone>{};
|
||||
|
||||
@override
|
||||
Future<T> transaction<T>(Future<T> Function() action) async {
|
||||
// we want transactions to lock, however NOT if transactoins are run inside of each other.
|
||||
// to be able to do this, we use dart zones (https://dart.dev/articles/archive/zones).
|
||||
// _transactionZones holds a set of all zones which are currently running a transaction.
|
||||
// _transactionLock holds the lock.
|
||||
|
||||
// first we try to determine if we are inside of a transaction currently
|
||||
var isInTransaction = false;
|
||||
Zone? zone = Zone.current;
|
||||
// for that we keep on iterating to the parent zone until there is either no zone anymore
|
||||
// or we have found a zone inside of _transactionZones.
|
||||
while (zone != null) {
|
||||
if (_transactionZones.contains(zone)) {
|
||||
isInTransaction = true;
|
||||
break;
|
||||
}
|
||||
zone = zone.parent;
|
||||
}
|
||||
// if we are inside a transaction....just run the action
|
||||
if (isInTransaction) {
|
||||
return await action();
|
||||
}
|
||||
// if we are *not* in a transaction, time to wait for the lock!
|
||||
while (_transactionLock != null) {
|
||||
await _transactionLock!.future;
|
||||
}
|
||||
// claim the lock
|
||||
final lock = Completer<void>();
|
||||
_transactionLock = lock;
|
||||
try {
|
||||
// run the action inside of a new zone
|
||||
return await runZoned(() async {
|
||||
try {
|
||||
// don't forget to add the new zone to _transactionZones!
|
||||
_transactionZones.add(Zone.current);
|
||||
late final T result;
|
||||
await _collection.transaction(() async {
|
||||
result = await action();
|
||||
});
|
||||
return result;
|
||||
} finally {
|
||||
// aaaand remove the zone from _transactionZones again
|
||||
_transactionZones.remove(Zone.current);
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
// aaaand finally release the lock
|
||||
_transactionLock = null;
|
||||
lock.complete();
|
||||
}
|
||||
}
|
||||
Future<void> transaction(Future<void> Function() action) =>
|
||||
_collection.transaction(action);
|
||||
|
||||
@override
|
||||
Future<void> updateClient(
|
||||
|
|
|
|||
|
|
@ -1255,7 +1255,7 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
|
|||
final _transactionZones = <Zone>{};
|
||||
|
||||
@override
|
||||
Future<T> transaction<T>(Future<T> Function() action) async {
|
||||
Future<void> transaction(Future<void> Function() action) async {
|
||||
// we want transactions to lock, however NOT if transactoins are run inside of each other.
|
||||
// to be able to do this, we use dart zones (https://dart.dev/articles/archive/zones).
|
||||
// _transactionZones holds a set of all zones which are currently running a transaction.
|
||||
|
|
|
|||
|
|
@ -64,18 +64,6 @@ void testDatabase(
|
|||
});
|
||||
expect(counter++, 3);
|
||||
});
|
||||
|
||||
// we can't use Zone.root.run inside of tests so we abuse timers instead
|
||||
Timer(Duration(milliseconds: 50), () async {
|
||||
await database.transaction(() async {
|
||||
expect(counter++, 6);
|
||||
});
|
||||
});
|
||||
await database.transaction(() async {
|
||||
expect(counter++, 4);
|
||||
await Future.delayed(Duration(milliseconds: 100));
|
||||
expect(counter++, 5);
|
||||
});
|
||||
});
|
||||
test('insertIntoToDeviceQueue', () async {
|
||||
toDeviceQueueIndex = await database.insertIntoToDeviceQueue(
|
||||
|
|
|
|||
Loading…
Reference in New Issue