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: Duplicate
    • Priority: Icon: Unknown Unknown
    • None
    • Affects Version/s: 2.21.0, 2.28.0
    • Component/s: Connectivity
    • None
    • Dotnet Drivers
    • Hide

      1. What would you like to communicate to the user about this feature?
      2. Would you like the user to see examples of the syntax and/or executable code and its output?
      3. Which versions of the driver/connector does this apply to?

      Show
      1. What would you like to communicate to the user about this feature? 2. Would you like the user to see examples of the syntax and/or executable code and its output? 3. Which versions of the driver/connector does this apply to?

      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:
            adelin.mbidaowona@mongodb.com Adelin Mbida Owona
            Reporter:
            kristiyan.lazarov.giddir@gmail.com Kristiyan Lazarov
            Votes:
            1 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved: