diff --git a/slo/src/TableService/SloTableContext.cs b/slo/src/TableService/SloTableContext.cs index 105d462a..947362a8 100644 --- a/slo/src/TableService/SloTableContext.cs +++ b/slo/src/TableService/SloTableContext.cs @@ -14,9 +14,8 @@ public class SloTableContext : SloTableContext protected override async Task Create(TableClient client, string createTableSql, int operationTimeout) { - var response = await client.SessionExec( - async session => await session.ExecuteSchemeQuery(createTableSql, - new ExecuteSchemeQuerySettings { OperationTimeout = TimeSpan.FromSeconds(operationTimeout) })); + var response = await client.SessionExec(async session => await session.ExecuteSchemeQuery(createTableSql, + new ExecuteSchemeQuerySettings { OperationTimeout = TimeSpan.FromSeconds(operationTimeout) })); response.Status.EnsureSuccess(); } @@ -29,21 +28,20 @@ protected override async Task Create(TableClient client, string createTableSql, var attempts = 0; - var response = await tableClient.SessionExec( - async session => + var response = await tableClient.SessionExec(async session => + { + attempts++; + var response = await session.ExecuteDataQuery(upsertSql, _txControl, parameters, querySettings); + if (response.Status.IsSuccess) { - attempts++; - var response = await session.ExecuteDataQuery(upsertSql, _txControl, parameters, querySettings); - if (response.Status.IsSuccess) - { - return response; - } + return response; + } - errorsGauge?.WithLabels(response.Status.StatusCode.ToString(), "retried").Inc(); + errorsGauge?.WithLabels(response.Status.StatusCode.ToString(), "retried").Inc(); - return response; - }); + return response; + }); return (attempts, response.Status.StatusCode); } @@ -56,22 +54,21 @@ protected override async Task Create(TableClient client, string createTableSql, var attempts = 0; - var response = (ExecuteDataQueryResponse)await tableClient.SessionExec( - async session => + var response = (ExecuteDataQueryResponse)await tableClient.SessionExec(async session => + { + attempts++; + var response = await session.ExecuteDataQuery(selectSql, _txControl, parameters, querySettings); + if (response.Status.IsSuccess) { - attempts++; - var response = await session.ExecuteDataQuery(selectSql, _txControl, parameters, querySettings); - if (response.Status.IsSuccess) - { - return response; - } + return response; + } - Logger.LogWarning("{}", response.Status.ToString()); + Logger.LogWarning("{}", response.Status.ToString()); - errorsGauge?.WithLabels(response.Status.StatusCode.StatusName(), "retried").Inc(); + errorsGauge?.WithLabels(response.Status.StatusCode.StatusName(), "retried").Inc(); - return response; - }); + return response; + }); return (attempts, response.Status.StatusCode, response.Status.IsSuccess ? response.Result.ResultSets[0].Rows[0][0].GetOptionalInt32() : null); diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Migrations/YdbMigrationsSqlGeneratorTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Migrations/YdbMigrationsSqlGeneratorTest.cs index d13b2777..5a236821 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Migrations/YdbMigrationsSqlGeneratorTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Migrations/YdbMigrationsSqlGeneratorTest.cs @@ -150,17 +150,16 @@ public override void InsertDataOperation_required_args_multiple_rows() public override void InsertDataOperation_throws_for_unsupported_column_types() => Assert.Equal( RelationalStrings.UnsupportedDataOperationStoreType("foo", "dbo.People.First Name"), - Assert.Throws( - () => - Generate( - new InsertDataOperation - { - Table = "People", - Schema = "dbo", - Columns = ["First Name"], - ColumnTypes = ["foo"], - Values = new object?[,] { { null } } - })).Message); + Assert.Throws(() => + Generate( + new InsertDataOperation + { + Table = "People", + Schema = "dbo", + Columns = ["First Name"], + ColumnTypes = ["foo"], + Values = new object?[,] { { null } } + })).Message); public override void DeleteDataOperation_all_args() { diff --git a/src/Ydb.Sdk/CHANGELOG.md b/src/Ydb.Sdk/CHANGELOG.md index 4d577783..9f1b230e 100644 --- a/src/Ydb.Sdk/CHANGELOG.md +++ b/src/Ydb.Sdk/CHANGELOG.md @@ -1,3 +1,5 @@ +- Added `x-ydb-sdk-build-info` header to any RPC call. + ## v0.16.0 - **Breaking Change**: `Ydb.Sdk.Yc.Auth` version <= 0.1.0 is not compatible with newer versions. diff --git a/src/Ydb.Sdk/src/Driver.cs b/src/Ydb.Sdk/src/Driver.cs index d872f9e9..f46bf686 100644 --- a/src/Ydb.Sdk/src/Driver.cs +++ b/src/Ydb.Sdk/src/Driver.cs @@ -1,5 +1,4 @@ using System.Collections.Immutable; -using System.Reflection; using Grpc.Core; using Grpc.Net.Client; using Microsoft.Extensions.Logging; @@ -16,7 +15,6 @@ public sealed class Driver : BaseDriver { private const int AttemptDiscovery = 10; - private readonly string _sdkInfo; private readonly GrpcChannelFactory _grpcChannelFactory; private readonly EndpointPool _endpointPool; private readonly ChannelPool _channelPool; @@ -35,10 +33,6 @@ public Driver(DriverConfig config, ILoggerFactory? loggerFactory = null) _grpcChannelFactory ); - var version = Assembly.GetExecutingAssembly().GetName().Version; - var versionStr = version is null ? "unknown" : version.ToString(3); - _sdkInfo = $"ydb-dotnet-sdk/{versionStr}"; - CredentialsProvider = Config.User != null ? new CachedCredentialsProvider( new StaticCredentialsAuthClient(config, _grpcChannelFactory, LoggerFactory), @@ -134,12 +128,10 @@ private async Task DiscoverEndpoints() TransportTimeout = Config.EndpointDiscoveryTimeout }; - var options = await GetCallOptions(requestSettings); - options.Headers?.Add(Metadata.RpcSdkInfoHeader, _sdkInfo); - var response = await client.ListEndpointsAsync( request: request, - options: options); + options: await GetCallOptions(requestSettings) + ); if (!response.Operation.Ready) { @@ -168,7 +160,8 @@ private async Task DiscoverEndpoints() Logger.LogDebug( "Successfully discovered endpoints: {EndpointsCount}, self location: {SelfLocation}, sdk info: {SdkInfo}", - resultProto.Endpoints.Count, resultProto.SelfLocation, _sdkInfo); + resultProto.Endpoints.Count, resultProto.SelfLocation, Config.SdkVersion + ); _endpointPool.Reset(resultProto.Endpoints .Select(endpointSettings => new EndpointSettings( @@ -189,15 +182,16 @@ private async Task PeriodicDiscovery() try { await Task.Delay(Config.EndpointDiscoveryInterval); + _ = await DiscoverEndpoints(); } catch (RpcException e) { - Logger.LogWarning($"RPC error during endpoint discovery: {e.Status}"); + Logger.LogWarning("RPC error during endpoint discovery: {Status}", e.Status); } catch (Exception e) { - Logger.LogError($"Unexpected exception during session pool periodic check: {e}"); + Logger.LogError(e, "Unexpected exception during session pool periodic check"); } } } diff --git a/src/Ydb.Sdk/src/DriverConfig.cs b/src/Ydb.Sdk/src/DriverConfig.cs index 8bd1bd61..28eb457d 100644 --- a/src/Ydb.Sdk/src/DriverConfig.cs +++ b/src/Ydb.Sdk/src/DriverConfig.cs @@ -1,4 +1,5 @@ -using System.Security.Cryptography.X509Certificates; +using System.Reflection; +using System.Security.Cryptography.X509Certificates; using Ydb.Sdk.Auth; namespace Ydb.Sdk; @@ -21,6 +22,7 @@ public class DriverConfig internal X509Certificate2Collection CustomServerCertificates { get; } = new(); internal TimeSpan EndpointDiscoveryInterval = TimeSpan.FromMinutes(1); internal TimeSpan EndpointDiscoveryTimeout = TimeSpan.FromSeconds(10); + internal string SdkVersion { get; } public DriverConfig( string endpoint, @@ -42,6 +44,10 @@ public DriverConfig( { CustomServerCertificates.AddRange(customServerCertificates); } + + var version = Assembly.GetExecutingAssembly().GetName().Version; + var versionStr = version is null ? "unknown" : version.ToString(3); + SdkVersion = $"ydb-dotnet-sdk/{versionStr}"; } private static string FormatEndpoint(string endpoint) diff --git a/src/Ydb.Sdk/src/IDriver.cs b/src/Ydb.Sdk/src/IDriver.cs index 133937fa..55e9abec 100644 --- a/src/Ydb.Sdk/src/IDriver.cs +++ b/src/Ydb.Sdk/src/IDriver.cs @@ -138,7 +138,8 @@ protected async ValueTask GetCallOptions(GrpcRequestSettings settin { var meta = new Grpc.Core.Metadata { - { Metadata.RpcDatabaseHeader, Config.Database } + { Metadata.RpcDatabaseHeader, Config.Database }, + { Metadata.RpcSdkInfoHeader, Config.SdkVersion } }; if (CredentialsProvider != null) diff --git a/src/Ydb.Sdk/src/Services/Topic/Reader/Reader.cs b/src/Ydb.Sdk/src/Services/Topic/Reader/Reader.cs index 1383eb6f..1513f387 100644 --- a/src/Ydb.Sdk/src/Services/Topic/Reader/Reader.cs +++ b/src/Ydb.Sdk/src/Services/Topic/Reader/Reader.cs @@ -468,8 +468,8 @@ public async Task CommitOffsetRange(OffsetsRange offsetsRange, long partitionSes { var tcsCommit = new TaskCompletionSource(); - await using var register = _lifecycleReaderSessionCts.Token.Register( - () => tcsCommit.TrySetException(new ReaderException($"ReaderSession[{SessionId}] was deactivated")) + await using var register = _lifecycleReaderSessionCts.Token.Register(() => + tcsCommit.TrySetException(new ReaderException($"ReaderSession[{SessionId}] was deactivated")) ); var commitSending = new CommitSending(offsetsRange, tcsCommit); diff --git a/src/Ydb.Sdk/tests/Ado/YdbCommandTests.cs b/src/Ydb.Sdk/tests/Ado/YdbCommandTests.cs index 98d4ac67..eeb200fa 100644 --- a/src/Ydb.Sdk/tests/Ado/YdbCommandTests.cs +++ b/src/Ydb.Sdk/tests/Ado/YdbCommandTests.cs @@ -283,18 +283,18 @@ public void GetChars_WhenSelectText_MoveCharsToBuffer() Assert.Equal($"dataOffset must be between 0 and {int.MaxValue}", Assert.Throws(() => ydbDataReader.GetChars(0, -1, null, 0, 6)).Message); Assert.Equal($"dataOffset must be between 0 and {int.MaxValue}", - Assert.Throws( - () => ydbDataReader.GetChars(0, long.MaxValue, null, 0, 6)).Message); + Assert.Throws(() => + ydbDataReader.GetChars(0, long.MaxValue, null, 0, 6)).Message); - Assert.Equal("bufferOffset must be between 0 and 10", Assert.Throws( - () => ydbDataReader.GetChars(0, 0, bufferChars, -1, 6)).Message); - Assert.Equal("bufferOffset must be between 0 and 10", Assert.Throws( - () => ydbDataReader.GetChars(0, 0, bufferChars, -1, 6)).Message); + Assert.Equal("bufferOffset must be between 0 and 10", + Assert.Throws(() => ydbDataReader.GetChars(0, 0, bufferChars, -1, 6)).Message); + Assert.Equal("bufferOffset must be between 0 and 10", + Assert.Throws(() => ydbDataReader.GetChars(0, 0, bufferChars, -1, 6)).Message); - Assert.Equal("length must be between 0 and 10", Assert.Throws( - () => ydbDataReader.GetChars(0, 0, bufferChars, 3, -1)).Message); - Assert.Equal("bufferOffset must be between 0 and 5", Assert.Throws( - () => ydbDataReader.GetChars(0, 0, bufferChars, 8, 5)).Message); + Assert.Equal("length must be between 0 and 10", + Assert.Throws(() => ydbDataReader.GetChars(0, 0, bufferChars, 3, -1)).Message); + Assert.Equal("bufferOffset must be between 0 and 5", + Assert.Throws(() => ydbDataReader.GetChars(0, 0, bufferChars, 8, 5)).Message); Assert.Equal(6, ydbDataReader.GetChars(0, 0, bufferChars, 4, 6)); checkBuffer[4] = 'a'; @@ -330,19 +330,18 @@ public void GetBytes_WhenSelectBytes_MoveBytesToBuffer() Assert.Equal(7, ydbDataReader.GetBytes(0, 4, null, 0, 6)); Assert.Equal($"dataOffset must be between 0 and {int.MaxValue}", Assert.Throws(() => ydbDataReader.GetBytes(0, -1, null, 0, 6)).Message); - Assert.Equal($"dataOffset must be between 0 and {int.MaxValue}", - Assert.Throws( - () => ydbDataReader.GetBytes(0, long.MaxValue, null, 0, 6)).Message); - - Assert.Equal("bufferOffset must be between 0 and 10", Assert.Throws( - () => ydbDataReader.GetBytes(0, 0, bufferChars, -1, 6)).Message); - Assert.Equal("bufferOffset must be between 0 and 10", Assert.Throws( - () => ydbDataReader.GetBytes(0, 0, bufferChars, -1, 6)).Message); - - Assert.Equal("length must be between 0 and 10", Assert.Throws( - () => ydbDataReader.GetBytes(0, 0, bufferChars, 3, -1)).Message); - Assert.Equal("bufferOffset must be between 0 and 5", Assert.Throws( - () => ydbDataReader.GetBytes(0, 0, bufferChars, 8, 5)).Message); + Assert.Equal($"dataOffset must be between 0 and {int.MaxValue}", Assert.Throws(() => + ydbDataReader.GetBytes(0, long.MaxValue, null, 0, 6)).Message); + + Assert.Equal("bufferOffset must be between 0 and 10", + Assert.Throws(() => ydbDataReader.GetBytes(0, 0, bufferChars, -1, 6)).Message); + Assert.Equal("bufferOffset must be between 0 and 10", Assert.Throws(() => + ydbDataReader.GetBytes(0, 0, bufferChars, -1, 6)).Message); + + Assert.Equal("length must be between 0 and 10", Assert.Throws(() => + ydbDataReader.GetBytes(0, 0, bufferChars, 3, -1)).Message); + Assert.Equal("bufferOffset must be between 0 and 5", Assert.Throws(() => + ydbDataReader.GetBytes(0, 0, bufferChars, 8, 5)).Message); Assert.Equal(6, ydbDataReader.GetBytes(0, 0, bufferChars, 4, 6)); checkBuffer[4] = (byte)'a'; diff --git a/src/Ydb.Sdk/tests/Ado/YdbConnectionStringBuilderTests.cs b/src/Ydb.Sdk/tests/Ado/YdbConnectionStringBuilderTests.cs index 4a634a88..661aba4f 100644 --- a/src/Ydb.Sdk/tests/Ado/YdbConnectionStringBuilderTests.cs +++ b/src/Ydb.Sdk/tests/Ado/YdbConnectionStringBuilderTests.cs @@ -24,11 +24,11 @@ public void InitDefaultValues_WhenEmptyConstructorInvoke_ReturnDefaultConnection [Fact] public void InitConnectionStringBuilder_WhenUnexpectedKey_ThrowException() { - Assert.Equal("Key doesn't support: unexpectedkey", Assert.Throws( - () => new YdbConnectionStringBuilder("UnexpectedKey=123;Port=2135;")).Message); + Assert.Equal("Key doesn't support: unexpectedkey", Assert.Throws(() => + new YdbConnectionStringBuilder("UnexpectedKey=123;Port=2135;")).Message); - Assert.Equal("Key doesn't support: unexpectedkey", Assert.Throws( - () => new YdbConnectionStringBuilder { ConnectionString = "UnexpectedKey=123;Port=2135;" }).Message); + Assert.Equal("Key doesn't support: unexpectedkey", Assert.Throws(() => + new YdbConnectionStringBuilder { ConnectionString = "UnexpectedKey=123;Port=2135;" }).Message); } [Fact] diff --git a/src/Ydb.Sdk/tests/Ado/YdbDataReaderTests.cs b/src/Ydb.Sdk/tests/Ado/YdbDataReaderTests.cs index 0e04cf9b..c1ccab57 100644 --- a/src/Ydb.Sdk/tests/Ado/YdbDataReaderTests.cs +++ b/src/Ydb.Sdk/tests/Ado/YdbDataReaderTests.cs @@ -48,9 +48,8 @@ public async Task BasedIteration_WhenNotCallMethodRead_ThrowException() public async Task CreateYdbDataReader_WhenAbortedStatus_ThrowException() { var statuses = new List(); - Assert.Equal("Status: Aborted", (await Assert.ThrowsAsync( - () => YdbDataReader.CreateYdbDataReader(SingleEnumeratorFailed, statuses.Add))) - .Message); + Assert.Equal("Status: Aborted", (await Assert.ThrowsAsync(() => + YdbDataReader.CreateYdbDataReader(SingleEnumeratorFailed, statuses.Add))).Message); Assert.Single(statuses); Assert.Equal(StatusCode.Aborted, statuses[0].StatusCode); } diff --git a/src/Ydb.Sdk/tests/Ado/YdbParameterTests.cs b/src/Ydb.Sdk/tests/Ado/YdbParameterTests.cs index af383866..f7b481c2 100644 --- a/src/Ydb.Sdk/tests/Ado/YdbParameterTests.cs +++ b/src/Ydb.Sdk/tests/Ado/YdbParameterTests.cs @@ -224,12 +224,12 @@ public class TestDataGenerator : IEnumerable new object[] { new Data(DbType.DateTime2, null, value => value.GetOptionalTimestamp()) }, new object[] { - new Data(DbType.Binary, Encoding.ASCII.GetBytes("test str").ToArray(), + new Data(DbType.Binary, Encoding.ASCII.GetBytes("test str"), value => value.GetString()) }, new object[] { - new Data(DbType.Binary, Encoding.ASCII.GetBytes("test str").ToArray(), + new Data(DbType.Binary, Encoding.ASCII.GetBytes("test str"), value => value.GetString(), true) }, new object[] { new Data(DbType.Binary, null, value => value.GetOptionalString()) }, diff --git a/src/Ydb.Sdk/tests/Ado/YdbSchemaTests.cs b/src/Ydb.Sdk/tests/Ado/YdbSchemaTests.cs index b09e32e4..8e0076c0 100644 --- a/src/Ydb.Sdk/tests/Ado/YdbSchemaTests.cs +++ b/src/Ydb.Sdk/tests/Ado/YdbSchemaTests.cs @@ -47,8 +47,8 @@ public async Task GetSchema_WhenTablesCollection_ReturnAllTables() Assert.Equal(_table2, singleTable2.Rows[0]["table_name"].ToString()); Assert.Equal("TABLE", singleTable2.Rows[0]["table_type"].ToString()); - await Assert.ThrowsAsync( - async () => await ydbConnection.GetSchemaAsync("Tables", new[] { "not_found", null }) + await Assert.ThrowsAsync(async () => + await ydbConnection.GetSchemaAsync("Tables", new[] { "not_found", null }) ); } @@ -87,8 +87,8 @@ public async Task GetSchema_WhenTablesWithStatsCollection_ReturnAllTables() Assert.NotNull(singleTable2.Rows[0]["modification_time"]); // not found case - await Assert.ThrowsAsync( - async () => await ydbConnection.GetSchemaAsync("Tables", new[] { "not_found", null }) + await Assert.ThrowsAsync(async () => + await ydbConnection.GetSchemaAsync("Tables", new[] { "not_found", null }) ); } diff --git a/src/Ydb.Sdk/tests/Auth/StaticAuthTests.cs b/src/Ydb.Sdk/tests/Auth/StaticAuthTests.cs index 29e12f16..03212cdc 100644 --- a/src/Ydb.Sdk/tests/Auth/StaticAuthTests.cs +++ b/src/Ydb.Sdk/tests/Auth/StaticAuthTests.cs @@ -90,8 +90,8 @@ private async Task CheckAuth(string? passwordCreate, string? passwordAuth) public async Task NoPasswordAuth() => await CheckAuth(null, null); [Fact] - public async Task WrongPassword() => await Assert.ThrowsAsync( - async () => await CheckAuth("good_password", "wrong_password")); + public async Task WrongPassword() => await Assert.ThrowsAsync(async () => + await CheckAuth("good_password", "wrong_password")); [Fact] public async Task NotExistAuth() @@ -101,7 +101,7 @@ public async Task NotExistAuth() database: "/local" ) { User = "notexists", Password = "nopass" }; - await Assert.ThrowsAsync( - async () => await Driver.CreateInitialized(driverConfig, _loggerFactory)); + await Assert.ThrowsAsync(async () => + await Driver.CreateInitialized(driverConfig, _loggerFactory)); } } diff --git a/src/Ydb.Sdk/tests/Table/GracefulShutdownTests.cs b/src/Ydb.Sdk/tests/Table/GracefulShutdownTests.cs index da52f637..a4e74984 100644 --- a/src/Ydb.Sdk/tests/Table/GracefulShutdownTests.cs +++ b/src/Ydb.Sdk/tests/Table/GracefulShutdownTests.cs @@ -22,8 +22,7 @@ public GracefulShutdownTests(TableClientFixture tableClientFixture) public async Task Test() { var session1 = ""; - await _tableClientFixture.TableClient.SessionExec( - async session => + await _tableClientFixture.TableClient.SessionExec(async session => { session1 = session.Id; return await session.ExecuteDataQuery("SELECT 1", TxControl.BeginSerializableRW().Commit()); @@ -31,8 +30,7 @@ await _tableClientFixture.TableClient.SessionExec( ); var session2 = ""; - await _tableClientFixture.TableClient.SessionExec( - async session => + await _tableClientFixture.TableClient.SessionExec(async session => { session2 = session.Id; return await session.ExecuteDataQuery("SELECT 1", TxControl.BeginSerializableRW().Commit()); @@ -49,8 +47,7 @@ await _tableClientFixture.TableClient.SessionExec( // new session var session3 = ""; - await _tableClientFixture.TableClient.SessionExec( - async session => + await _tableClientFixture.TableClient.SessionExec(async session => { session3 = session.Id; return await session.ExecuteDataQuery("SELECT 1", TxControl.BeginSerializableRW().Commit()); @@ -60,8 +57,7 @@ await _tableClientFixture.TableClient.SessionExec( Assert.Equal(session2, session3); var session4 = ""; - await _tableClientFixture.TableClient.SessionExec( - async session => + await _tableClientFixture.TableClient.SessionExec(async session => { session4 = session.Id; return await session.ExecuteDataQuery("SELECT 1", TxControl.BeginSerializableRW().Commit()); diff --git a/src/Ydb.Sdk/tests/Table/RollbackTableTests.cs b/src/Ydb.Sdk/tests/Table/RollbackTableTests.cs index 8cdd5991..1cf041ec 100644 --- a/src/Ydb.Sdk/tests/Table/RollbackTableTests.cs +++ b/src/Ydb.Sdk/tests/Table/RollbackTableTests.cs @@ -17,8 +17,8 @@ public RollbackTableTests(TableClientFixture tableClientFixture) [Fact] public async Task RollbackTransactionTest() { - var response = await _tableClientFixture.TableClient.SessionExec( - async session => await session.ExecuteSchemeQuery(@" + var response = await _tableClientFixture.TableClient.SessionExec(async session => + await session.ExecuteSchemeQuery(@" CREATE TABLE `test` ( id Int32 NOT NULL, name Text, diff --git a/src/Ydb.Sdk/tests/Utils.cs b/src/Ydb.Sdk/tests/Utils.cs index a7099917..c3d5164e 100644 --- a/src/Ydb.Sdk/tests/Utils.cs +++ b/src/Ydb.Sdk/tests/Utils.cs @@ -32,9 +32,8 @@ public static async Task ExecuteDataQuery(TableClient public static async Task ExecuteSchemeQuery( TableClient tableClient, string query, bool ensureSuccess = true) { - var response = await tableClient.SessionExec( - async session => - await session.ExecuteSchemeQuery(query: query)); + var response = await tableClient.SessionExec(async session => + await session.ExecuteSchemeQuery(query: query)); if (ensureSuccess) {