/// <summary> /// Get score for invoker /// </summary> /// <param name="ib"></param> /// <returns></returns> private int GetScore(InvokerBundle ib) { // not active if (!ib.IsActive) { return(int.MinValue); } // not connected physically if (ib.Channel.State != ChannelState.Idle && ib.Channel.State != ChannelState.Ready) { return(int.MinValue); } // score offset pow int offset = 32768; // default score int score = 0; // apl online (16 points) if (ib.IsAplOnline) { score = score + offset * 16; } // error under limit (8 points) if (ib.ErrorsBelowThreshold) { score = score + offset * 8; } // return score return(score); }
/// <summary> /// Constructor /// </summary> /// <param name="logger"></param> /// <param name="clientConfiguration"></param> /// <param name="connectionInfoList"></param> /// <param name="channelCustomSelector"></param> public ManagedCallInvoker(ILogger logger, GrpcClientConfiguration clientConfiguration, List <GrpcChannelConnectionData> connectionInfoList, Func <object, string, string, string> channelCustomSelector = null) { // set properteis _configuration = clientConfiguration; _logger = logger; _channelCustomSelector = channelCustomSelector; // create invoke bundles Invokers = connectionInfoList.Select(options => { var ch = new Channel(options.Url, options.Port, ChannelCredentials.Insecure); var inv = new DefaultCallInvoker(ch); var bundle = new InvokerBundle(ch, inv, options); return(bundle); }).ToList(); // setup round robin _roundRobin = new RoundRobinPolicy <InvokerBundle>(Invokers, GetScore); }
/// <summary> /// On execution completed /// </summary> /// <typeparam name="TRequest"></typeparam> /// <typeparam name="TResponse"></typeparam> /// <param name="watch"></param> /// <param name="method"></param> /// <param name="request"></param> /// <param name="bundle"></param> /// <param name="t"></param> private void OnExecuteCompleteHandler <TRequest, TResponse>(Stopwatch watch, Method <TRequest, TResponse> method, TRequest request, InvokerBundle bundle, Task <TResponse> t) { // task status TaskStatus status = t.Status; // get execution duration watch.Stop(); var duration = watch.ElapsedMilliseconds; // get svc name var svcName = method.ServiceName.Split('.').Last(); // invoker status update if (status == TaskStatus.RanToCompletion) { bundle.ResetError(); } else { bundle.AddError(); } // log end if (_configuration.Options.LogRequests && _logger != null) { if (status == TaskStatus.RanToCompletion) { _logger.LogInformation("End for action {action} on client {client} with request {@request}, response {@response} and duration {duration}.", $"{svcName}/{method.Name}", _configuration.Name, request, t.Result, duration); } else { _logger.LogError(t.Exception, "End for failed action {action} on client {client} with request {@request} and duration {duration}.", $"{svcName}/{method.Name}", _configuration.Name, request, duration); } } // request end action try { _configuration.DataHandlers.OnRequestEnd?.Invoke(_logger, new RequestEndData { ServiceName = svcName, MethodName = method.Name, HostName = _configuration.Name, Request = request, Response = t.Result, DurationMs = duration, Exception = t.Exception }); } catch (Exception e) { _logger.LogError(e, "Failed to execute reqeust end action."); } }