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); }
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)); } }
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(); }
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); }
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);
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)); }