예제 #1
0
파일: Router.cs 프로젝트: 00mjk/Router-1
        /// <summary>
        /// Routes the call using the ResolverFrx
        /// </summary>
        /// <param name="sAddress">Address which the call was sent to</param>
        /// <param name="Context">Dictionary of context variables used for routing and/or processing</param>
        /// <param name="Body">Message Body/Call Body</param>
        /// <param name="overrideDefaultExecutionStrategy">overrides the router's default execution strategy</param>
        /// <returns>Routing Result</returns>
        public virtual async Task <RER> RouteAsync(string sAddress,
                                                   IDictionary <string, object> Context,
                                                   Stream Body,
                                                   ContextExecuteStrategyBase overrideDefaultExecutionStrategy)
        {
            // context management
            var chs = overrideDefaultExecutionStrategy == null ? mDefaultContextExecuteStrategy : overrideDefaultExecutionStrategy;
            RoutingContextBase re;
            RER rer;

            Context = null != Context ? Context : new Dictionary <string, object>();
            // can be used by various sub system involved to reach the router, unique call instance id, or the trace log
            Context.Add(Context_Router_Call_InstanceId_Key, Guid.NewGuid().ToString()); // instance id

            #region Resolve

            try
            {
                re = await ResolveAsync(sAddress, Context, Body);
            }

            // caller can handle this ae, or RouterResolveException
            catch (AggregateException ae)
            {
                throw new RouterResolveException(ae);
            }
            catch (Exception e)
            {
                // this is either a telemetry error, and shouldn't happen in runtime
                // (unless you are doing something funny with the telemetry sub system)
                // or you have a sub class that is doing something funny.
                throw new RouterResolveException(e);
            }

            #endregion
            // if no resolver is matching then we need return null
            if (null == re)
            {
                return(null);
            }

            #region Execute
            try
            {
                rer = await ExecuteContextAsync(re, chs);
            }
            catch
            {
                throw;
            }
            finally
            {
                // context maintenance
                // just in case the caller intersted in reusing the dictionary
                Context.Remove(Context_Router_Call_InstanceId_Key);
            }
            return(rer);

            #endregion
        }
예제 #2
0
        public static ContextExecuteStrategyBase ThenTryAgain(this ContextExecuteStrategyBase strategy,
                                                              int times,
                                                              int DelayMs)
        {
            var current = strategy;

            for (var i = 1; i <= times; i++)
            {
                current.Next = new RetryAfterStrategy(DelayMs);
                current      = current.Next;
            }

            return(current);
        }
예제 #3
0
        /// <summary>
        /// chains multiple retries with different backoffs
        /// </summary>
        /// <param name="strategy"></param>
        /// <param name="times"></param>
        /// <param name="DelayMs"></param>
        /// <param name="delayFactor"></param>
        /// <returns></returns>
        public static ContextExecuteStrategyBase ThenTryAgainWithBackOff(this ContextExecuteStrategyBase strategy,
                                                                         int times,
                                                                         int DelayMs,
                                                                         float delayFactor)
        {
            var current = strategy;

            for (var i = 1; i <= times; i++)
            {
                var actualDelay = 1 == i ? DelayMs : i * delayFactor * DelayMs;

                current.Next = new RetryAfterStrategy((int)actualDelay);
                current      = current.Next;
            }

            return(current);
        }
예제 #4
0
파일: Router.cs 프로젝트: 00mjk/Router-1
        protected virtual async Task <RER> ExecuteContextAsync(RoutingContextBase re, ContextExecuteStrategyBase chs)
        {
            RER       rer        = null;
            Stopwatch sw         = new Stopwatch();
            var       currentChs = chs;
            ContextExecuteModeBase ExecuteMode = new DoNotRetryMode();
            var TryCount = 1;
            var bSucess  = false;


            while (true)
            {
                try
                {
                    sw.Start();
                    rer = (RER)await re.ExecuteAsync(ExecuteMode);

                    sw.Stop();
                    bSucess = true;
                }
                catch (Exception e)
                {
                    if (null == currentChs)
                    {
                        throw;
                    }

                    TryCount++;

                    // circut breaker
                    if (TryCount > mMaxRetryCount)
                    {
                        throw new RouterMaxedRetryException(new AggregateException(e))
                              {
                                  RetryCount = (TryCount - 1), RoutingContext = re
                              }
                    }
                    ;


                    try
                    {
                        // execute current strategy;
                        ExecuteMode = await currentChs.ExecuteStrategyAsync(TryCount, re, new AggregateException(e));
                    }
                    catch (Exception StrategyExecuteFail)
                    {
                        // if we failed to execute strategy we just wrap the exception
                        // along with the orginal execution one.
                        throw new FailedToExecuteStrategyException(StrategyExecuteFail, e)
                              {
                                  TryCount = TryCount, RoutingContext = re
                              };
                    }

                    // move to next strategy
                    currentChs = currentChs.Next;


                    if (!ExecuteMode.ShouldRouterTryAgain)
                    {
                        throw new AggregateException(e);
                    }
                }

                finally
                {
                    OnTelemetryExecute(re, rer, sw.Elapsed.TotalMilliseconds);
                    Trace.WriteLine(string.Format("Execute in {0} Call Count {1} Routing Type:{2}",
                                                  sw.Elapsed.TotalMilliseconds, TryCount, re.RouteExecuteType), "Verbose");

                    sw.Reset(); // reset the clock
                }

                if (bSucess)
                {
                    break; // exit the loop
                }
            }


            return(rer);
        }
예제 #5
0
 public static ContextExecuteStrategyBase ThrowIfExceptionIsIn(this ContextExecuteStrategyBase strategy, params Exception[] exceptions)
 {
     return(strategy.Then(new ThrowIfInnerExceptionNotIn(exceptions)));
 }
예제 #6
0
 public virtual ContextExecuteStrategyBase Then(ContextExecuteStrategyBase next)
 {
     this.Next = next;
     return(this.Next);
 }