public async Task <PooledConnection> CreateOpenedOrReuseAsync(CancellationToken cancellationToken) { var connection = _pool._connectionHolder.Acquire(); var waitTimeout = _connectingTimeout; var stopwatch = Stopwatch.StartNew(); while (connection == null) { // Try to acquire connecting semaphore. Possible operation results: // Entered: The request was successfully fulfilled, and a connection establishment can start // Signaled: The request was interrupted because Connection was return to pool and can be reused // Timeout: The request was timed out after WaitQueueTimeout period. _connectingWaitStatus = await _pool._connectingQueue.WaitSignaledAsync(waitTimeout, cancellationToken).ConfigureAwait(false); connection = _connectingWaitStatus switch { SemaphoreSlimSignalable.SemaphoreWaitResult.Signaled => _pool._connectionHolder.Acquire(), SemaphoreSlimSignalable.SemaphoreWaitResult.Entered => await CreateOpenedInternalAsync(cancellationToken).ConfigureAwait(false), SemaphoreSlimSignalable.SemaphoreWaitResult.TimedOut => throw TimoutException(stopwatch), _ => throw new InvalidOperationException($"Invalid wait result {_connectingWaitStatus}") }; waitTimeout = _connectingTimeout - stopwatch.Elapsed; if (connection == null && waitTimeout <= TimeSpan.Zero) { throw TimoutException(stopwatch); } } return(connection); }
public async Task <IConnectionHandle> AcquireConnectionAsync(CancellationToken cancellationToken) { try { StartCheckingOut(); var stopwatch = Stopwatch.StartNew(); _poolQueueWaitResult = await _pool._maxConnectionsQueue.WaitSignaledAsync(_timeout, cancellationToken).ConfigureAwait(false); if (_poolQueueWaitResult == SemaphoreSlimSignalable.SemaphoreWaitResult.Entered) { PooledConnection pooledConnection = null; var timeout = EnsureTimeout(stopwatch); using (var connectionCreator = new ConnectionCreator(_pool, timeout)) { pooledConnection = await connectionCreator.CreateOpenedOrReuseAsync(cancellationToken).ConfigureAwait(false); } return(EndCheckingOut(pooledConnection, stopwatch)); } stopwatch.Stop(); throw CreateException(stopwatch); } catch (Exception ex) { HandleException(ex); throw; } }
public async Task <PooledConnection> CreateOpenedAsync(CancellationToken cancellationToken) { try { var stopwatch = Stopwatch.StartNew(); _connectingWaitStatus = await _pool._maxConnectingQueue.WaitAsync(_connectingTimeout, cancellationToken).ConfigureAwait(false); stopwatch.Stop(); _pool._poolState.ThrowIfNotReady(); if (_connectingWaitStatus == SemaphoreSlimSignalable.SemaphoreWaitResult.TimedOut) { _pool.CreateTimeoutException(stopwatch, $"Timed out waiting for in connecting queue after {stopwatch.ElapsedMilliseconds}ms."); } var connection = await CreateOpenedInternalAsync(cancellationToken).ConfigureAwait(false); return(connection); } catch (Exception ex) { _pool._connectionExceptionHandler.HandleExceptionOnOpen(ex); throw; } }
public ConnectionCreator(ExclusiveConnectionPool pool, TimeSpan connectingTimeout) { _pool = pool; _connectingTimeout = connectingTimeout; _connectingWaitStatus = SemaphoreSlimSignalable.SemaphoreWaitResult.None; _connection = null; _disposeConnection = true; _stopwatch = null; }
private IConnectionHandle EndCheckingOut(PooledConnection pooledConnection, Stopwatch stopwatch) { var reference = new ReferenceCounted <PooledConnection>(pooledConnection, _pool.ReleaseConnection); var connectionHandle = new AcquiredConnection(_pool, reference); stopwatch.Stop(); var checkedOutConnectionEvent = new ConnectionPoolCheckedOutConnectionEvent(connectionHandle.ConnectionId, stopwatch.Elapsed, EventContext.OperationId); _pool._checkedOutConnectionEventHandler?.Invoke(checkedOutConnectionEvent); // no need to release the semaphore _poolQueueWaitResult = SemaphoreSlimSignalable.SemaphoreWaitResult.None; return(connectionHandle); }
public async Task <PooledConnection> CreateOpenedAsync(CancellationToken cancellationToken) { var stopwatch = Stopwatch.StartNew(); _connectingWaitStatus = await _pool._connectingQueue.WaitAsync(_connectingTimeout, cancellationToken).ConfigureAwait(false); stopwatch.Stop(); if (_connectingWaitStatus == SemaphoreSlimSignalable.SemaphoreWaitResult.TimedOut) { throw new TimeoutException($"Timed out waiting for in connecting queue after {stopwatch.ElapsedMilliseconds}ms."); } var connection = await CreateOpenedInternalAsync(cancellationToken).ConfigureAwait(false); return(connection); }
public PooledConnection CreateOpenedOrReuse(CancellationToken cancellationToken) { try { var connection = _pool._connectionHolder.Acquire(); var waitTimeout = _connectingTimeout; var stopwatch = Stopwatch.StartNew(); while (connection == null) { _pool._poolState.ThrowIfNotReady(); // Try to acquire connecting semaphore. Possible operation results: // Entered: The request was successfully fulfilled, and a connection establishment can start // Signaled: The request was interrupted because Connection was return to pool and can be reused // Timeout: The request was timed out after WaitQueueTimeout period. _connectingWaitStatus = _pool._maxConnectingQueue.WaitSignaled(waitTimeout, cancellationToken); connection = _connectingWaitStatus switch { SemaphoreSlimSignalable.SemaphoreWaitResult.Signaled => _pool._connectionHolder.Acquire(), SemaphoreSlimSignalable.SemaphoreWaitResult.Entered => CreateOpenedInternal(cancellationToken), SemaphoreSlimSignalable.SemaphoreWaitResult.TimedOut => throw CreateTimeoutException(stopwatch), _ => throw new InvalidOperationException($"Invalid wait result {_connectingWaitStatus}") }; waitTimeout = _connectingTimeout - stopwatch.Elapsed; if (connection == null && waitTimeout <= TimeSpan.Zero) { throw CreateTimeoutException(stopwatch); } } return(connection); } catch (Exception ex) { _pool._connectionExceptionHandler.HandleExceptionOnOpen(ex); throw; } }
private void Assert(SemaphoreSlimSignalable.SemaphoreWaitResult[] actual, SemaphoreSlimSignalable.SemaphoreWaitResult expected) => actual.All(r => r == expected).Should().BeTrue();