[CSHARP-1018] Driver ignores timeout option when machine is not accessible Created: 21/Jul/14  Updated: 05/Apr/19  Resolved: 04/Apr/15

Status: Closed
Project: C# Driver
Component/s: Connectivity
Affects Version/s: 1.9.1
Fix Version/s: None

Type: Task Priority: Critical - P2
Reporter: Stanislav Radkov [X] Assignee: Unassigned
Resolution: Done Votes: 1
Labels: question
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Attachments: Text File Program.cs    
Issue Links:
Related
is related to CSHARP-1231 Expose Server Selection Timeout via C... Closed

 Description   

When we set a timeout option it is ignored if the machine is turned off or not accessible. We use MongoDB for caching and have some fallback logic in case the DB is not accessible, but in this case the driver ignores the timeout value and needs at least 20 seconds to throw an exception.

Here is a sample code. We used the IP of a turned off machine for the second test, you may also try with a non-existing machine:

I've also attached the .cs file we used to demonstrate the issue.

 static void Main(string[] args)
        {
            var stopwatch = new Stopwatch();
 
            stopwatch.Start();
 
            var settings = new MongoClientSettings
            {
                Server = new MongoServerAddress("localhost", 27017),
                ConnectTimeout = TimeSpan.FromSeconds(2),
            };
 
            var client = new MongoClient(settings);
            try
            {
                client.GetServer().Connect();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
           
 
            stopwatch.Stop();
            Console.WriteLine(stopwatch.Elapsed);
 
            
            // Non-existing machine
            stopwatch.Reset();
            stopwatch.Start();
 
            settings = new MongoClientSettings
            {
                Server = new MongoServerAddress("XXX.XXX.XXX.XX", 27017),
                ConnectTimeout = TimeSpan.FromSeconds(2),
            };
 
            client = new MongoClient(settings);
            try
            {
                client.GetServer().Connect();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
 
            stopwatch.Stop();
            Console.WriteLine(stopwatch.Elapsed);
        }



 Comments   
Comment by Peter Gordon [ 17/Apr/15 ]

Robert - thanks - I like the work around in CHARP-1231 - it worked great.

Comment by Robert Stam [ 16/Apr/15 ]

See the workaround posted to CSHARP-1231 for a way that the ServerSelectionTimeout can be set in the current 2.0.0 version of the driver if you prefer that approach to using shorter timeouts on specific operations.

I would recommend the cancellation token approach in the previous comment. Using short server selection timeouts can result in spurious exceptions during replica set elections if the server selection timeout is shorter than the time it takes an election to complete.

Comment by Robert Stam [ 16/Apr/15 ]

If you are using the new 2.0 async API you can use a cancellation token to apply your own timeout to the overall operation.

You can write something like this:

var startTime = DateTime.UtcNow;
try
{
    using (var timeoutCancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMilliseconds(500)))
    {
        await collection.Find("{ _id : 1 }").ToListAsync(timeoutCancellationTokenSource.Token);
    }
}
catch (OperationCanceledException ex)
{
    var endTime = DateTime.UtcNow;
    var elapsed = endTime - startTime;
    Console.WriteLine("Operation was cancelled after {0} seconds.", elapsed.TotalSeconds);
}

In this example, even though the ServerSelectionTimeout is still the default value of 30 seconds, this particular operation will be cancelled after only 500 milliseconds (approximately, cancellation can sometimes take slightly longer).

Comment by Craig Wilson [ 16/Apr/15 ]

Hi Peter,

ConnectTimeout is how long we wait for a connection to actually connect. The 30 seconds you are seeing is how long we wait for a connected server before quitting. I know there are a lot of knobs, so I apologize for that. Unfortunately, we also haven't exposed knob to change this timeout from 30 seconds. You can track ticket CSHARP-1231 for that.

Craig

Comment by Peter Gordon [ 16/Apr/15 ]

I just tried changing the connection timeout in my sample project that uses the new version 2.0 of the driver and it still ignores the setting.

It takes about 30 seconds before the task generates an exception (and the exception message says it tried for approx 30000 ms.

var settings = new MongoClientSettings
{
   Server = new MongoServerAddress("XXX.XXX.XXX.XX", 27017),
   ConnectTimeout = TimeSpan.FromSeconds(2),
};
 
var client = new MongoClient(settings);
 
_db = client.GetDatabase("test");
_db.GetCollection<SystemLockModel>("SystemLockModel").CountAsync(new BsonDocument()).ContinueWith(t =>
                    {
                        //t.Exception is an exception that occurs after about 30 seconds sayign it could not connect
                    }).Wait();

Comment by Craig Wilson [ 04/Apr/15 ]

Connection logic has been fixed in 2.0. It currently will try for 30 seconds, but that is configurable to something smaller if you need faster connection times and you know it should take much less time.

Generated at Wed Feb 07 21:38:27 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.