transaction<T> method

  1. @override
Future<T> transaction<T>(
  1. void f(
    1. Transaction tx,
    2. void setResult(
      1. T res
      )
    )
)
override

Runs the provided non-async function inside a transaction.

The function may not use async/await otherwise the transaction may commit before the queries are actually executed. This is a limitation of some adapters, that the function passed to the transaction runs "synchronously" through callbacks without releasing the event loop.

Implementation

@override
Future<T> transaction<T>(
  void Function(Transaction tx, void Function(T res) setResult) f,
) {
  return txLock.synchronized(() async {
    db.execute('BEGIN');

    try {
      final txCompleter = Completer<T>();
      final tx = Transaction(this, (e) => txCompleter.completeError(e));

      runZonedGuarded(() {
        f(tx, (T res) {
          // Commit the transaction when the user sets the result.
          // This assumes that the user does not execute any more queries after setting the result.
          db.execute('COMMIT');
          txCompleter.complete(res);
        });
      }, (error, stack) {
        txCompleter.completeError(error);
      });

      return await txCompleter.future;
    } catch (e) {
      db.execute('ROLLBACK');
      rethrow;
    }
  });
}