diff --git a/src/Ydb.Sdk/CHANGELOG.md b/src/Ydb.Sdk/CHANGELOG.md index da016a5c..5b1b41b6 100644 --- a/src/Ydb.Sdk/CHANGELOG.md +++ b/src/Ydb.Sdk/CHANGELOG.md @@ -1,3 +1,5 @@ +- Added `ConnectTimeout`: time to wait (in seconds) while trying to establish a connection. + ## v0.18.2 - Fixed YdbException: propagate inner exception. diff --git a/src/Ydb.Sdk/src/Ado/YdbConnectionStringBuilder.cs b/src/Ydb.Sdk/src/Ado/YdbConnectionStringBuilder.cs index 673aca21..f9bade30 100644 --- a/src/Ydb.Sdk/src/Ado/YdbConnectionStringBuilder.cs +++ b/src/Ydb.Sdk/src/Ado/YdbConnectionStringBuilder.cs @@ -29,6 +29,7 @@ private void InitDefaultValues() _database = "/local"; _maxSessionPool = 100; _useTls = false; + _connectTimeout = GrpcDefaultSettings.ConnectTimeoutSeconds; _keepAlivePingDelay = GrpcDefaultSettings.DefaultKeepAlivePingSeconds; _keepAlivePingTimeout = GrpcDefaultSettings.DefaultKeepAlivePingTimeoutSeconds; _enableMultipleHttp2Connections = false; @@ -145,6 +146,23 @@ public string? RootCertificate private string? _rootCertificate; + public int ConnectTimeout + { + get => _connectTimeout; + set + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), value, "Invalid connect timeout: " + value); + } + + _connectTimeout = value; + SaveValue(nameof(ConnectTimeout), value); + } + } + + private int _connectTimeout; + public int KeepAlivePingDelay { get => _keepAlivePingDelay; @@ -283,6 +301,9 @@ internal async Task BuildDriver() customServerCertificates: ServerCertificates ) { + ConnectTimeout = ConnectTimeout == 0 + ? Timeout.InfiniteTimeSpan + : TimeSpan.FromSeconds(ConnectTimeout), KeepAlivePingDelay = KeepAlivePingDelay == 0 ? Timeout.InfiniteTimeSpan : TimeSpan.FromSeconds(KeepAlivePingDelay), @@ -367,10 +388,12 @@ static YdbConnectionOption() "MaxSessionPool", "Max Session Pool", "Maximum Pool Size", "Max Pool Size", "MaximumPoolSize"); AddOption(new YdbConnectionOption(BoolExtractor, (builder, useTls) => builder.UseTls = useTls), "UseTls", "Use Tls"); - AddOption( - new YdbConnectionOption(StringExtractor, + AddOption(new YdbConnectionOption(StringExtractor, (builder, rootCertificate) => builder.RootCertificate = rootCertificate), "RootCertificate", "Root Certificate"); + AddOption(new YdbConnectionOption(IntExtractor, + (builder, connectTimeout) => builder.ConnectTimeout = connectTimeout), + "ConnectTimeout", "Connect Timeout"); AddOption(new YdbConnectionOption(IntExtractor, (builder, keepAlivePingDelay) => builder.KeepAlivePingDelay = keepAlivePingDelay), "KeepAlivePingDelay", "Keep Alive Ping Delay"); diff --git a/src/Ydb.Sdk/src/DriverConfig.cs b/src/Ydb.Sdk/src/DriverConfig.cs index b97ffbc6..8eb8772e 100644 --- a/src/Ydb.Sdk/src/DriverConfig.cs +++ b/src/Ydb.Sdk/src/DriverConfig.cs @@ -10,6 +10,9 @@ public class DriverConfig public string Database { get; } public ICredentialsProvider? Credentials { get; } + public TimeSpan ConnectTimeout { get; init; } = + TimeSpan.FromSeconds(GrpcDefaultSettings.ConnectTimeoutSeconds); + public TimeSpan KeepAlivePingDelay { get; init; } = TimeSpan.FromSeconds(GrpcDefaultSettings.DefaultKeepAlivePingSeconds); diff --git a/src/Ydb.Sdk/src/GrpcDefaultSettings.cs b/src/Ydb.Sdk/src/GrpcDefaultSettings.cs index 3e16b4b1..af0dddfb 100644 --- a/src/Ydb.Sdk/src/GrpcDefaultSettings.cs +++ b/src/Ydb.Sdk/src/GrpcDefaultSettings.cs @@ -15,4 +15,6 @@ internal static class GrpcDefaultSettings internal const int MaxSendMessageSize = 64 * 1024 * 1024; // 64 Mb internal const int MaxReceiveMessageSize = 64 * 1024 * 1024; // 64 Mb + + internal const int ConnectTimeoutSeconds = 5; } diff --git a/src/Ydb.Sdk/src/Pool/ChannelPool.cs b/src/Ydb.Sdk/src/Pool/ChannelPool.cs index 67f9c10f..84a3c50d 100644 --- a/src/Ydb.Sdk/src/Pool/ChannelPool.cs +++ b/src/Ydb.Sdk/src/Pool/ChannelPool.cs @@ -102,6 +102,7 @@ public GrpcChannel CreateChannel(string endpoint) var httpHandler = new SocketsHttpHandler { + ConnectTimeout = _config.ConnectTimeout, // https://github.com/grpc/proposal/blob/master/A8-client-side-keepalive.md KeepAlivePingDelay = _config.KeepAlivePingDelay, KeepAlivePingTimeout = _config.KeepAlivePingTimeout, diff --git a/src/Ydb.Sdk/tests/Ado/YdbConnectionStringBuilderTests.cs b/src/Ydb.Sdk/tests/Ado/YdbConnectionStringBuilderTests.cs index cd21d2f8..c1da9cfb 100644 --- a/src/Ydb.Sdk/tests/Ado/YdbConnectionStringBuilderTests.cs +++ b/src/Ydb.Sdk/tests/Ado/YdbConnectionStringBuilderTests.cs @@ -16,6 +16,7 @@ public void InitDefaultValues_WhenEmptyConstructorInvoke_ReturnDefaultConnection Assert.Equal(100, ydbConnectionStringBuilder.MaxSessionPool); Assert.Null(ydbConnectionStringBuilder.User); Assert.Null(ydbConnectionStringBuilder.Password); + Assert.Equal(5, ydbConnectionStringBuilder.ConnectTimeout); Assert.Equal(10, ydbConnectionStringBuilder.KeepAlivePingDelay); Assert.Equal(10, ydbConnectionStringBuilder.KeepAlivePingTimeout); Assert.Equal("", ydbConnectionStringBuilder.ConnectionString); @@ -40,7 +41,7 @@ public void InitConnectionStringBuilder_WhenExpectedKeys_ReturnUpdatedConnection { var connectionString = new YdbConnectionStringBuilder("Host=server;Port=2135;Database=/my/path;User=Kirill;UseTls=true;" + - "KeepAlivePingDelay=30;KeepAlivePingTimeout=60;" + + "ConnectTimeout=30;KeepAlivePingDelay=30;KeepAlivePingTimeout=60;" + "EnableMultipleHttp2Connections=true;" + "MaxSendMessageSize=1000000;MaxReceiveMessageSize=1000000;" + "DisableDiscovery=true"); @@ -50,6 +51,7 @@ public void InitConnectionStringBuilder_WhenExpectedKeys_ReturnUpdatedConnection Assert.Equal("/my/path", connectionString.Database); Assert.Equal(100, connectionString.MaxSessionPool); Assert.Equal("Kirill", connectionString.User); + Assert.Equal(30, connectionString.ConnectTimeout); Assert.Equal(30, connectionString.KeepAlivePingDelay); Assert.Equal(60, connectionString.KeepAlivePingTimeout); Assert.Null(connectionString.Password); @@ -57,7 +59,7 @@ public void InitConnectionStringBuilder_WhenExpectedKeys_ReturnUpdatedConnection Assert.Equal(1000000, connectionString.MaxSendMessageSize); Assert.Equal(1000000, connectionString.MaxReceiveMessageSize); Assert.Equal("Host=server;Port=2135;Database=/my/path;User=Kirill;UseTls=True;" + - "KeepAlivePingDelay=30;KeepAlivePingTimeout=60;" + + "ConnectTimeout=30;KeepAlivePingDelay=30;KeepAlivePingTimeout=60;" + "EnableMultipleHttp2Connections=True;" + "MaxSendMessageSize=1000000;MaxReceiveMessageSize=1000000;" + "DisableDiscovery=True", connectionString.ConnectionString);