rollbackAfter<T> method

Future<T> rollbackAfter<T>(
  1. Future<T> body(), {
  2. String? connection,
})

Runs body in a transaction that is always rolled back (Laravel RefreshDatabase). Application transactions inside become savepoints and their after-commit callbacks fire when they "commit", as they would without the wrapper.

Implementation

Future<T> rollbackAfter<T>(
  Future<T> Function() body, {
  String? connection,
}) async {
  if (_activeScope(connection) != null) {
    throw StateError('rollbackAfter cannot be nested inside a transaction.');
  }
  final connectionName = connection ?? config.defaultConnection;
  final driver = await this.connection(connection);
  final baseline = <FutureOr<void> Function()>[];
  late T result;
  try {
    await driver.transaction<void>((tx) {
      final scope = _TransactionScope(tx, this, connectionName);
      return runZoned<Future<void>>(
        () async {
          result = await body();
          throw const _RollbackSignal();
        },
        zoneValues: <Object?, Object?>{
          transactionKey: scope.executor,
          _scopeKey: scope,
          depthKey: 1,
          afterCommitKey: baseline,
          baselineKey: baseline,
        },
      ).whenComplete(scope.close);
    });
  } on _RollbackSignal {
    return result;
  }
  return result;
}