public static async Task <Stream> CreateAsync(
     Func <long, Stream> responseFactory,
     Func <long, ValueTask <Stream> > asyncResponseFactory,
     ResponseClassifier responseClassifier,
     int maxRetries)
 {
     return(Create(await asyncResponseFactory(0).ConfigureAwait(false), responseFactory, asyncResponseFactory, responseClassifier, maxRetries));
 }
 public static Stream Create(
     Func <long, Stream> responseFactory,
     Func <long, ValueTask <Stream> > asyncResponseFactory,
     ResponseClassifier responseClassifier,
     int maxRetries)
 {
     return(Create(responseFactory(0), responseFactory, asyncResponseFactory, responseClassifier, maxRetries));
 }
 public RetriableStreamImpl(Stream initialStream, Func <long, Stream> streamFactory, Func <long, ValueTask <Stream> > asyncStreamFactory, ResponseClassifier responseClassifier, int maxRetries)
 {
     _initialStream      = EnsureStream(initialStream);
     _currentStream      = EnsureStream(initialStream);
     _streamFactory      = streamFactory;
     _responseClassifier = responseClassifier;
     _asyncStreamFactory = asyncStreamFactory;
     _maxRetries         = maxRetries;
 }
 public static Stream Create(
     Stream initialResponse,
     Func <long, Stream> streamFactory,
     Func <long, ValueTask <Stream> > asyncResponseFactory,
     ResponseClassifier responseClassifier,
     int maxRetries)
 {
     return(new RetriableStreamImpl(initialResponse, streamFactory, asyncResponseFactory, responseClassifier, maxRetries));
 }
        public void DetectsTextContentTypes(string contentType, bool isText, string expectedEncoding)
        {
            var response = new MockResponse(200);

            response.AddHeader(new HttpHeader("Content-Type", contentType));

            Assert.AreEqual(isText, ResponseClassifier.IsTextResponse(response, out var encoding));
            Assert.AreEqual(encoding?.EncodingName, expectedEncoding);
        }
 private Task <Stream> CreateAsync(
     Func <long, Response> responseFactory,
     Func <long, Task <Response> > asyncResponseFactory,
     ResponseClassifier responseClassifier,
     int maxRetries)
 {
     return(IsAsync ?
            RetriableStream.CreateAsync(responseFactory, asyncResponseFactory, responseClassifier, maxRetries) :
            Task.FromResult(RetriableStream.Create(responseFactory, asyncResponseFactory, responseClassifier, maxRetries)));
 }
        public void TreatsAll4xAnd5xAsErrors()
        {
            var classifier  = new ResponseClassifier();
            var httpMessage = new HttpMessage(new MockRequest(), new ResponseClassifier());

            for (int i = 400; i < 600; i++)
            {
                httpMessage.Response = new MockResponse(i);
                Assert.True(classifier.IsErrorResponse(httpMessage));
            }
        }
        public static IList <IRequestModule> BuildChain(IClusterClientConfiguration config, IReplicaStorageProvider storageProvider)
        {
            var responseClassifier   = new ResponseClassifier();
            var requestConverter     = new RequestConverter(config.Log);
            var requestSender        = new RequestSender(config, storageProvider, responseClassifier, requestConverter, config.Transport);
            var resultStatusSelector = new ClusterResultStatusSelector();

            var modules = new List <IRequestModule>(15 + config.Modules?.Count ?? 0)
            {
                new ErrorCatchingModule(),
                new RequestTransformationModule(config.RequestTransforms),
                new OperationNameFallbackModule(),
                new RequestPriorityApplicationModule()
            };

            if (config.Modules != null)
            {
                modules.AddRange(config.Modules);
            }

            if (config.EnableTracing)
            {
                modules.Add(new TracingModule(config.ServiceName));
            }

            modules.Add(new LoggingModule(config.LogRequestDetails, config.LogResultDetails));
            modules.Add(new ResponseTransformationModule(config.ResponseTransforms));
            modules.Add(new ErrorCatchingModule());
            modules.Add(new RequestValidationModule());
            modules.Add(new TimeoutValidationModule());
            modules.Add(new RequestRetryModule(config.RetryPolicy, config.RetryStrategy));

            if (config.AdaptiveThrottling != null)
            {
                modules.Add(new AdaptiveThrottlingModule(config.AdaptiveThrottling));
            }

            if (config.ReplicaBudgeting != null)
            {
                modules.Add(new ReplicaBudgetingModule(config.ReplicaBudgeting));
            }

            modules.Add(new AbsoluteUrlSenderModule(config.Transport, responseClassifier, config.ResponseCriteria, resultStatusSelector));
            modules.Add(new RequestExecutionModule(config.ClusterProvider, config.ReplicaOrdering, config.ResponseSelector,
                                                   storageProvider, requestSender, resultStatusSelector));

            return(modules);
        }
Beispiel #9
0
        public static IList <IRequestModule> BuildChain(IClusterClientConfiguration config, IReplicaStorageProvider storageProvider)
        {
            var responseClassifier   = new ResponseClassifier();
            var requestConverter     = new RequestConverter(config.Log, config.DeduplicateRequestUrl);
            var requestSender        = new RequestSender(config, storageProvider, responseClassifier, requestConverter);
            var resultStatusSelector = new ClusterResultStatusSelector();

            // ReSharper disable once UseObjectOrCollectionInitializer
            var modules = new List <IRequestModule>(12 + config.Modules?.Sum(x => x.Value.Count) ?? 0);

            var addedModules = new HashSet <Type>();

            AddModule(new LeakPreventionModule());
            AddModule(new GlobalErrorCatchingModule());
            AddModule(new RequestTransformationModule(config.RequestTransforms));
            AddModule(new AuxiliaryHeadersModule());

            // -->> user-defined modules by default inserted here <<-- //

            AddModule(new LoggingModule(config.Logging.LogRequestDetails, config.Logging.LogResultDetails, config.TargetServiceName));
            AddModule(new ResponseTransformationModule(config.ResponseTransforms));
            AddModule(new ErrorCatchingModule());
            AddModule(new RequestValidationModule());

            AddModule(new TimeoutValidationModule());
            AddModule(new RequestRetryModule(config.RetryPolicy, config.RetryStrategyEx));

            // -->> adaptive throttling module <<-- //

            AddModule(new AbsoluteUrlSenderModule(responseClassifier, config.ResponseCriteria, resultStatusSelector));

            // -->> replica budgeting module <<-- //

            // -->> service-mesh module is injected before RequestExecutionModule <<-- //

            AddModule(
                new RequestExecutionModule(
                    config.ResponseSelector,
                    storageProvider,
                    requestSender,
                    resultStatusSelector));

            return(modules);

            void AddModules(IEnumerable <IRequestModule> modulesRange)
            {
                if (modulesRange == null)
                {
                    return;
                }

                foreach (var module in modulesRange)
                {
                    AddModule(module);
                }
            }

            void AddModule(IRequestModule module)
            {
                if (config.ModulesToRemove.Contains(module.GetType()))
                {
                    return;
                }

                var moduleType = module.GetType();

                var isNewModule = addedModules.Add(moduleType);

                if (!isNewModule || config.Modules == null)
                {
                    modules.Add(module);
                    return;
                }

                var relatedModules = config.Modules.TryGetValue(moduleType, out var v) ? v : null;

                AddModules(relatedModules?.Before);
                modules.Add(module);
                AddModules(relatedModules?.After);
            }
        }
Beispiel #10
0
        private static async Task ProcessAsync(HttpPipelineMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline, bool async)
        {
            if (!s_eventSource.IsEnabled())
            {
                if (async)
                {
                    await ProcessNextAsync(pipeline, message).ConfigureAwait(false);
                }
                else
                {
                    ProcessNext(pipeline, message);
                }
                return;
            }

            s_eventSource.Request(message.Request);

            Encoding requestTextEncoding = null;

            if (message.Request.TryGetHeader(HttpHeader.Names.ContentType, out var contentType) && IsTextContentType(contentType))
            {
                requestTextEncoding = Encoding.UTF8;
            }

            if (message.Request.Content != null)
            {
                if (requestTextEncoding != null)
                {
                    if (async)
                    {
                        await s_eventSource.RequestContentTextAsync(message.Request, requestTextEncoding, message.Cancellation);
                    }
                    else
                    {
                        s_eventSource.RequestContentText(message.Request, requestTextEncoding, message.Cancellation);
                    }
                }
                else
                {
                    if (async)
                    {
                        await s_eventSource.RequestContentAsync(message.Request, message.Cancellation);
                    }
                    else
                    {
                        s_eventSource.RequestContent(message.Request, message.Cancellation);
                    }
                }
            }

            var before = Stopwatch.GetTimestamp();

            if (async)
            {
                await ProcessNextAsync(pipeline, message).ConfigureAwait(false);
            }
            else
            {
                ProcessNext(pipeline, message);
            }

            var after = Stopwatch.GetTimestamp();

            bool isError = message.ResponseClassifier.IsErrorResponse(message.Response);

            var textResponse = ResponseClassifier.IsTextResponse(message.Response, out Encoding responseTextEncoding);

            bool wrapResponseStream = s_eventSource.ShouldLogContent(isError) && message.Response.ContentStream?.CanSeek == false;

            if (wrapResponseStream)
            {
                message.Response.ContentStream = new LoggingStream(
                    message.Response.ClientRequestId, s_eventSource, message.Response.ContentStream, isError, responseTextEncoding);
            }

            if (isError)
            {
                s_eventSource.ErrorResponse(message.Response);

                if (!wrapResponseStream && message.Response.ContentStream != null)
                {
                    if (textResponse)
                    {
                        if (async)
                        {
                            await s_eventSource.ErrorResponseContentTextAsync(message.Response, responseTextEncoding, message.Cancellation).ConfigureAwait(false);
                        }
                        else
                        {
                            s_eventSource.ErrorResponseContentText(message.Response, responseTextEncoding, message.Cancellation);
                        }
                    }
                    else
                    {
                        if (async)
                        {
                            await s_eventSource.ErrorResponseContentAsync(message.Response, message.Cancellation).ConfigureAwait(false);
                        }
                        else
                        {
                            s_eventSource.ErrorResponseContent(message.Response);
                        }
                    }
                }
            }

            s_eventSource.Response(message.Response);

            if (!wrapResponseStream && message.Response.ContentStream != null)
            {
                if (textResponse)
                {
                    await s_eventSource.ResponseContentTextAsync(message.Response, responseTextEncoding, message.Cancellation).ConfigureAwait(false);
                }
                else
                {
                    await s_eventSource.ResponseContentAsync(message.Response, message.Cancellation).ConfigureAwait(false);
                }
            }

            var elapsedMilliseconds = (after - before) * 1000 / s_frequency;

            if (elapsedMilliseconds > s_delayWarningThreshold)
            {
                s_eventSource.ResponseDelay(message.Response, elapsedMilliseconds);
            }
        }
        public void DoesntRetryRequestFailedExceptionsWithStatusCode()
        {
            var classifier = new ResponseClassifier();

            Assert.False(classifier.IsRetriableException(new RequestFailedException(500, "IO Exception")));
        }
        public void RetriesRequestFailedExceptionsWithoutCode()
        {
            var classifier = new ResponseClassifier();

            Assert.True(classifier.IsRetriableException(new RequestFailedException(0, "IO Exception")));
        }
Beispiel #13
0
 protected async Task <Response> SendGetRequest(HttpPipelineTransport transport, HttpPipelinePolicy policy, ResponseClassifier responseClassifier = null)
 {
     using Request request  = transport.CreateRequest();
     request.Method         = RequestMethod.Get;
     request.UriBuilder.Uri = new Uri("http://example.com");
     return(await SendRequestAsync(transport, request, policy, responseClassifier));
 }
        protected static async Task <Response> SendGetRequest(HttpPipelineTransport transport, HttpPipelinePolicy policy, ResponseClassifier responseClassifier = null)
        {
            Assert.IsInstanceOf <HttpPipelineSynchronousPolicy>(policy, "Use SyncAsyncPolicyTestBase base type for non-sync policies");

            using (Request request = transport.CreateRequest())
            {
                request.Method = RequestMethod.Get;
                request.Uri.Reset(new Uri("http://example.com"));
                var pipeline = new HttpPipeline(transport, new[] { policy }, responseClassifier);
                return(await pipeline.SendRequestAsync(request, CancellationToken.None));
            }
        }
        protected async Task <Response> SendRequestAsync(HttpPipelineTransport transport, Action <Request> requestAction, HttpPipelinePolicy policy, ResponseClassifier responseClassifier = null, bool bufferResponse = true, CancellationToken cancellationToken = default)
        {
            await Task.Yield();

            var pipeline = new HttpPipeline(transport, new[] { policy }, responseClassifier);

            return(await SendRequestAsync(pipeline, requestAction, bufferResponse, cancellationToken));
        }
 protected Task <Response> SendRequestAsync(HttpPipelineTransport transport, Action <Request> requestAction, HttpPipelinePolicy policy, ResponseClassifier responseClassifier = null, bool bufferResponse = true, CancellationToken cancellationToken = default)
 {
     return(SendRequestAsync(transport, message => requestAction(message.Request), policy, responseClassifier, bufferResponse, cancellationToken));
 }
Beispiel #17
0
 public PerCallResponseClassifier(ResponseClassifier inner, List <HttpMessageClassifier> classifiers)
 {
     _inner       = inner;
     _classifiers = classifiers;
 }
 public HttpMessage(Request request, ResponseClassifier responseClassifier)
 {
     Request            = request ?? throw new ArgumentNullException(nameof(request));
     ResponseClassifier = responseClassifier;
 }
 protected async Task <Response> SendGetRequest(HttpPipelineTransport transport, HttpPipelinePolicy policy, ResponseClassifier responseClassifier = null, bool bufferResponse = true, Uri uri = null, CancellationToken cancellationToken = default)
 {
     return(await SendRequestAsync(transport, request =>
     {
         request.Method = RequestMethod.Get;
         request.Uri.Reset(uri ?? new Uri("http://example.com"));
     }, policy, responseClassifier, bufferResponse, cancellationToken));
 }
Beispiel #20
0
 protected async Task <Response> SendGetRequest(HttpPipelineTransport transport, HttpPipelinePolicy policy, ResponseClassifier responseClassifier = null, bool bufferResponse = true)
 {
     return(await SendRequestAsync(transport, request =>
     {
         request.Method = RequestMethod.Get;
         request.Uri.Reset(new Uri("http://example.com"));
     }, policy, responseClassifier, bufferResponse));
 }
Beispiel #21
0
        protected async Task <Response> SendRequestAsync(HttpPipelineTransport transport, Request request, HttpPipelinePolicy policy, ResponseClassifier responseClassifier = null)
        {
            await Task.Yield();

            var pipeline = new HttpPipeline(transport, new [] { policy }, responseClassifier);

            return(await SendRequestAsync(pipeline, request, CancellationToken.None));
        }
Beispiel #22
0
        protected async Task <Response> SendGetRequest(HttpPipelineTransport transport, HttpPipelinePolicy policy, ResponseClassifier responseClassifier = null)
        {
            await Task.Yield();

            using (Request request = transport.CreateRequest())
            {
                request.Method         = HttpPipelineMethod.Get;
                request.UriBuilder.Uri = new Uri("http://example.com");
                var pipeline = new HttpPipeline(transport, new [] { policy }, responseClassifier);
                return(await SendRequestAsync(pipeline, request, CancellationToken.None));
            }
        }
 public void SetUp()
 {
     criteria   = new List <IResponseCriterion>();
     classifier = new ResponseClassifier();
     response   = Responses.Timeout;
 }
Beispiel #24
0
 protected static Task <Response> SendRequest(MockTransport mockTransport, HttpPipelinePolicy policy, ResponseClassifier responseClassifier)
 {
     return(SendGetRequest(mockTransport, policy, responseClassifier));
 }