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);
            }
Example #2
0
            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;
 }
Example #5
0
            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);
            }
Example #7
0
            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;
                }
            }
Example #8
0
 private void Assert(SemaphoreSlimSignalable.SemaphoreWaitResult[] actual, SemaphoreSlimSignalable.SemaphoreWaitResult expected) =>
 actual.All(r => r == expected).Should().BeTrue();