public static PolledObject <T> GetFromPoolWithRetrying <T>(this ObjectPool <T> pool, string methodName, int maxGetClientTryingCount = 3, int waitingSeconds = 1)
        {
            Guard.ArgumentNotNull(pool, nameof(pool));
            Guard.ArgumentNotEmpty(methodName, nameof(methodName));

            PolledObject <T> result = null;

            bool clientGot            = false;
            int  clientGetTryingCount = 0;

            do
            {
                clientGetTryingCount++;

                if (pool.GetFromPool(out result))
                {
                    clientGot = true;
                }
                else
                {
                    Log.Information("{0}: The creation limit has been exceeded for {0}, waiting next trying", methodName);

                    Thread.Sleep(TimeSpan.FromSeconds(waitingSeconds));
                }
            }while (!clientGot && (clientGetTryingCount < maxGetClientTryingCount));

            if (result == null)
            {
                Log.Warning("{0}: Can't get from pool after {0} trying", methodName, maxGetClientTryingCount);
            }

            return(result);
        }
Beispiel #2
0
        public void ReleaseToPool(PolledObject <T> obj)
        {
            if (obj != null)
            {
                _useCounter.AddOrUpdate(obj.Id, 0, (key, existing) => existing - 1);
            }

            DisposeFailedObjects();
        }
Beispiel #3
0
        public void CloseObject(PolledObject <T> obj)
        {
            if (obj == null)
            {
                return;
            }

            _failed.TryAdd(obj.Id, obj);
        }
Beispiel #4
0
        public bool GetFromPool(out PolledObject <T> obj)
        {
            obj = null;

            bool success    = false;
            bool needCreate = false;

            do
            {
                if (needCreate || _objectInUse.IsEmpty)
                {
                    _index++;

                    if (_index > _max)
                    {
                        _index--;
                        break;
                    }

                    obj = new PolledObject <T>
                    {
                        Id       = Guid.NewGuid(),
                        Instance = _init()
                    };

                    if (_objectInUse.TryAdd(obj.Id, obj))
                    {
                        Log.Information("Create new {0}", _name);

                        success = true;
                    }
                }
                else
                {
                    foreach (var item in _objectInUse)
                    {
                        if (!_failed.ContainsKey(item.Key))
                        {
                            obj = item.Value;

                            success = true;

                            break;
                        }
                    }
                }

                if (success)
                {
                    _useCounter.AddOrUpdate(obj.Id, 1, (key, existing) => existing + 1);
                }
                else
                {
                    needCreate = true;

                    Log.Information("Need to create new {0}", _name);
                }
            }while (!success);

            return(success);
        }
Beispiel #5
0
        public async Task <(HttpStatusCode Code, string Html)> GetAsync(string url, CancellationToken token = default(CancellationToken))
        {
            (HttpStatusCode code, string Html)result = default((HttpStatusCode code, string Html));

            PolledObject <HttpClient> clientInfo = null;

            try
            {
                string methodName = $"Calling GET to {url}";

                clientInfo = _httpClientPool.GetFromPoolWithRetrying(methodName, _maxGetClientTryingCount);

                if (clientInfo != null)
                {
                    bool maxRetryCountAchieved = false;
                    result = await _retry.DoWithRetryAsync(
                        job : async(n, ct) =>
                    {
                        var data = await clientInfo.Instance.GetAsync(new Uri(url))
                                   .ConfigureAwait(false);

                        if (data.IsSuccessStatusCode)
                        {
                            using (var stream = new MemoryStream())
                            {
                                await data.Content.CopyToAsync(stream);
                                stream.Seek(0, SeekOrigin.Begin);

                                using (var reader = new StreamReader(stream, true))
                                {
                                    return(Code : data.StatusCode, Html : await reader.ReadToEndAsync());
                                }
                            }
                        }
                        else
                        {
                            return(Code : data.StatusCode, Html : string.Empty);
                        }
                    },
                        exceptionHandler : (ex) =>
                    {
                        _httpClientPool.CloseObject(clientInfo);

                        Log.Error(ex, "There was an exception while execute {0} with {1}", methodName, clientInfo.Id);
                    },
                        failCallback : (p) =>
                    {
                        maxRetryCountAchieved = true;

                        Log.Warning("Can't execute {0}", methodName);
                    },
                        token : token);

                    if (maxRetryCountAchieved)
                    {
                        throw new HttpClientCallerMaxRetryException($"Can't execute {methodName}, server doesn't respond after {_retry.RetryCount} attempt(s)");
                    }
                }
                else
                {
                    throw new HttpClientPoolException();
                }
            }
            finally
            {
                _httpClientPool.ReleaseToPool(clientInfo);
            }

            return(result);
        }