public void SetUp()
        {
            replica1 = new Uri("http://replica1");
            replica2 = new Uri("http://replica2");

            response1        = new Response(ResponseCode.Ok);
            response2        = new Response(ResponseCode.Ok);
            selectedResponse = new Response(ResponseCode.Ok);

            result1 = new ReplicaResult(replica1, response1, ResponseVerdict.DontKnow, TimeSpan.Zero);
            result2 = new ReplicaResult(replica2, response2, ResponseVerdict.DontKnow, TimeSpan.Zero);

            var log = new ConsoleLog();

            context = new RequestContext(Request.Get("foo/bar"), Substitute.For <IRequestStrategy>(), Budget.Infinite, log, CancellationToken.None, null, int.MaxValue);
            // ReSharper disable AssignNullToNotNullAttribute
            context.Strategy.SendAsync(null, null, null, null, 0, default(CancellationToken))
            // ReSharper restore AssignNullToNotNullAttribute
            .ReturnsForAnyArgs(
                async info =>
            {
                var replicas = info.Arg <IEnumerable <Uri> >();
                var sender   = info.Arg <IRequestSender>();

                foreach (var replica in replicas)
                {
                    await sender.SendToReplicaAsync(replica, context.Request, TimeSpan.Zero, CancellationToken.None);
                }
            });

            clusterProvider = Substitute.For <IClusterProvider>();
            clusterProvider.GetCluster().Returns(new[] { replica1, replica2 });

            requestSender = Substitute.For <IRequestSender>();
            requestSender.SendToReplicaAsync(replica1, Arg.Any <Request>(), Arg.Any <TimeSpan>(), Arg.Any <CancellationToken>()).ReturnsTask(_ => result1);
            requestSender.SendToReplicaAsync(replica2, Arg.Any <Request>(), Arg.Any <TimeSpan>(), Arg.Any <CancellationToken>()).ReturnsTask(_ => result2);

            replicaOrdering = Substitute.For <IReplicaOrdering>();
            // ReSharper disable AssignNullToNotNullAttribute
            replicaOrdering.Order(null, null, null).ReturnsForAnyArgs(info => info.Arg <IList <Uri> >().Reverse());
            // ReSharper restore AssignNullToNotNullAttribute

            responseSelector = Substitute.For <IResponseSelector>();
            // ReSharper disable once AssignNullToNotNullAttribute
            responseSelector.Select(null).ReturnsForAnyArgs(_ => selectedResponse);

            resultStatusSelector = Substitute.For <IClusterResultStatusSelector>();
            // ReSharper disable AssignNullToNotNullAttribute
            resultStatusSelector.Select(null, null).ReturnsForAnyArgs(ClusterResultStatus.Success);
            // ReSharper restore AssignNullToNotNullAttribute

            storageProvider = Substitute.For <IReplicaStorageProvider>();
            module          = new RequestExecutionModule(
                clusterProvider,
                replicaOrdering,
                responseSelector,
                storageProvider,
                requestSender,
                resultStatusSelector);
        }
Exemple #2
0
        public void TestSetup()
        {
            request       = Request.Get("foo/bar");
            replicas      = Enumerable.Range(0, 10).Select(i => new Uri($"http://replica-{i}/")).ToArray();
            resultSources = replicas.ToDictionary(r => r, _ => new TaskCompletionSource <ReplicaResult>());
            parameters    = RequestParameters.Empty.WithConnectionTimeout(1.Seconds());

            sender = Substitute.For <IRequestSender>();
            sender
            .SendToReplicaAsync(Arg.Any <Uri>(), Arg.Any <Request>(), Arg.Any <TimeSpan?>(), Arg.Any <TimeSpan>(), Arg.Any <CancellationToken>())
            .Returns(info => resultSources[info.Arg <Uri>()].Task);

            delaySources           = replicas.Select(_ => new TaskCompletionSource <bool>()).ToList();
            delaySourcesEnumerator = delaySources.GetEnumerator();
            delaysPlanner          = Substitute.For <IForkingDelaysPlanner>();
            SetupDelaysPlanner();

            delaysProvider = Substitute.For <IForkingDelaysProvider>();
            SetupForkingDelays(1.Milliseconds());

            tokenSource = new CancellationTokenSource();
            token       = tokenSource.Token;

            strategy = new ForkingRequestStrategy(delaysProvider, delaysPlanner, 3);
        }
        /// <inheritdoc />
        public async Task SendAsync(Request request, RequestParameters parameters, IRequestSender sender, IRequestTimeBudget budget, IEnumerable <Uri> replicas, int replicasCount, CancellationToken cancellationToken)
        {
            var currentReplicaIndex = 0;

            foreach (var replica in replicas)
            {
                if (budget.HasExpired)
                {
                    break;
                }

                if (request.ContainsAlreadyUsedStream())
                {
                    break;
                }

                var timeout = TimeSpanArithmetics.Min(timeoutsProvider.GetTimeout(request, budget, currentReplicaIndex++, replicasCount), budget.Remaining);

                var connectionAttemptTimeout = currentReplicaIndex == replicasCount ? null : parameters.ConnectionTimeout;

                var result = await sender.SendToReplicaAsync(replica, request, connectionAttemptTimeout, timeout, cancellationToken).ConfigureAwait(false);

                if (result.Verdict == ResponseVerdict.Accept)
                {
                    break;
                }

                cancellationToken.ThrowIfCancellationRequested();
            }
        }
        public async Task SendAsync(Request request, IRequestSender sender, IRequestTimeBudget budget, IEnumerable <Uri> replicas, int replicasCount, CancellationToken cancellationToken)
        {
            var initialRequestCount = Math.Min(parallelismLevel, replicasCount);
            var currentTasks        = new List <Task <ReplicaResult> >(initialRequestCount);

            using (var localCancellationSource = new CancellationTokenSource())
                using (var linkedCancellationSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, localCancellationSource.Token))
                {
                    var linkedCancellationToken = linkedCancellationSource.Token;

                    using (var replicasEnumerator = replicas.GetEnumerator())
                    {
                        for (var i = 0; i < initialRequestCount; i++)
                        {
                            if (!replicasEnumerator.MoveNext())
                            {
                                throw new InvalidOperationException("Replicas enumerator ended prematurely. This is definitely a bug in code.");
                            }

                            currentTasks.Add(sender.SendToReplicaAsync(replicasEnumerator.Current, request, budget.Remaining, linkedCancellationToken));
                        }

                        while (currentTasks.Count > 0)
                        {
                            var completedTask = await Task.WhenAny(currentTasks).ConfigureAwait(false);

                            currentTasks.Remove(completedTask);

                            var completedResult = await completedTask.ConfigureAwait(false);

                            if (completedResult.Verdict == ResponseVerdict.Accept)
                            {
                                localCancellationSource.Cancel();
                                return;
                            }

                            cancellationToken.ThrowIfCancellationRequested();

                            if (replicasEnumerator.MoveNext())
                            {
                                currentTasks.Add(sender.SendToReplicaAsync(replicasEnumerator.Current, request, budget.Remaining, linkedCancellationToken));
                            }
                        }
                    }
                }
        }
        private void LaunchRequest(List <Task> currentTasks, Request request, IRequestTimeBudget budget, IRequestSender sender, IEnumerator <Uri> replicasEnumerator, CancellationToken cancellationToken)
        {
            if (!replicasEnumerator.MoveNext())
            {
                throw new InvalidOperationException("Replicas enumerator ended prematurely. This is definitely a bug in code.");
            }

            currentTasks.Add(sender.SendToReplicaAsync(replicasEnumerator.Current, request, budget.Remaining, cancellationToken));
        }
        private void LaunchRequest(List <Task> currentTasks, Request request, IRequestTimeBudget budget, IRequestSender sender, IEnumerator <Uri> replicasEnumerator, TimeSpan?connectionTimeout, CancellationToken cancellationToken)
        {
            if (!replicasEnumerator.MoveNext())
            {
                throw new InvalidOperationException("Replicas enumerator ended prematurely. This is definitely a bug in code.");
            }

            request = request.WithHeader(HeaderNames.ConcurrencyLevel, currentTasks.Count(task => task is Task <ReplicaResult>) + 1);

            currentTasks.Add(sender.SendToReplicaAsync(replicasEnumerator.Current, request, connectionTimeout, budget.Remaining, cancellationToken));
        }
        public void SetUp()
        {
            request       = Request.Get("foo/bar");
            replicas      = Enumerable.Range(0, 10).Select(i => new Uri($"http://replica-{i}/")).ToArray();
            resultSources = replicas.ToDictionary(r => r, _ => new TaskCompletionSource <ReplicaResult>());

            sender = Substitute.For <IRequestSender>();
            sender
            .SendToReplicaAsync(Arg.Any <Uri>(), Arg.Any <Request>(), Arg.Any <TimeSpan>(), Arg.Any <CancellationToken>())
            .Returns(info => resultSources[info.Arg <Uri>()].Task);

            token = new CancellationTokenSource().Token;

            strategy = new ParallelRequestStrategy(3);
        }
 public Task SendAsync(
     Request request,
     RequestParameters parameters,
     IRequestSender sender,
     IRequestTimeBudget budget,
     IEnumerable <Uri> replicas,
     int replicasCount,
     CancellationToken cancellationToken)
 {
     return(sender.SendToReplicaAsync(
                replicas.Single(),
                request,
                parameters.ConnectionTimeout,
                budget.Remaining,
                cancellationToken));
 }
        public async Task <ReplicaResult> SendToReplicaAsync(Uri replica, Request request, TimeSpan?connectionTimeout, TimeSpan timeout,
                                                             CancellationToken cancellationToken)
        {
            var leftTimeout = timeout;

            if (rateManager.ShouldInjectWithRate(rate))
            {
                leftTimeout = latency > timeout ? TimeSpan.Zero : timeout - latency;
                var addedLatency = leftTimeout > TimeSpan.Zero ? latency : timeout;
                await latencyPerformer.PerformLatencyAsync(addedLatency, cancellationToken).ConfigureAwait(false);
            }

            return(await baseRequestSender
                   .SendToReplicaAsync(replica, request, connectionTimeout, leftTimeout, cancellationToken)
                   .ConfigureAwait(false));
        }
        private static void TryLaunchNextRequest(Request request, IRequestSender sender, IRequestTimeBudget budget, IEnumerator <Uri> replicas, List <Task <ReplicaResult> > currentTasks, TimeSpan?connectionTimeout, CancellationToken cancellationToken)
        {
            if (budget.HasExpired)
            {
                return;
            }

            if (request.ContainsAlreadyUsedStream() || request.ContainsAlreadyUsedContent())
            {
                return;
            }

            if (replicas.MoveNext())
            {
                currentTasks.Add(sender.SendToReplicaAsync(replicas.Current, request, connectionTimeout, budget.Remaining, cancellationToken));
            }
        }
Exemple #11
0
        public void TestSetup()
        {
            replicas = new[]
            {
                new Uri("http://host1/"),
                new Uri("http://host2/")
            };

            request    = Request.Get("foo/bar");
            budget     = Budget.WithRemaining(5.Minutes());
            parameters = RequestParameters.Empty.WithConnectionTimeout(1.Seconds());
            result     = new ReplicaResult(replicas[0], new Response(ResponseCode.NotFound), ResponseVerdict.Accept, TimeSpan.Zero);

            sender = Substitute.For <IRequestSender>();
            sender.SendToReplicaAsync(null, null, parameters.ConnectionTimeout, TimeSpan.Zero, Arg.Any <CancellationToken>()).ReturnsForAnyArgs(_ => result);

            strategy = new SingleReplicaRequestStrategy();
        }
Exemple #12
0
        public void SetUp()
        {
            replica = new Uri("http://replica");
            request = Request.Get("foo/bar");
            result  = new ReplicaResult(replica, new Response(ResponseCode.Ok), ResponseVerdict.Accept, 1.Milliseconds());
            timeout = 1.Minutes();

            resultSource = new TaskCompletionSource <ReplicaResult>();

            baseSender = Substitute.For <IRequestSender>();
            // ReSharper disable AssignNullToNotNullAttribute
            baseSender.SendToReplicaAsync(null, null, TimeSpan.Zero, CancellationToken.None).ReturnsForAnyArgs(_ => resultSource.Task);
            // ReSharper restore AssignNullToNotNullAttribute

            var log = new ConsoleLog();

            context          = new RequestContext(request, Strategy.SingleReplica, Budget.WithRemaining(timeout), log, CancellationToken.None, null, int.MaxValue);
            contextualSender = new ContextualRequestSender(baseSender, context);
        }
Exemple #13
0
        public async Task <ReplicaResult> SendToReplicaAsync(Uri replica, Request request, TimeSpan timeout, CancellationToken cancellationToken)
        {
            context.SetReplicaResult(CreateUnknownResult(replica));

            try
            {
                var result = await sender.SendToReplicaAsync(replica, request, timeout, cancellationToken).ConfigureAwait(false);

                context.SetReplicaResult(result);

                return(result);
            }
            catch (OperationCanceledException)
            {
                context.SetReplicaResult(CreateCanceledResult(replica));

                throw;
            }
        }
        public void SetUp()
        {
            replicas = new[]
            {
                new Uri("http://host1/"),
                new Uri("http://host2/")
            };

            request = Request.Get("foo/bar");
            budget  = Budget.WithRemaining(5.Minutes());
            result  = new ReplicaResult(replicas[0], new Response(ResponseCode.NotFound), ResponseVerdict.Accept, TimeSpan.Zero);

            sender = Substitute.For <IRequestSender>();
            // ReSharper disable AssignNullToNotNullAttribute
            sender.SendToReplicaAsync(null, null, TimeSpan.Zero, Arg.Any <CancellationToken>()).ReturnsForAnyArgs(_ => result);
            // ReSharper restore AssignNullToNotNullAttribute

            strategy = new SingleReplicaRequestStrategy();
        }
        public async Task SendAsync(Request request, IRequestSender sender, IRequestTimeBudget budget, IEnumerable <Uri> replicas, int replicasCount, CancellationToken cancellationToken)
        {
            var currentReplicaIndex = 0;

            foreach (var replica in replicas)
            {
                if (budget.HasExpired)
                {
                    break;
                }

                var timeout = TimeSpanExtensions.Min(timeoutsProvider.GetTimeout(request, budget, currentReplicaIndex++, replicasCount), budget.Remaining);

                var result = await sender.SendToReplicaAsync(replica, request, timeout, cancellationToken).ConfigureAwait(false);

                if (result.Verdict == ResponseVerdict.Accept)
                {
                    break;
                }

                cancellationToken.ThrowIfCancellationRequested();
            }
        }
 /// <inheritdoc />
 public Task SendAsync(Request request, RequestParameters parameters, IRequestSender sender, IRequestTimeBudget budget, IEnumerable <Uri> replicas, int replicasCount, CancellationToken cancellationToken) =>
 sender.SendToReplicaAsync(replicas.First(), request, null, budget.Remaining, cancellationToken);
Exemple #17
0
 public Task SendAsync(Request request, IRequestSender sender, IRequestTimeBudget budget, IEnumerable <Uri> replicas, int replicasCount, CancellationToken cancellationToken)
 {
     return(sender.SendToReplicaAsync(replicas.First(), request, budget.Remaining, cancellationToken));
 }
 private void SetupResult(Uri replica, ResponseVerdict verdict)
 {
     sender
     .SendToReplicaAsync(replica, Arg.Any <Request>(), Arg.Any <TimeSpan?>(), Arg.Any <TimeSpan>(), Arg.Any <CancellationToken>())
     .ReturnsTask(new ReplicaResult(replica, new Response(ResponseCode.Ok), verdict, TimeSpan.Zero));
 }