run<R> method
Future<R>
run<R>(
- Future<
R> action(), { - AcquisitionOptions acquire = const AcquisitionOptions(),
- OrmException? acquisitionTimeoutError,
Runs action with an acquired or already leased connection.
This does not start a transaction. acquire limits only connection waiting;
the connection must not escape action. Prefer execute for one command.
Implementation
Future<R> run<R>(
Future<R> Function(SqlConnection) action, {
AcquisitionOptions acquire = const AcquisitionOptions(),
OrmException? acquisitionTimeoutError,
}) {
checkActive();
acquire.check();
final connection = _connection == null
? null
: _sessionConnection(_connection);
final observer = onAcquire;
final clock = observer == null || connection != null
? null
: (Stopwatch()..start());
var entered = false;
void report(Object? error) {
clock?.stop();
try {
observer?.call(
AcquisitionEvent(
elapsed: clock?.elapsed ?? Duration.zero,
reusedConnection: connection != null,
error: error,
),
);
} catch (_) {}
}
Future<R> enter(SqlConnection value) {
entered = true;
report(null);
return action(value);
}
Future<R> observed(Future<R> result) => observer == null
? result
: result.onError((Object error, StackTrace stack) {
if (!entered) report(error);
Error.throwWithStackTrace(error, stack);
});
final callback = observer == null ? action : enter;
if (connection == null &&
(acquire.timeout != null || acquire.cancellation != null)) {
final wait = ConnectionWait(
driver,
callback,
acquire,
timeoutError: acquisitionTimeoutError,
);
_track(wait.drained);
return observed(wait.result);
}
final result = connection != null
? Future.sync(() => callback(connection))
: observer == null
? driver.run(action)
: Future.sync(() => driver.run(callback));
final done = result.then<void>(
(_) {},
onError: (Object _, StackTrace _) {},
);
_track(done);
return observed(result);
}