From 185b49b43025089322a06c8b8ebb6c8de058e501 Mon Sep 17 00:00:00 2001 From: Omer Ratsaby Date: Tue, 18 Jul 2023 11:18:10 +0300 Subject: [PATCH 1/4] RavenDB_19900: added an option to modify the timeout of GetDatabaseTopologyCommand --- src/Raven.Client/Http/RavenCommand.cs | 2 +- src/Raven.Client/Http/RequestExecutor.cs | 5 +++ test/SlowTests/Issues/RavenDB_19900.cs | 45 ++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 test/SlowTests/Issues/RavenDB_19900.cs 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); + } + } + } + + } +} + From 814e890b95e37561de00d86e5ccddb1e15f971e0 Mon Sep 17 00:00:00 2001 From: Omer Ratsaby Date: Tue, 18 Jul 2023 15:55:28 +0300 Subject: [PATCH 2/4] RavenDB_19900: addressed pr comments --- src/Raven.Client/Http/RavenCommand.cs | 2 +- src/Raven.Client/Http/RequestExecutor.cs | 6 +++--- test/SlowTests/Issues/RavenDB_19900.cs | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Raven.Client/Http/RavenCommand.cs b/src/Raven.Client/Http/RavenCommand.cs index 3cb07d16167..b11c84a981f 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; internal set; } + public TimeSpan? Timeout { get; protected 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 406d1472ec0..fff26b390ef 100644 --- a/src/Raven.Client/Http/RequestExecutor.cs +++ b/src/Raven.Client/Http/RequestExecutor.cs @@ -485,8 +485,8 @@ 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(); + if (DefaultTimeout.HasValue && DefaultTimeout.Value > command.Timeout) + command.Timeout = DefaultTimeout.Value; await ExecuteAsync(parameters.Node, null, context, command, shouldRetry: false, sessionInfo: null, token: CancellationToken.None).ConfigureAwait(false); var topology = command.Result; @@ -2369,7 +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); + internal Action DelayRequest; } } } diff --git a/test/SlowTests/Issues/RavenDB_19900.cs b/test/SlowTests/Issues/RavenDB_19900.cs index 60b270fa156..b08135e4731 100644 --- a/test/SlowTests/Issues/RavenDB_19900.cs +++ b/test/SlowTests/Issues/RavenDB_19900.cs @@ -2,6 +2,7 @@ using Xunit; using Xunit.Abstractions; using System; +using System.Threading; using Raven.Client.Http; using Tests.Infrastructure; @@ -23,7 +24,7 @@ public async Task UpdateTopologyTimeoutBehaviourShouldBeAccordingToConfiguration var executor = store.GetRequestExecutor(); // delaying response should result in UpdateTopology timeout - var testingStuff = executor.ForTestingPurposesOnly(); + executor.ForTestingPurposesOnly().DelayRequest = () => { Thread.Sleep(18000); }; var e = await Assert.ThrowsAsync(async () => await UpdateTopology()); Assert.Contains("failed with timeout after 00:00:15", e.ToString()); From 440d2afd6ca4a62924de125fd268a158927d8442 Mon Sep 17 00:00:00 2001 From: Omer Ratsaby Date: Tue, 25 Jul 2023 15:56:37 +0300 Subject: [PATCH 3/4] RavenDB-19900: reduced test exec time --- src/Raven.Client/Http/RequestExecutor.cs | 4 +++ test/SlowTests/Issues/RavenDB_19900.cs | 42 +++++++++++++++--------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/Raven.Client/Http/RequestExecutor.cs b/src/Raven.Client/Http/RequestExecutor.cs index fff26b390ef..9f64e37df13 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 (ForTestingPurposes != null && ForTestingPurposes.timeout != TimeSpan.Zero) + command.Timeout = ForTestingPurposes.timeout; + if (DefaultTimeout.HasValue && DefaultTimeout.Value > command.Timeout) command.Timeout = DefaultTimeout.Value; @@ -2370,6 +2373,7 @@ internal TestingStuff(RequestExecutor requestExecutor) internal ConcurrentDictionary> FailedNodesTimers => _requestExecutor._failedNodesTimers; internal (int Index, ServerNode Node) PreferredNode => _requestExecutor._nodeSelector.GetPreferredNode(); internal Action DelayRequest; + internal TimeSpan timeout; } } } diff --git a/test/SlowTests/Issues/RavenDB_19900.cs b/test/SlowTests/Issues/RavenDB_19900.cs index b08135e4731..635b2ad131d 100644 --- a/test/SlowTests/Issues/RavenDB_19900.cs +++ b/test/SlowTests/Issues/RavenDB_19900.cs @@ -18,29 +18,41 @@ public RavenDB_19900(ITestOutputHelper output) : base(output) [Fact] public async Task UpdateTopologyTimeoutBehaviourShouldBeAccordingToConfiguration() { - var timeout1 = TimeSpan.FromSeconds(20); + var generalTimeout = TimeSpan.FromSeconds(3); + var customCommandTimeout = TimeSpan.FromSeconds(1); + var delay = 2000; + using (var store = GetDocumentStore()) { var executor = store.GetRequestExecutor(); - // delaying response should result in UpdateTopology timeout - executor.ForTestingPurposesOnly().DelayRequest = () => { Thread.Sleep(18000); }; - 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() + try { - var node = executor.GetPreferredNode().Result.Node; - var topologyUpdateCommand = new RequestExecutor.UpdateTopologyParameters(node); - await executor.UpdateTopologyAsync(topologyUpdateCommand); + // delaying response should result in UpdateTopology timeout + executor.ForTestingPurposesOnly().DelayRequest = () => { Thread.Sleep(delay); }; + executor.ForTestingPurposesOnly().timeout = customCommandTimeout; + var e = await Assert.ThrowsAsync(async () => await UpdateTopology()); + Assert.Contains("failed with timeout after 00:00:01", e.ToString()); + + // increasing the general timeout should let UpdateTopology() to be executed + using (store.SetRequestTimeout(generalTimeout)) + { + await UpdateTopology(); + } + + async Task UpdateTopology() + { + var node = executor.GetPreferredNode().Result.Node; + var topologyUpdateCommand = new RequestExecutor.UpdateTopologyParameters(node); + await executor.UpdateTopologyAsync(topologyUpdateCommand); + } + } + finally + { + executor.ForTestingPurposes = null; } } } - } } From 2ec4c297b8b95db18d9d1fd138424e8d640359ed Mon Sep 17 00:00:00 2001 From: Omer Ratsaby Date: Wed, 26 Jul 2023 09:35:50 +0300 Subject: [PATCH 4/4] RavenDB-19900: changed test to use Action --- src/Raven.Client/Http/RequestExecutor.cs | 5 ++--- test/SlowTests/Issues/RavenDB_19900.cs | 9 ++++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Raven.Client/Http/RequestExecutor.cs b/src/Raven.Client/Http/RequestExecutor.cs index 9f64e37df13..068f6438b59 100644 --- a/src/Raven.Client/Http/RequestExecutor.cs +++ b/src/Raven.Client/Http/RequestExecutor.cs @@ -485,8 +485,7 @@ 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 (ForTestingPurposes != null && ForTestingPurposes.timeout != TimeSpan.Zero) - command.Timeout = ForTestingPurposes.timeout; + ForTestingPurposes?.SetCommandTimeout?.Invoke(command); if (DefaultTimeout.HasValue && DefaultTimeout.Value > command.Timeout) command.Timeout = DefaultTimeout.Value; @@ -2373,7 +2372,7 @@ internal TestingStuff(RequestExecutor requestExecutor) internal ConcurrentDictionary> FailedNodesTimers => _requestExecutor._failedNodesTimers; internal (int Index, ServerNode Node) PreferredNode => _requestExecutor._nodeSelector.GetPreferredNode(); internal Action DelayRequest; - internal TimeSpan timeout; + internal Action SetCommandTimeout; } } } diff --git a/test/SlowTests/Issues/RavenDB_19900.cs b/test/SlowTests/Issues/RavenDB_19900.cs index 635b2ad131d..81de1cee3d2 100644 --- a/test/SlowTests/Issues/RavenDB_19900.cs +++ b/test/SlowTests/Issues/RavenDB_19900.cs @@ -3,13 +3,13 @@ using Xunit.Abstractions; using System; using System.Threading; +using FastTests; using Raven.Client.Http; -using Tests.Infrastructure; namespace SlowTests.Issues { - public class RavenDB_19900 : ClusterTestBase + public class RavenDB_19900 : RavenTestBase { public RavenDB_19900(ITestOutputHelper output) : base(output) { @@ -30,7 +30,10 @@ public async Task UpdateTopologyTimeoutBehaviourShouldBeAccordingToConfiguration { // delaying response should result in UpdateTopology timeout executor.ForTestingPurposesOnly().DelayRequest = () => { Thread.Sleep(delay); }; - executor.ForTestingPurposesOnly().timeout = customCommandTimeout; + executor.ForTestingPurposesOnly().SetCommandTimeout = (command) => + { + command.Timeout = customCommandTimeout; + }; var e = await Assert.ThrowsAsync(async () => await UpdateTopology()); Assert.Contains("failed with timeout after 00:00:01", e.ToString());