diff --git a/src/Ydb.Sdk/CHANGELOG.md b/src/Ydb.Sdk/CHANGELOG.md index 1223dfd2..2db80e6a 100644 --- a/src/Ydb.Sdk/CHANGELOG.md +++ b/src/Ydb.Sdk/CHANGELOG.md @@ -1,3 +1,5 @@ +- Disable Discovery mode: skip discovery step and client balancing and use connection to start endpoint ([#420](https://github.com/ydb-platform/ydb-dotnet-sdk/issues/420)). + ## v0.17.0 - Shutdown channels which are removed from the EndpointPool after discovery calls. diff --git a/src/Ydb.Sdk/src/Ado/YdbConnectionStringBuilder.cs b/src/Ydb.Sdk/src/Ado/YdbConnectionStringBuilder.cs index 133b9d5c..673aca21 100644 --- a/src/Ydb.Sdk/src/Ado/YdbConnectionStringBuilder.cs +++ b/src/Ydb.Sdk/src/Ado/YdbConnectionStringBuilder.cs @@ -2,7 +2,9 @@ using System.Diagnostics.CodeAnalysis; using System.Security.Cryptography.X509Certificates; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Ydb.Sdk.Auth; +using Ydb.Sdk.Transport; namespace Ydb.Sdk.Ado; @@ -32,6 +34,7 @@ private void InitDefaultValues() _enableMultipleHttp2Connections = false; _maxSendMessageSize = GrpcDefaultSettings.MaxSendMessageSize; _maxReceiveMessageSize = GrpcDefaultSettings.MaxReceiveMessageSize; + _disableDiscovery = false; } public string Host @@ -213,6 +216,18 @@ public int MaxReceiveMessageSize private int _maxReceiveMessageSize; + public bool DisableDiscovery + { + get => _disableDiscovery; + set + { + _disableDiscovery = value; + SaveValue(nameof(DisableDiscovery), value); + } + } + + private bool _disableDiscovery; + public ILoggerFactory? LoggerFactory { get; init; } public ICredentialsProvider? CredentialsProvider { get; init; } @@ -257,33 +272,34 @@ public override object this[string keyword] private string Endpoint => $"{(UseTls ? "grpcs" : "grpc")}://{Host}:{Port}"; - internal Task BuildDriver() + internal async Task BuildDriver() { var cert = RootCertificate != null ? X509Certificate.CreateFromCertFile(RootCertificate) : null; + var driverConfig = new DriverConfig( + endpoint: Endpoint, + database: Database, + credentials: CredentialsProvider, + customServerCertificate: cert, + customServerCertificates: ServerCertificates + ) + { + KeepAlivePingDelay = KeepAlivePingDelay == 0 + ? Timeout.InfiniteTimeSpan + : TimeSpan.FromSeconds(KeepAlivePingDelay), + KeepAlivePingTimeout = KeepAlivePingTimeout == 0 + ? Timeout.InfiniteTimeSpan + : TimeSpan.FromSeconds(KeepAlivePingTimeout), + User = User, + Password = Password, + EnableMultipleHttp2Connections = EnableMultipleHttp2Connections, + MaxSendMessageSize = MaxSendMessageSize, + MaxReceiveMessageSize = MaxReceiveMessageSize + }; + var loggerFactory = LoggerFactory ?? NullLoggerFactory.Instance; - return Driver.CreateInitialized( - new DriverConfig( - endpoint: Endpoint, - database: Database, - credentials: CredentialsProvider, - customServerCertificate: cert, - customServerCertificates: ServerCertificates - ) - { - KeepAlivePingDelay = KeepAlivePingDelay == 0 - ? Timeout.InfiniteTimeSpan - : TimeSpan.FromSeconds(KeepAlivePingDelay), - KeepAlivePingTimeout = KeepAlivePingTimeout == 0 - ? Timeout.InfiniteTimeSpan - : TimeSpan.FromSeconds(KeepAlivePingTimeout), - User = User, - Password = Password, - EnableMultipleHttp2Connections = EnableMultipleHttp2Connections, - MaxSendMessageSize = MaxSendMessageSize, - MaxReceiveMessageSize = MaxReceiveMessageSize - }, - LoggerFactory - ); + return DisableDiscovery + ? new DirectGrpcChannelDriver(driverConfig, loggerFactory) + : await Driver.CreateInitialized(driverConfig, loggerFactory); } public override void Clear() @@ -369,6 +385,8 @@ static YdbConnectionOption() AddOption(new YdbConnectionOption(IntExtractor, (builder, maxReceiveMessageSize) => builder.MaxReceiveMessageSize = maxReceiveMessageSize), "MaxReceiveMessageSize", "Max Receive Message Size"); + AddOption(new YdbConnectionOption(BoolExtractor, (builder, disableDiscovery) => + builder.DisableDiscovery = disableDiscovery), "DisableDiscovery", "Disable Discovery"); } private static void AddOption(YdbConnectionOption option, params string[] keys) diff --git a/src/Ydb.Sdk/src/Driver.cs b/src/Ydb.Sdk/src/Driver.cs index bfe2b067..dc8789e5 100644 --- a/src/Ydb.Sdk/src/Driver.cs +++ b/src/Ydb.Sdk/src/Driver.cs @@ -1,13 +1,10 @@ using System.Collections.Immutable; using Grpc.Core; -using Grpc.Net.Client; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Ydb.Discovery; using Ydb.Discovery.V1; -using Ydb.Sdk.Auth; using Ydb.Sdk.Pool; -using Ydb.Sdk.Services.Auth; namespace Ydb.Sdk; @@ -15,9 +12,7 @@ public sealed class Driver : BaseDriver { private const int AttemptDiscovery = 10; - private readonly GrpcChannelFactory _grpcChannelFactory; private readonly EndpointPool _endpointPool; - private readonly ChannelPool _channelPool; internal string Database => Config.Database; @@ -26,19 +21,7 @@ public Driver(DriverConfig config, ILoggerFactory? loggerFactory = null) (loggerFactory ?? NullLoggerFactory.Instance).CreateLogger() ) { - _grpcChannelFactory = new GrpcChannelFactory(LoggerFactory, config); - _endpointPool = new EndpointPool(LoggerFactory.CreateLogger()); - _channelPool = new ChannelPool( - LoggerFactory.CreateLogger>(), - _grpcChannelFactory - ); - - CredentialsProvider = Config.User != null - ? new CachedCredentialsProvider( - new StaticCredentialsAuthClient(config, _grpcChannelFactory, LoggerFactory), - LoggerFactory - ) - : Config.Credentials; + _endpointPool = new EndpointPool(LoggerFactory); } public static async Task CreateInitialized(DriverConfig config, ILoggerFactory? loggerFactory = null) @@ -48,8 +31,6 @@ public static async Task CreateInitialized(DriverConfig config, ILoggerF return driver; } - protected override ValueTask InternalDispose() => _channelPool.DisposeAsync(); - public async Task Initialize() { Logger.LogInformation("Started initial endpoint discovery"); @@ -78,18 +59,13 @@ public async Task Initialize() } } - await Task.Delay(TimeSpan.FromMilliseconds(i * 200)); // await 0 ms, 200 ms, 400ms, .. 1.8 sec + await Task.Delay(TimeSpan.FromMilliseconds(i * 200)); // await 0 ms, 200 ms, 400ms, ... 1.8 sec } throw new InitializationFailureException("Error during initial endpoint discovery"); } - protected override (string, GrpcChannel) GetChannel(long nodeId) - { - var endpoint = _endpointPool.GetEndpoint(nodeId); - - return (endpoint, _channelPool.GetChannel(endpoint)); - } + protected override string GetEndpoint(long nodeId) => _endpointPool.GetEndpoint(nodeId); protected override void OnRpcError(string endpoint, RpcException e) { @@ -114,11 +90,9 @@ Grpc.Core.StatusCode.DeadlineExceeded or _ = Task.Run(DiscoverEndpoints); } - protected override ICredentialsProvider? CredentialsProvider { get; } - private async Task DiscoverEndpoints() { - using var channel = _grpcChannelFactory.CreateChannel(Config.Endpoint); + using var channel = GrpcChannelFactory.CreateChannel(Config.Endpoint); var client = new DiscoveryService.DiscoveryServiceClient(channel); @@ -167,7 +141,7 @@ private async Task DiscoverEndpoints() resultProto.Endpoints.Count, resultProto.SelfLocation, Config.SdkVersion ); - await _channelPool.RemoveChannels( + await ChannelPool.RemoveChannels( _endpointPool.Reset(resultProto.Endpoints .Select(endpointSettings => new EndpointSettings( (int)endpointSettings.NodeId, diff --git a/src/Ydb.Sdk/src/DriverConfig.cs b/src/Ydb.Sdk/src/DriverConfig.cs index b8d32619..b97ffbc6 100644 --- a/src/Ydb.Sdk/src/DriverConfig.cs +++ b/src/Ydb.Sdk/src/DriverConfig.cs @@ -55,6 +55,12 @@ public DriverConfig( SdkVersion = $"ydb-dotnet-sdk/{versionStr}"; } + internal Grpc.Core.Metadata GetCallMetadata => new() + { + { Metadata.RpcDatabaseHeader, Database }, + { Metadata.RpcSdkInfoHeader, SdkVersion } + }; + private static string FormatEndpoint(string endpoint) { endpoint = endpoint.ToLower().Trim(); diff --git a/src/Ydb.Sdk/src/IDriver.cs b/src/Ydb.Sdk/src/IDriver.cs index 55e9abec..7ee53eaf 100644 --- a/src/Ydb.Sdk/src/IDriver.cs +++ b/src/Ydb.Sdk/src/IDriver.cs @@ -2,6 +2,8 @@ using Grpc.Net.Client; using Microsoft.Extensions.Logging; using Ydb.Sdk.Auth; +using Ydb.Sdk.Pool; +using Ydb.Sdk.Services.Auth; namespace Ydb.Sdk; @@ -45,16 +47,35 @@ public interface IBidirectionalStream : IDisposable public abstract class BaseDriver : IDriver { + private readonly ICredentialsProvider? _credentialsProvider; + protected readonly DriverConfig Config; protected readonly ILogger Logger; + internal readonly GrpcChannelFactory GrpcChannelFactory; + internal readonly ChannelPool ChannelPool; + protected int Disposed; - protected BaseDriver(DriverConfig config, ILoggerFactory loggerFactory, ILogger logger) + internal BaseDriver( + DriverConfig config, + ILoggerFactory loggerFactory, + ILogger logger + ) { Config = config; Logger = logger; LoggerFactory = loggerFactory; + + GrpcChannelFactory = new GrpcChannelFactory(LoggerFactory, Config); + ChannelPool = new ChannelPool(LoggerFactory, GrpcChannelFactory); + + _credentialsProvider = Config.User != null + ? new CachedCredentialsProvider( + new StaticCredentialsAuthClient(Config, GrpcChannelFactory, LoggerFactory), + LoggerFactory + ) + : Config.Credentials; } public async Task UnaryCall( @@ -64,7 +85,9 @@ public async Task UnaryCall( where TRequest : class where TResponse : class { - var (endpoint, channel) = GetChannel(settings.NodeId); + var endpoint = GetEndpoint(settings.NodeId); + var channel = ChannelPool.GetChannel(endpoint); + var callInvoker = channel.CreateCallInvoker(); Logger.LogTrace("Unary call, method: {MethodName}, endpoint: {Endpoint}", method.Name, endpoint); @@ -97,7 +120,9 @@ public async ValueTask> ServerStreamCall> BidirectionalS where TRequest : class where TResponse : class { - var (endpoint, channel) = GetChannel(settings.NodeId); + var endpoint = GetEndpoint(settings.NodeId); + var channel = ChannelPool.GetChannel(endpoint); + var callInvoker = channel.CreateCallInvoker(); var call = callInvoker.AsyncDuplexStreamingCall( @@ -126,25 +153,21 @@ public async ValueTask> BidirectionalS return new BidirectionalStream( call, e => { OnRpcError(endpoint, e); }, - CredentialsProvider + _credentialsProvider ); } - protected abstract (string, GrpcChannel) GetChannel(long nodeId); + protected abstract string GetEndpoint(long nodeId); protected abstract void OnRpcError(string endpoint, RpcException e); protected async ValueTask GetCallOptions(GrpcRequestSettings settings) { - var meta = new Grpc.Core.Metadata - { - { Metadata.RpcDatabaseHeader, Config.Database }, - { Metadata.RpcSdkInfoHeader, Config.SdkVersion } - }; + var meta = Config.GetCallMetadata; - if (CredentialsProvider != null) + if (_credentialsProvider != null) { - meta.Add(Metadata.RpcAuthHeader, await CredentialsProvider.GetAuthInfoAsync()); + meta.Add(Metadata.RpcAuthHeader, await _credentialsProvider.GetAuthInfoAsync()); } if (settings.TraceId.Length > 0) @@ -152,10 +175,7 @@ protected async ValueTask GetCallOptions(GrpcRequestSettings settin meta.Add(Metadata.RpcTraceIdHeader, settings.TraceId); } - var options = new CallOptions( - headers: meta, - cancellationToken: settings.CancellationToken - ); + var options = new CallOptions(headers: meta, cancellationToken: settings.CancellationToken); if (settings.TransportTimeout != TimeSpan.Zero) { @@ -165,8 +185,6 @@ protected async ValueTask GetCallOptions(GrpcRequestSettings settin return options; } - protected abstract ICredentialsProvider? CredentialsProvider { get; } - public ILoggerFactory LoggerFactory { get; } public void Dispose() => DisposeAsync().AsTask().GetAwaiter().GetResult(); @@ -175,11 +193,11 @@ public async ValueTask DisposeAsync() { if (Interlocked.CompareExchange(ref Disposed, 1, 0) == 0) { - await InternalDispose(); + await ChannelPool.DisposeAsync(); + + GC.SuppressFinalize(this); } } - - protected abstract ValueTask InternalDispose(); } public sealed class ServerStream : IAsyncEnumerator, IAsyncEnumerable diff --git a/src/Ydb.Sdk/src/Pool/ChannelPool.cs b/src/Ydb.Sdk/src/Pool/ChannelPool.cs index e9e77914..67f9c10f 100644 --- a/src/Ydb.Sdk/src/Pool/ChannelPool.cs +++ b/src/Ydb.Sdk/src/Pool/ChannelPool.cs @@ -15,9 +15,9 @@ internal class ChannelPool : IAsyncDisposable where T : ChannelBase, IDisposa private readonly ILogger> _logger; private readonly IChannelFactory _channelFactory; - public ChannelPool(ILogger> logger, IChannelFactory channelFactory) + public ChannelPool(ILoggerFactory loggerFactory, IChannelFactory channelFactory) { - _logger = logger; + _logger = loggerFactory.CreateLogger>(); _channelFactory = channelFactory; } diff --git a/src/Ydb.Sdk/src/Pool/EndpointPool.cs b/src/Ydb.Sdk/src/Pool/EndpointPool.cs index 070cc1f2..feff114e 100644 --- a/src/Ydb.Sdk/src/Pool/EndpointPool.cs +++ b/src/Ydb.Sdk/src/Pool/EndpointPool.cs @@ -16,9 +16,9 @@ internal class EndpointPool private Dictionary _nodeIdToEndpoint = new(); private int _preferredEndpointCount; - internal EndpointPool(ILogger logger, IRandom? random = null) + internal EndpointPool(ILoggerFactory loggerFactory, IRandom? random = null) { - _logger = logger; + _logger = loggerFactory.CreateLogger(); _random = random ?? ThreadLocalRandom.Instance; } diff --git a/src/Ydb.Sdk/src/Services/Auth/StaticCredentialsAuthClient.cs b/src/Ydb.Sdk/src/Services/Auth/StaticCredentialsAuthClient.cs index 74800161..afc5e632 100644 --- a/src/Ydb.Sdk/src/Services/Auth/StaticCredentialsAuthClient.cs +++ b/src/Ydb.Sdk/src/Services/Auth/StaticCredentialsAuthClient.cs @@ -1,4 +1,5 @@ using System.IdentityModel.Tokens.Jwt; +using Grpc.Core; using Microsoft.Extensions.Logging; using Ydb.Auth; using Ydb.Auth.V1; @@ -6,7 +7,6 @@ using Ydb.Sdk.Client; using Ydb.Sdk.Pool; using Ydb.Sdk.Services.Operations; -using Ydb.Sdk.Transport; namespace Ydb.Sdk.Services.Auth; @@ -14,7 +14,6 @@ internal class StaticCredentialsAuthClient : IAuthClient { private readonly DriverConfig _config; private readonly GrpcChannelFactory _grpcChannelFactory; - private readonly ILoggerFactory _loggerFactory; private readonly ILogger _logger; private readonly RetrySettings _retrySettings = new(5); @@ -27,7 +26,6 @@ ILoggerFactory loggerFactory { _config = config; _grpcChannelFactory = grpcChannelFactory; - _loggerFactory = loggerFactory; _logger = loggerFactory.CreateLogger(); } @@ -76,13 +74,10 @@ private async Task Login() try { - await using var transport = new AuthGrpcChannelDriver(_config, _grpcChannelFactory, _loggerFactory); + using var channel = _grpcChannelFactory.CreateChannel(_config.Endpoint); - var response = await transport.UnaryCall( - method: AuthService.LoginMethod, - request: request, - settings: new GrpcRequestSettings() - ); + var response = await new AuthService.AuthServiceClient(channel) + .LoginAsync(request, new CallOptions(_config.GetCallMetadata)); var status = response.Operation.TryUnpack(out LoginResult? resultProto); diff --git a/src/Ydb.Sdk/src/Services/Query/SessionPool.cs b/src/Ydb.Sdk/src/Services/Query/SessionPool.cs index a2157885..d64551f3 100644 --- a/src/Ydb.Sdk/src/Services/Query/SessionPool.cs +++ b/src/Ydb.Sdk/src/Services/Query/SessionPool.cs @@ -24,11 +24,11 @@ internal sealed class SessionPool : SessionPool, IAsyncDisposable TransportTimeout = TimeSpan.FromMinutes(2) }; - private readonly Driver _driver; + private readonly IDriver _driver; private readonly bool _disposingDriver; private readonly ILogger _loggerSession; - internal SessionPool(Driver driver, int? maxSessionPool = null, bool disposingDriver = false) + internal SessionPool(IDriver driver, int? maxSessionPool = null, bool disposingDriver = false) : base(driver.LoggerFactory.CreateLogger(), maxSessionPool) { _driver = driver; @@ -120,10 +120,10 @@ protected override async Task CreateSession() internal class Session : SessionBase { - internal Driver Driver { get; } + internal IDriver Driver { get; } internal Session( - Driver driver, + IDriver driver, SessionPool sessionPool, string sessionId, long nodeId, diff --git a/src/Ydb.Sdk/src/Transport/AuthGrpcChannelDriver.cs b/src/Ydb.Sdk/src/Transport/AuthGrpcChannelDriver.cs deleted file mode 100644 index 99486cef..00000000 --- a/src/Ydb.Sdk/src/Transport/AuthGrpcChannelDriver.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Grpc.Core; -using Grpc.Net.Client; -using Microsoft.Extensions.Logging; -using Ydb.Sdk.Auth; -using Ydb.Sdk.Pool; - -namespace Ydb.Sdk.Transport; - -internal class AuthGrpcChannelDriver : BaseDriver -{ - private readonly GrpcChannel _channel; - - public AuthGrpcChannelDriver( - DriverConfig driverConfig, - GrpcChannelFactory grpcChannelFactory, - ILoggerFactory loggerFactory - ) : base( - new DriverConfig( - endpoint: driverConfig.Endpoint, - database: driverConfig.Database, - customServerCertificates: driverConfig.CustomServerCertificates - ), loggerFactory, loggerFactory.CreateLogger()) - { - _channel = grpcChannelFactory.CreateChannel(Config.Endpoint); - } - - protected override (string, GrpcChannel) GetChannel(long nodeId) => (Config.Endpoint, _channel); - - protected override void OnRpcError(string endpoint, RpcException e) - { - var status = e.Status; - if (e.Status.StatusCode != Grpc.Core.StatusCode.OK) - { - Logger.LogWarning("gRPC error {StatusCode}[{Detail}] on fixed channel {Endpoint}", - status.StatusCode, status.Detail, endpoint); - } - } - - protected override ICredentialsProvider? CredentialsProvider => null; - - protected override async ValueTask InternalDispose() - { - await _channel.ShutdownAsync(); - - _channel.Dispose(); - } -} diff --git a/src/Ydb.Sdk/src/Transport/DirectGrpcChannelDriver.cs b/src/Ydb.Sdk/src/Transport/DirectGrpcChannelDriver.cs new file mode 100644 index 00000000..d7a1abc3 --- /dev/null +++ b/src/Ydb.Sdk/src/Transport/DirectGrpcChannelDriver.cs @@ -0,0 +1,22 @@ +using Grpc.Core; +using Microsoft.Extensions.Logging; + +namespace Ydb.Sdk.Transport; + +public class DirectGrpcChannelDriver : BaseDriver +{ + public DirectGrpcChannelDriver(DriverConfig driverConfig, ILoggerFactory loggerFactory) : + base(driverConfig, loggerFactory, loggerFactory.CreateLogger()) + { + } + + protected override string GetEndpoint(long nodeId) => Config.Endpoint; + + protected override void OnRpcError(string endpoint, RpcException e) + { + var status = e.Status; + + Logger.LogWarning("gRPC error {StatusCode}[{Detail}] on fixed channel {Endpoint}", + status.StatusCode, status.Detail, endpoint); + } +} diff --git a/src/Ydb.Sdk/tests/Ado/YdbAdoUserPasswordTests.cs b/src/Ydb.Sdk/tests/Ado/YdbAdoUserPasswordTests.cs index 51855563..b248db87 100644 --- a/src/Ydb.Sdk/tests/Ado/YdbAdoUserPasswordTests.cs +++ b/src/Ydb.Sdk/tests/Ado/YdbAdoUserPasswordTests.cs @@ -7,6 +7,8 @@ namespace Ydb.Sdk.Tests.Ado; public class YdbAdoUserPasswordTests : YdbAdoNetFixture { + private readonly string _user = "kurdyukovkirya" + Random.Shared.Next(); + public YdbAdoUserPasswordTests(YdbFactoryFixture fixture) : base(fixture) { } @@ -14,24 +16,11 @@ public YdbAdoUserPasswordTests(YdbFactoryFixture fixture) : base(fixture) [Fact] public async Task Authentication_WhenUserAndPassword_ReturnValidConnection() { - await using var connection = await CreateOpenConnectionAsync(); - var ydbCommand = connection.CreateCommand(); - var kurdyukovkirya = "kurdyukovkirya" + Random.Shared.Next(); - ydbCommand.CommandText = $"CREATE USER {kurdyukovkirya} PASSWORD 'password'"; - await ydbCommand.ExecuteNonQueryAsync(); - await connection.CloseAsync(); - - await using var userPasswordConnection = - new YdbConnection($"{ConnectionString};User={kurdyukovkirya};Password=password;"); + await using var userPasswordConnection = new YdbConnection( + $"{ConnectionString};User={_user};Password=password;"); await userPasswordConnection.OpenAsync(); - ydbCommand = userPasswordConnection.CreateCommand(); - ydbCommand.CommandText = "SELECT 1 + 2"; - Assert.Equal(3, await ydbCommand.ExecuteScalarAsync()); - - await using var newConnection = await CreateOpenConnectionAsync(); - ydbCommand = newConnection.CreateCommand(); - ydbCommand.CommandText = $"DROP USER {kurdyukovkirya};"; - await ydbCommand.ExecuteNonQueryAsync(); + Assert.Equal(3, await new YdbCommand(userPasswordConnection) + { CommandText = "SELECT 1 + 2" }.ExecuteScalarAsync()); } [Fact] @@ -45,4 +34,31 @@ public async Task ExecuteNonQueryAsync_WhenCreateUser_ReturnEmptyResultSet() dbCommand.CommandText = $"DROP USER {user};"; await dbCommand.ExecuteNonQueryAsync(); } + + [Fact] + public async Task DisableDiscovery_WhenUserIsCreatedAndPropertyIsTrue_SimpleWorking() + { + await using var userPasswordConnection = new YdbConnection( + $"{ConnectionString};User={_user};Password=password;DisableDiscovery=true"); + await userPasswordConnection.OpenAsync(); + var ydbCommand = userPasswordConnection.CreateCommand(); + ydbCommand.CommandText = "SELECT 1 + 2"; + Assert.Equal(3, await ydbCommand.ExecuteScalarAsync()); + } + + protected override async Task OnInitializeAsync() + { + await using var connection = await CreateOpenConnectionAsync(); + var ydbCommand = connection.CreateCommand(); + ydbCommand.CommandText = $"CREATE USER {_user} PASSWORD 'password'"; + await ydbCommand.ExecuteNonQueryAsync(); + } + + protected override async Task OnDisposeAsync() + { + await using var ydbConnection = await CreateOpenConnectionAsync(); + var ydbCommand = ydbConnection.CreateCommand(); + ydbCommand.CommandText = $"DROP USER {_user};"; + await ydbCommand.ExecuteNonQueryAsync(); + } } diff --git a/src/Ydb.Sdk/tests/Ado/YdbConnectionStringBuilderTests.cs b/src/Ydb.Sdk/tests/Ado/YdbConnectionStringBuilderTests.cs index c72b9c8b..cd21d2f8 100644 --- a/src/Ydb.Sdk/tests/Ado/YdbConnectionStringBuilderTests.cs +++ b/src/Ydb.Sdk/tests/Ado/YdbConnectionStringBuilderTests.cs @@ -22,6 +22,7 @@ public void InitDefaultValues_WhenEmptyConstructorInvoke_ReturnDefaultConnection Assert.False(ydbConnectionStringBuilder.EnableMultipleHttp2Connections); Assert.Equal(64 * 1024 * 1024, ydbConnectionStringBuilder.MaxSendMessageSize); Assert.Equal(64 * 1024 * 1024, ydbConnectionStringBuilder.MaxReceiveMessageSize); + Assert.False(ydbConnectionStringBuilder.DisableDiscovery); } [Fact] @@ -41,7 +42,8 @@ public void InitConnectionStringBuilder_WhenExpectedKeys_ReturnUpdatedConnection new YdbConnectionStringBuilder("Host=server;Port=2135;Database=/my/path;User=Kirill;UseTls=true;" + "KeepAlivePingDelay=30;KeepAlivePingTimeout=60;" + "EnableMultipleHttp2Connections=true;" + - "MaxSendMessageSize=1000000;MaxReceiveMessageSize=1000000"); + "MaxSendMessageSize=1000000;MaxReceiveMessageSize=1000000;" + + "DisableDiscovery=true"); Assert.Equal(2135, connectionString.Port); Assert.Equal("server", connectionString.Host); @@ -57,7 +59,9 @@ public void InitConnectionStringBuilder_WhenExpectedKeys_ReturnUpdatedConnection Assert.Equal("Host=server;Port=2135;Database=/my/path;User=Kirill;UseTls=True;" + "KeepAlivePingDelay=30;KeepAlivePingTimeout=60;" + "EnableMultipleHttp2Connections=True;" + - "MaxSendMessageSize=1000000;MaxReceiveMessageSize=1000000", connectionString.ConnectionString); + "MaxSendMessageSize=1000000;MaxReceiveMessageSize=1000000;" + + "DisableDiscovery=True", connectionString.ConnectionString); + Assert.True(connectionString.DisableDiscovery); } [Fact] diff --git a/src/Ydb.Sdk/tests/Ado/YdbConnectionTests.cs b/src/Ydb.Sdk/tests/Ado/YdbConnectionTests.cs index 74408265..0244bb4e 100644 --- a/src/Ydb.Sdk/tests/Ado/YdbConnectionTests.cs +++ b/src/Ydb.Sdk/tests/Ado/YdbConnectionTests.cs @@ -202,6 +202,16 @@ INSERT INTO {tableName} await ydbCommand.ExecuteNonQueryAsync(); } + [Fact] + public async Task DisableDiscovery_WhenPropertyIsTrue_SimpleWorking() + { + await using var connection = CreateConnection(); + connection.ConnectionString += ";DisableDiscovery=true"; + await connection.OpenAsync(); + Assert.True((bool)(await new YdbCommand(connection) { CommandText = "SELECT TRUE;" }.ExecuteScalarAsync())!); + await YdbConnection.ClearPool(connection); + } + private List GenerateTasks() => Enumerable.Range(0, 100).Select(async i => { await using var connection = await CreateOpenConnectionAsync(); diff --git a/src/Ydb.Sdk/tests/Pool/ChannelPoolTests.cs b/src/Ydb.Sdk/tests/Pool/ChannelPoolTests.cs index a51cdf61..ec5ce24a 100644 --- a/src/Ydb.Sdk/tests/Pool/ChannelPoolTests.cs +++ b/src/Ydb.Sdk/tests/Pool/ChannelPoolTests.cs @@ -1,7 +1,6 @@ using System.Collections.Concurrent; using System.Collections.Immutable; using Grpc.Core; -using Microsoft.Extensions.Logging; using Moq; using Xunit; using Ydb.Sdk.Pool; @@ -17,8 +16,7 @@ public class ChannelPoolTests public ChannelPoolTests() { - _channelPool = new ChannelPool(Utils.GetLoggerFactory().CreateLogger>(), - _mockChannelFactory.Object); + _channelPool = new ChannelPool(Utils.GetLoggerFactory(), _mockChannelFactory.Object); _mockChannelFactory .Setup(channelFactory => channelFactory.CreateChannel(It.IsAny())) .Returns(endpoint => diff --git a/src/Ydb.Sdk/tests/Pool/EndpointPoolTests.cs b/src/Ydb.Sdk/tests/Pool/EndpointPoolTests.cs index cad6ff08..fd594e94 100644 --- a/src/Ydb.Sdk/tests/Pool/EndpointPoolTests.cs +++ b/src/Ydb.Sdk/tests/Pool/EndpointPoolTests.cs @@ -1,5 +1,4 @@ using System.Collections.Immutable; -using Microsoft.Extensions.Logging; using Moq; using Xunit; using Ydb.Sdk.Pool; @@ -24,7 +23,7 @@ public class MockRandomUnitTests public MockRandomUnitTests() { - _endpointPool = new EndpointPool(Utils.GetLoggerFactory().CreateLogger(), _mockRandom.Object); + _endpointPool = new EndpointPool(Utils.GetLoggerFactory(), _mockRandom.Object); _endpointPool.Reset(EndpointSettingsList); } @@ -172,7 +171,7 @@ public void PessimizeEndpoint_WhenPessimizedAllNodes_ReturnRandomEndpoint() public class ThreadLocalRandomTests { - private readonly EndpointPool _endpointPool = new(Utils.GetLoggerFactory().CreateLogger()); + private readonly EndpointPool _endpointPool = new(Utils.GetLoggerFactory()); public ThreadLocalRandomTests() {