private bool RetryAction(Func <int, bool> action, ConnectionPoolOptions options)
        {
            if (action == null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            for (var i = 0; i < options.MaximumRetryWhenFailure; i++)
            {
                // 'action' must handle exceptions explicitly
                var success = action(i + 1);

                if (success)
                {
                    return(true);
                }

                Thread.Sleep(TimeSpan.FromSeconds(options.RetryIntervalInSeconds));
            }

            return(false);
        }
        public async Task <string> InitDbConnectionAsync(ConnectionPoolOptions options)
        {
            if (disposedValue)
            {
                throw new ObjectDisposedException(nameof(SqlConnectionPoolManager));
            }

            var poolKey = GetPoolKeyFromConnStr(options.ConnectionString);

            #region Validation
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            if (options.LifetimeInMinutes <= 0)
            {
                throw new ArgumentException(nameof(options.LifetimeInMinutes));
            }

            if (string.IsNullOrWhiteSpace(options.ConnectionString))
            {
                throw new ArgumentException(nameof(options.ConnectionString));
            }

            if (options.MaxPoolSize < 1)
            {
                throw new ArgumentException(nameof(options.MaxPoolSize));
            }

            if (options.MinPoolSize < 0 || options.MinPoolSize > options.MaxPoolSize)
            {
                throw new ArgumentException(nameof(options.MinPoolSize));
            }

            if (options.MaximumRetryWhenFailure < 0)
            {
                throw new ArgumentException(nameof(options.MaximumRetryWhenFailure));
            }

            if (_poolOptions.ContainsKey(poolKey))
            {
                throw new InvalidOperationException($"Already initialized '{poolKey}'");
            }
            #endregion

            try
            {
                _poolOptions[poolKey] = options.Snapshot();
                _pools[poolKey]       = new ConcurrentQueue <PooledDbConnectionWrapper>();

                for (var i = 0; i < options.MinPoolSize; i++)
                {
                    SetupNewConnection(poolKey);
                }

                // Create watcher
                if (_watcherThread == null)
                {
                    _watcherThread = new Thread(new ThreadStart(Watch))
                    {
                        IsBackground = true
                    };

                    _watcherThread.Start();
                }
            }
            catch (Exception e)
            {
                await ReleasePoolAsync(poolKey);

                throw e;
            }

            return(poolKey);
        }
 private bool HasRedundantConnections(ConcurrentQueue <PooledDbConnectionWrapper> pool,
                                      ConnectionPoolOptions poolOption)
 {
     return(pool.Count > poolOption.MinPoolSize);
 }
 private bool IsLackOfConnections(ConcurrentQueue <PooledDbConnectionWrapper> pool,
                                  ConnectionPoolOptions poolOption)
 {
     return(pool.Count < poolOption.MinPoolSize);
 }
 private bool HasFullOfConnections(ConcurrentQueue <PooledDbConnectionWrapper> pool,
                                   ConnectionPoolOptions poolOption)
 {
     return(pool.Count >= poolOption.MaxPoolSize);
 }
 private bool HasExceededLifetime(ConnectionInfo info, ConnectionPoolOptions poolOption)
 {
     return((DateTime.UtcNow - info.CreatedTime).TotalMinutes >= poolOption.LifetimeInMinutes);
 }