Uploaded image for project: 'C# Driver'
  1. C# Driver
  2. CSHARP-5282

C# driver fails to connect to DB Atlas 50% of the time

    • Type: Icon: Bug Bug
    • Resolution: Unresolved
    • Priority: Icon: Unknown Unknown
    • None
    • Affects Version/s: 2.21.0, 2.28.0
    • Component/s: Connectivity
    • None
    • Dotnet Drivers

      Summary

      The C# driver fails to connect to the MongoDB Atlas M10 cluster some times. This happens around 40-50% of the times, and a retry usually succeeds. It also gets stuck on the connecting part for a long time (around 30 seconds) after which it times out.

      This bug is not found in for example the Rust driver which always connects withing a couple hundred ms. 

      Please provide the version of the driver. If applicable, please provide the MongoDB server version and topology (standalone, replica set, or sharded cluster).

      The C# driver versions that I have tested are 2.21 and 2.28. Our Atlas cluster is running 7.0.2. This was tested on Windows 11. We are using .Net 8.

      How to Reproduce

      1. Create a Mongo Atlas cluster.
      2. Verify connection using Compass or some other software.
      3. Run the C# code.
      4. If it succeeds, run it again until it fails, usually for me it fails around 50% of the times.

      Code for C#:

      using MongoDB.Driver;
      using MongoDB.Bson;
      var connectionString = "mongodb+srv://some connection string to an atlas cluster";
      
      Console.WriteLine("Started test");
      for (int idx = 0; idx < 100; idx++){
          var client = new MongoClient(connectionString);
          var collection = client.GetDatabase("database").GetCollection<MongoDataObj>("collection");
          var filter = Builders<MongoDataObj>.Filter.Eq("Content", "foobar");
          var document = collection.Find(filter).First();
          Console.WriteLine($"Search nr: {idx}");
          Console.WriteLine(document._id);
          Console.WriteLine(document.Content);
          Console.WriteLine("-----------------------------------");}
      
      public class MongoDataObj{
          public ObjectId _id { get; set; }
          public string Content { get; set; }
      } 

      This will fail with one of these errors:

      Unhandled exception. System.TimeoutException: A timeout occurred after 30000ms selecting a server using CompositeServerSelector{ Selectors = ReadPreferenceServerSelector{ ReadPreference = { Mode : Primary } }, LatencyLimitingServerSelector{ AllowedLatencyRange = 00:00:00.0150000 }, OperationsCountServerSelector }. Client view of cluster state is { ClusterId : "1", ConnectionMode : "ReplicaSet", Type : "ReplicaSet", State : "Disconnected", Servers : [{ ServerId: "{ ClusterId : 1, EndPoint : "Unspecified/server-01:27017" }", EndPoint: "Unspecified/server-01:27017", ReasonChanged: "ServerInitialDescription", State: "Disconnected", ServerVersion: , TopologyVersion: , Type: "Unknown", LastHeartbeatTimestamp: null, LastUpdateTimestamp: "2024-09-17T09:24:19.8985270Z" }, { ServerId: "{ ClusterId : 1, EndPoint : "Unspecified/server-02:27017" }", EndPoint: "Unspecified/server-02:27017", ReasonChanged: "ServerInitialDescription", State: "Disconnected", ServerVersion: , TopologyVersion: , Type: "Unknown", LastHeartbeatTimestamp: null, LastUpdateTimestamp: "2024-09-17T09:24:19.8995270Z" }, { ServerId: "{ ClusterId : 1, EndPoint : "Unspecified/server-03:27017" }", EndPoint: "Unspecified/server-03:27017", ReasonChanged: "ServerInitialDescription", State: "Disconnected", ServerVersion: , TopologyVersion: , Type: "Unknown", LastHeartbeatTimestamp: null, LastUpdateTimestamp: "2024-09-17T09:24:19.9006273Z" }] }.
      at MongoDB.Driver.Core.Clusters.Cluster.ThrowTimeoutException(IServerSelector selector, ClusterDescription description)
         at MongoDB.Driver.Core.Clusters.Cluster.SelectServerHelper.WaitingForDescriptionToChange()
         at MongoDB.Driver.Core.Clusters.Cluster.SelectServer(IServerSelector selector, CancellationToken cancellationToken)
         at MongoDB.Driver.Core.Clusters.IClusterExtensions.SelectServerAndPinIfNeeded(ICluster cluster, ICoreSessionHandle session, IServerSelector selector, IReadOnlyCollection`1 deprioritizedServers, CancellationToken cancellationToken)
         at MongoDB.Driver.Core.Bindings.ReadPreferenceBinding.GetReadChannelSource(IReadOnlyCollection`1 deprioritizedServers, CancellationToken cancellationToken)
         at MongoDB.Driver.Core.Bindings.ReadPreferenceBinding.GetReadChannelSource(CancellationToken cancellationToken)
         at MongoDB.Driver.Core.Bindings.ReadBindingHandle.GetReadChannelSource(CancellationToken cancellationToken)
         at MongoDB.Driver.Core.Operations.RetryableReadContext.Initialize(CancellationToken cancellationToken)
         at MongoDB.Driver.Core.Operations.RetryableReadContext.Create(IReadBinding binding, Boolean retryRequested, CancellationToken cancellationToken)
         at MongoDB.Driver.Core.Operations.FindOperation`1.Execute(IReadBinding binding, CancellationToken cancellationToken)
         at MongoDB.Driver.OperationExecutor.ExecuteReadOperation[TResult](IReadBinding binding, IReadOperation`1 operation, CancellationToken cancellationToken)
         at MongoDB.Driver.MongoCollectionImpl`1.ExecuteReadOperation[TResult](IClientSessionHandle session, IReadOperation`1 operation, ReadPreference readPreference, CancellationToken cancellationToken)
         at MongoDB.Driver.MongoCollectionImpl`1.ExecuteReadOperation[TResult](IClientSessionHandle session, IReadOperation`1 operation, CancellationToken cancellationToken)
         at MongoDB.Driver.MongoCollectionImpl`1.FindSync[TProjection](IClientSessionHandle session, FilterDefinition`1 filter, FindOptions`2 options, CancellationToken cancellationToken)
         at MongoDB.Driver.MongoCollectionImpl`1.<>c__DisplayClass52_0`1.<FindSync>b__0(IClientSessionHandle session)
         at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSession[TResult](Func`2 func, CancellationToken cancellationToken)
         at MongoDB.Driver.MongoCollectionImpl`1.FindSync[TProjection](FilterDefinition`1 filter, FindOptions`2 options, CancellationToken cancellationToken)
         at MongoDB.Driver.FindFluent`2.ToCursor(CancellationToken cancellationToken)   at MongoDB.Driver.IAsyncCursorSourceExtensions.First[TDocument](IAsyncCursorSource`1 source, CancellationToken cancellationToken)
         at MongoDB.Driver.IFindFluentExtensions.First[TDocument,TProjection](IFindFluent`2 find, CancellationToken cancellationToken)
         at Program.<Main>$(String[] args) in C:\Users\codetest\test\Program.cs:line 13 

      Or

      Unhandled exception. System.TimeoutException: A timeout occurred after 30000ms selecting a server using CompositeServerSelector{ Selectors = ReadPreferenceServerSelector{ ReadPreference = { Mode : Primary } }, LatencyLimitingServerSelector{ AllowedLatencyRange = 00:00:00.0150000 }, OperationsCountServerSelector }. Client view of cluster state is { ClusterId : "1", ConnectionMode : "ReplicaSet", Type : "ReplicaSet", State : "Disconnected", Servers : [] }. 

      The equivalent Rust code with driver version 3.1.0 doesn't have this issue:

      use std::time::Duration;
      
      use mongodb::{
          bson::{self, doc, oid::ObjectId},
          options::{ClientOptions, ServerApi, ServerApiVersion},
          Client,
      };
      use serde::{Deserialize, Serialize};
      
      #[derive(Debug, Clone, Serialize, Deserialize)]
      struct MongoDataObj {
          #[serde(rename = "_id")]
          id: ObjectId,
          pub Content: String,
      }
      
      #[tokio::main]
      async fn main() -> mongodb::error::Result<()> {
          let uri = "mongodb+srv://some connection string to an atlas cluster";
      
          for n in 0..100 {
              let mut client_options = ClientOptions::parse(uri).await?;
      
              // Create a new client and connect to the server
              let client = Client::with_options(client_options)?;
      
              println!("Search nr: {}", n );
      
              let collection = client
                  .database("database")
                  .collection::<MongoDataObj>("collection");
      
              let filter = doc! { "Content": "foobar" };
      
              let doc = collection.find_one(filter).await?;
              println!("{:?}", doc);
              println!("------------------------------------")
          }
      
          Ok(())
      }
      

      Extra info

      The only way I have been able to make sure that the C# driver connects is either by having a try-catch that retries again until it succeeds, or increase all timeouts and idle times to 60 seconds. It will then connect at around 45-50 seconds.

      The Rust code doesn't have this issue at all and is able to connect within 250-300ms.

      The C# bug exists both in sync and async code.

            Assignee:
            Unassigned Unassigned
            Reporter:
            kristiyan.lazarov.giddir@gmail.com Kristiyan Lazarov
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: