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 11 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.

/// <param name="deprioritizedServers">The deprioritized servers.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>A channel source.</returns>
IChannelSourceHandle GetReadChannelSource(IReadOnlyCollection<ServerDescription> deprioritizedServers, CancellationToken cancellationToken);
Copy link
Contributor

Choose a reason for hiding this comment

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

This interface is pseudo public (going to be hidden in 3.0), and we are introducing a breaking change anyway.
So should we consider just adding a parameter to the existing method?

src/MongoDB.Driver.Core/Core/Clusters/Cluster.cs Outdated Show resolved Hide resolved

subject.Initialize();

var endPoint1 = new DnsEndPoint("localhost", 27017);
Copy link
Contributor

Choose a reason for hiding this comment

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

minor: add simple test to validate deprioritizedServers == null case

IServer result;
if (async)
{
result = subject.SelectServerAsync(selector, deprioritizedServers, CancellationToken.None).GetAwaiter().GetResult();
Copy link
Contributor

Choose a reason for hiding this comment

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

Make the test return Task, and just await here.

@@ -77,14 +76,14 @@ public void Dispose()
}

/// <inheritdoc/>
public IChannelSourceHandle GetReadChannelSource(CancellationToken cancellationToken)
public IChannelSourceHandle GetReadChannelSource(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.

There is a convention that cancellationToken has to be a last parameter.

List<ServerDescription> filteredServers = new();
foreach (var description in _description.Servers)
{
if (!deprioritizedServers.Contains(description, new ServerDescriptionComparer()))
Copy link
Contributor

Choose a reason for hiding this comment

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

micro-optimization: could use single instance of comparer.
Or maybe the following would be slightly simpler:
if (deprioritizedServers.All(d => d.EndPoint != description.Endpoint))

/// <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.

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