/// <summary> /// Invokes service method that returns a value of type T. /// </summary> protected T Invoke <T>(ServiceMethod <T> method) { const int maxRetryCount = 1; int retryCount = 0; while (true) { var client = _AcquireClient(); try { return(method.Invoke(client)); } catch (Exception e) { if (ProxyAuthenticationErrorHandler.HandleError(e)) { continue; } var isTokenError = _IsTokenError(e); if (retryCount >= maxRetryCount || !isTokenError) { if (ServiceHelper.IsCommunicationError(e)) { throw ServiceHelper.CreateCommException( _connection.Title, e); } throw; } if (isTokenError) { _connection.GenerateToken(); _CloseClient(client); client = null; } ++retryCount; } finally { _ReleaseClient(client); } } }
/// <summary> /// Attempts to prepare for retrying request sending upon catching the /// specified exception. /// </summary> /// <param name="exception">The exception caused failure of the previous /// request sending.</param> /// <returns>True if and only if the request sending could be repeated.</returns> private bool _PrepareRetry(Exception exception) { var restException = exception as RestException; if (restException != null) { return(false); } if (ProxyAuthenticationErrorHandler.HandleError(exception)) { return(true); } if (_IsTransientError(exception)) { Thread.Sleep(RETRY_WAIT_TIME); return(true); } return(false); }
/// <summary> /// Handles AsyncCompleted event results. /// </summary> /// <returns> /// Returns true if the operation is completed, false if it's retried. /// </returns> protected bool IsAsyncCompleted(object sender, AsyncCompletedEventArgs args, out AsyncCompletedEventArgs outArgs) { outArgs = null; Guid id = Guid.Empty; Exception error = args.Error; object userState = null; bool isCompleted = true; try { TClient client = (TClient)sender; _DecrementAsyncRefCount(client); if (args.UserState == null) { throw new InvalidOperationException(); } id = (Guid)args.UserState; AsyncContext ctx = null; if (!_asyncContextMap.TryGetValue(id, out ctx)) { throw new InvalidOperationException(); } userState = ctx.UserState; if (_IsAsyncFailed(args)) { bool needToRetry = ctx.RetryCount == 0 && _IsTokenError(args.Error); if (ProxyAuthenticationErrorHandler.HandleError(args.Error)) { needToRetry = true; } if (needToRetry) { _connection.GenerateToken(); // update token } if (needToRetry || client.State == CommunicationState.Faulted) { _CloseClient(client); // do retry if needed if (needToRetry) { client = _AcquireClient(); _IncrementAsyncRefCount(client); ctx.RetryMethod(client); isCompleted = false; } } } } catch (Exception e) { error = e; } if (isCompleted) { if (error != null) { error = _ConvertCommException(error); } _asyncContextMap.Remove(id); outArgs = new AsyncCompletedEventArgs(error, args.Cancelled, userState); } return(isCompleted); }