diff --git a/src/Raven.Client/Http/RavenCommand.cs b/src/Raven.Client/Http/RavenCommand.cs index 26e9c0b8f35..3cb07d16167 100644 --- a/src/Raven.Client/Http/RavenCommand.cs +++ b/src/Raven.Client/Http/RavenCommand.cs @@ -57,7 +57,7 @@ public abstract class RavenCommand public RavenCommandResponseType ResponseType { get; protected set; } - public TimeSpan? Timeout { get; protected set; } + public TimeSpan? Timeout { get; internal set; } public bool CanCache { get; protected set; } public bool CanCacheAggressively { get; protected set; } public string SelectedNodeTag { get; protected set; } diff --git a/src/Raven.Client/Http/RequestExecutor.cs b/src/Raven.Client/Http/RequestExecutor.cs index a515073e199..406d1472ec0 100644 --- a/src/Raven.Client/Http/RequestExecutor.cs +++ b/src/Raven.Client/Http/RequestExecutor.cs @@ -485,6 +485,9 @@ public virtual async Task UpdateTopologyAsync(UpdateTopologyParameters par using (ContextPool.AllocateOperationContext(out JsonOperationContext context)) { var command = new GetDatabaseTopologyCommand(parameters.DebugTag, Conventions.SendApplicationIdentifier ? parameters.ApplicationIdentifier : null); + if (DefaultTimeout.HasValue) + command.Timeout = new[] { DefaultTimeout, command.Timeout }.Max(); + await ExecuteAsync(parameters.Node, null, context, command, shouldRetry: false, sessionInfo: null, token: CancellationToken.None).ConfigureAwait(false); var topology = command.Result; @@ -992,6 +995,7 @@ private async Task SendRequestToServer( cts.CancelAfter(timeout.Value); try { + ForTestingPurposes?.DelayRequest?.Invoke(); return await SendAsync(chosenNode, command, sessionInfo, request, cts.Token).ConfigureAwait(false); } catch (OperationCanceledException e) @@ -2365,6 +2369,7 @@ internal TestingStuff(RequestExecutor requestExecutor) internal int[] NodeSelectorFailures => _requestExecutor._nodeSelector.NodeSelectorFailures; internal ConcurrentDictionary> FailedNodesTimers => _requestExecutor._failedNodesTimers; internal (int Index, ServerNode Node) PreferredNode => _requestExecutor._nodeSelector.GetPreferredNode(); + internal Action DelayRequest => () => Thread.Sleep(18000); } } } diff --git a/test/SlowTests/Issues/RavenDB_19900.cs b/test/SlowTests/Issues/RavenDB_19900.cs new file mode 100644 index 00000000000..60b270fa156 --- /dev/null +++ b/test/SlowTests/Issues/RavenDB_19900.cs @@ -0,0 +1,45 @@ +using System.Threading.Tasks; +using Xunit; +using Xunit.Abstractions; +using System; +using Raven.Client.Http; +using Tests.Infrastructure; + + +namespace SlowTests.Issues +{ + public class RavenDB_19900 : ClusterTestBase + { + public RavenDB_19900(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public async Task UpdateTopologyTimeoutBehaviourShouldBeAccordingToConfiguration() + { + var timeout1 = TimeSpan.FromSeconds(20); + using (var store = GetDocumentStore()) + { + var executor = store.GetRequestExecutor(); + + // delaying response should result in UpdateTopology timeout + var testingStuff = executor.ForTestingPurposesOnly(); + var e = await Assert.ThrowsAsync(async () => await UpdateTopology()); + Assert.Contains("failed with timeout after 00:00:15", e.ToString()); + + // increasing the general timeout should let UpdateTopology() to be executed + store.SetRequestTimeout(timeout1); + await UpdateTopology(); + + async Task UpdateTopology() + { + var node = executor.GetPreferredNode().Result.Node; + var topologyUpdateCommand = new RequestExecutor.UpdateTopologyParameters(node); + await executor.UpdateTopologyAsync(topologyUpdateCommand); + } + } + } + + } +} +