runTransaction<T> method
Runs delegate
inside a transaction.
If delegate
returns without throwing an exception, the transaction
is committed and the return value is passed through as return value
of this method.
If delegate
throws an exception, the transaction is rolled back
and the exception is rethrown.
Implementation
@override
Future<T> runTransaction<T>(
Future<T> Function(DatabaseContext context) delegate) async {
if (Zone.current[#postgresTransactionConnection] == _connection &&
Zone.current[#postgresTransactionContext] != null) {
final context = await (Zone.current[#postgresTransactionContext]
as Completer<DatabaseContext>)
.future;
return await delegate(context);
}
final completer = Completer<_Box<T>>();
final contextCompleter = Completer<DatabaseContext>();
runZonedGuarded(() {
_connection
.transaction((c) async {
final context = PostgreSQLDatabaseContext(
adapter as PostgreSQLDatabaseAdapter, c);
contextCompleter.complete(context);
return await delegate(context);
})
.then((r) => completer.complete(_Box<T>.value(r)))
.catchError(
(e, stack) => completer.complete(_Box<T>.error(e, stack)));
}, (error, stack) {
resolve<LogService?>()?.warn(
'Unhandled error in postgres package.',
error: error,
trace: stack,
);
}, zoneValues: {
#postgresTransactionConnection: _connection,
#postgresTransactionContext: contextCompleter
});
return await (await completer.future).value;
}