Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSHARP-3757: Redirect read/write retries to other mongos if possible #1304

Open
wants to merge 17 commits into
base: master
Choose a base branch
from

Conversation

adelinowona
Copy link
Contributor

Description

On a sharded cluster, retrying reads and writes will attempt to prioritize other mongos for selection if available.

What is changing?

  • Server selection now takes a collection of servers to deprioritize and will attempt to exclude those servers when the topology is sharded and multiple mongoses are present.
  • Adds unit tests for server selection and prose tests for retryable reads and writes.
  • Adds functionality to provide a collection of servers to deprioritize in relevant places.

@adelinowona adelinowona requested a review from a team as a code owner April 10, 2024 23:13

var deprioritizedServers = new List<ServerDescription> { connected1 };

for (int i = 0; i < 15; i++)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running multiple times to account for server selection randomness and guarantee we get the expected result for each run.

@adelinowona adelinowona removed the request for review from a team April 10, 2024 23:24
Copy link
Contributor

@BorisDog BorisDog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, few minor comments.

src/MongoDB.Driver.Core/Core/Clusters/Cluster.cs Outdated Show resolved Hide resolved
/// <returns>The selected server.</returns>
IServer SelectServer(IServerSelector selector, CancellationToken cancellationToken);
IServer SelectServer(IServerSelector selector, CancellationToken cancellationToken, IReadOnlyCollection<ServerDescription> deprioritizedServers = null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider having augmenting IServerSelector to account for deprioritizedServers.

@adelinowona adelinowona requested a review from BorisDog May 22, 2024 21:17
Copy link
Contributor

@BorisDog BorisDog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some minor comments.

var selector = deprioritizedServers != null
? (IServerSelector)new CompositeServerSelector(new IServerSelector[] { new PriorityServerSelector(deprioritizedServers), writableServerSelector })
: writableServerSelector;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

selector = deprioritizedServers != null
                ? new CompositeServerSelector(new[] { new PriorityServerSelector(deprioritizedServers), selector })
                : selector;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new IServerSelector[] -> new[]

src/MongoDB.Driver.Core/Core/Clusters/ICluster.cs Outdated Show resolved Hide resolved
@adelinowona adelinowona requested a review from BorisDog May 24, 2024 23:37

[Theory]
[ParameterAttributeData]
public async void SelectServer_should_return_deprioritized_servers_if_no_other_servers_exist_or_cluster_not_sharded(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgot to mention that async method should return Task, for better clarity.

@@ -53,7 +53,7 @@ public static TResult Execute<TResult>(IRetryableWriteOperation<TResult> operati

try
{
context.ReplaceChannelSource(context.Binding.GetWriteChannelSource(cancellationToken));
context.ReplaceChannelSource(context.Binding.GetWriteChannelSource(new [] { context.ChannelSource.ServerDescription }, cancellationToken));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the extra space in new [] --> new[]

/// <summary>
/// Represents a server selector that selects servers based on a collection of servers to deprioritize.
/// </summary>
public sealed class PriorityServerSelector : IServerSelector
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably should have few very basic tests for this selector. like EndPointServerSelectorTests

var selector = deprioritizedServers != null
? (IServerSelector)new CompositeServerSelector(new IServerSelector[] { new PriorityServerSelector(deprioritizedServers), writableServerSelector })
: writableServerSelector;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new IServerSelector[] -> new[]

return CreateServerChannelSource(server);
}

/// <inheritdoc/>
public async Task<IChannelSourceHandle> GetWriteChannelSourceAsync(IMayUseSecondaryCriteria mayUseSecondary, CancellationToken cancellationToken)
{
return await GetWriteChannelSourceAsync(null, mayUseSecondary, cancellationToken).ConfigureAwait(false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to await, can just return the task.
Additional await might create addition wrapping task object.

var writableServerSelector = new WritableServerSelector(mayUseSecondary);

var selector = deprioritizedServers != null
? (IServerSelector)new CompositeServerSelector(new IServerSelector[] { new PriorityServerSelector(deprioritizedServers), writableServerSelector })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment applies here

/// <param name="deprioritizedServers">The collection of servers to deprioritize.</param>
public PriorityServerSelector(IReadOnlyCollection<ServerDescription> deprioritizedServers)
{
_deprioritizedServers = Ensure.IsNotNull(deprioritizedServers, nameof(deprioritizedServers));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be IsNotNullOrEmpty maybe?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants