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); }
public void ReleaseToPool(PolledObject <T> obj) { if (obj != null) { _useCounter.AddOrUpdate(obj.Id, 0, (key, existing) => existing - 1); } DisposeFailedObjects(); }
public void CloseObject(PolledObject <T> obj) { if (obj == null) { return; } _failed.TryAdd(obj.Id, obj); }
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); }
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); }