public ResultWrapper Execute(string name, ParameterWrapper[] parameters) { ActionWrapper action = this.GetAction(name); string path = RestWrapper.BuildActionUrl(parameters, action); int num = 0; int interval = action.Interval; while (num <= action.NumberOfRetries) { ++num; try { ResultWrapper result = CircuitBreakerContainer.GetCircuitBreaker(this.interfaceType).Execute(this.baseUri + path, (Func <ResultWrapper>)(() => this.InvokeAction(name, parameters, action, path)), this._serviceLocator); if (result.Error != null) { if (result.Error is SuspendedDependencyException || !action.Retry || num > action.NumberOfRetries || !this.IsTransient(action, result.Error)) { return(result); } this._serviceLocator.GetService <ILogger>()?.Error(result.Error); this._serviceLocator.GetService <ILogger>()?.Message(string.Format("Retrying action {0}, retry count {1}", (object)action.Name, (object)num)); interval *= action.IncrementalRetry ? num : 1; result.EndState(); Thread.Sleep(interval); } else { if (num > 1) { result.GetState().Extras.Add("retryCount", (object)num); } return(result); } } catch (Exception ex) { this._logger?.Error(ex); if (!action.Retry || num > action.NumberOfRetries || !this.IsTransient(action, ex)) { throw; } else { Thread.Sleep(action.IncrementalRetry ? num : action.Interval); } } } throw new Exception("Should not get here!?!"); }
public void InitializeClient(Type interfaceType) { ConcurrentDictionary <string, ActionWrapper> concurrentDictionary1; if (RestWrapper.cache.TryGetValue(interfaceType, out concurrentDictionary1)) { return; } ConcurrentDictionary <string, ActionWrapper> concurrentDictionary2 = new ConcurrentDictionary <string, ActionWrapper>(); IRoutePrefix routePrefix = RestWrapper.GetRoutePrefix(interfaceType); this._errorInterceptor = interfaceType.GetCustomAttribute <ErrorHandlerAttribute>(); this._serviceLocator.GetService <ILogger>()?.Message("Initializing client " + interfaceType.Name); RetryAttribute customAttribute = interfaceType.GetCustomAttribute <RetryAttribute>(); if (interfaceType.GetCustomAttribute <CircuitBreakerAttribute>() != null) { CircuitBreakerContainer.Register(interfaceType, (ICircuitBreaker) new Stardust.Interstellar.Rest.Client.CircuitBreaker.CircuitBreaker(interfaceType.GetCustomAttribute <CircuitBreakerAttribute>(), this._serviceLocator) { ServiceName = interfaceType.FullName }); } else { CircuitBreakerContainer.Register(interfaceType, (ICircuitBreaker) new NullBreaker()); } foreach (MethodInfo methodInfo in interfaceType.GetMethods().Length == 0 ? ((IEnumerable <Type>)interfaceType.GetInterfaces()).First <Type>().GetMethods() : interfaceType.GetMethods()) { try { RetryAttribute retryAttribute = methodInfo.GetCustomAttribute <RetryAttribute>() ?? customAttribute; this._serviceLocator.GetService <ILogger>()?.Message("Initializing client action " + interfaceType.Name + "." + methodInfo.Name); IRoute template = (IRoute)methodInfo.GetCustomAttribute <IRouteAttribute>() ?? (IRoute)methodInfo.GetCustomAttribute <VerbAttribute>(); string actionName = this.GetActionName(methodInfo); List <VerbAttribute> list = methodInfo.GetCustomAttributes(true).OfType <VerbAttribute>().ToList <VerbAttribute>(); ActionWrapper action = new ActionWrapper() { Name = actionName, ReturnType = methodInfo.ReturnType, RouteTemplate = ExtensionsFactory.GetRouteTemplate(routePrefix, template, methodInfo, this._serviceLocator), Parameters = new List <ParameterWrapper>() }; MethodInfo method = methodInfo; IServiceProvider serviceLocator = this._serviceLocator; List <HttpMethod> httpMethods = ExtensionsFactory.GetHttpMethods(list, method, serviceLocator); List <IHeaderInspector> headerInspectors = ExtensionsFactory.GetHeaderInspectors(methodInfo, this._serviceLocator); action.UseXml = methodInfo.GetCustomAttributes().OfType <UseXmlAttribute>().Any <UseXmlAttribute>(); action.CustomHandlers = headerInspectors.Where <IHeaderInspector>((Func <IHeaderInspector, bool>)(h => this.headerHandlers.All <IHeaderHandler>((Func <IHeaderHandler, bool>)(parent => parent.GetType() != h.GetType())))).ToList <IHeaderInspector>(); action.ErrorHandler = this._errorInterceptor; action.Actions = httpMethods; if (retryAttribute != null) { action.Retry = true; action.Interval = retryAttribute.RetryInterval; action.NumberOfRetries = retryAttribute.NumberOfRetries; action.IncrementalRetry = retryAttribute.IncremetalWait; if (retryAttribute.ErrorCategorizer != (Type)null) { action.ErrorCategorizer = (IErrorCategorizer)Activator.CreateInstance(retryAttribute.ErrorCategorizer, (object)this._serviceLocator); } } ExtensionsFactory.BuildParameterInfo(methodInfo, action, this._serviceLocator); concurrentDictionary2.TryAdd(action.Name, action); } catch (Exception ex) { this._logger?.Error(ex); throw; } } if (RestWrapper.cache.TryGetValue(interfaceType, out concurrentDictionary1)) { return; } RestWrapper.cache.TryAdd(interfaceType, concurrentDictionary2); }