Skip to content

Commit 04f41b0

Browse files
committed
test
1 parent 991a412 commit 04f41b0

File tree

9 files changed

+76
-74
lines changed

9 files changed

+76
-74
lines changed

src/EFCore.Ydb/CHANGELOG.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
- Added EF provider support for implicit sessions.
21
- Fixed Decimal precision/scale mapping in EF provider.
32
- Supported Guid (Uuid YDB type).
43
- PrivateAssets="none" is set to flow the EF Core analyzer to users referencing this package [issue](https://github.com/aspnet/EntityFrameworkCore/pull/11350).

src/Ydb.Sdk/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
- Added provider support for implicit sessions.
12
- Feat ADO.NET: `YdbDataSource.OpenRetryableConnectionAsync` opens a retryable connection with automatic retries for transient failures.
23
- Fixed bug ADO.NET/PoolManager: `SemaphoreSlim.WaitAsync` over-release on cancellation.
34
- Feat ADO.NET: Mark `YdbConnection.State` as `Broken` when the underlying session is broken, including background deactivation.

src/Ydb.Sdk/src/Ado/PoolManager.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ internal static class PoolManager
1010
internal static readonly ConcurrentDictionary<string, IDriver> Drivers = new();
1111
internal static readonly ConcurrentDictionary<string, ISessionSource> Pools = new();
1212

13-
internal static async ValueTask<ISessionSource> Get(
13+
internal static async Task<ISession> GetSession(
1414
YdbConnectionStringBuilder settings,
1515
CancellationToken cancellationToken
1616
)
1717
{
1818
if (Pools.TryGetValue(settings.ConnectionString, out var sessionPool))
1919
{
20-
return sessionPool;
20+
return await sessionPool.OpenSession(cancellationToken);
2121
}
2222

2323
await SemaphoreSlim.WaitAsync(cancellationToken);
@@ -26,7 +26,7 @@ CancellationToken cancellationToken
2626
{
2727
if (Pools.TryGetValue(settings.ConnectionString, out var pool))
2828
{
29-
return pool;
29+
return await pool.OpenSession(cancellationToken);
3030
}
3131

3232
var driver = Drivers.TryGetValue(settings.GrpcConnectionString, out var cacheDriver) &&
@@ -42,7 +42,7 @@ CancellationToken cancellationToken
4242

4343
Pools[settings.ConnectionString] = newSessionPool;
4444

45-
return newSessionPool;
45+
return await newSessionPool.OpenSession(cancellationToken);
4646
}
4747
finally
4848
{

src/Ydb.Sdk/src/Ado/Session/ImplicitSession.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public void OnNotSuccessStatusCode(StatusCode code)
5050
{
5151
}
5252

53-
public void Close() => _source.ReleaseLease();
53+
public void Dispose() => _source.ReleaseLease();
5454

5555
private static YdbException NotSupportedTransaction => new("Transactions are not supported in implicit sessions");
5656
}

src/Ydb.Sdk/src/Ado/YdbCommand.cs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Diagnostics.CodeAnalysis;
44
using System.Text;
55
using Ydb.Sdk.Ado.Internal;
6+
using Ydb.Sdk.Ado.Session;
67

78
namespace Ydb.Sdk.Ado;
89

@@ -211,14 +212,38 @@ protected override async Task<DbDataReader> ExecuteDbDataReaderAsync(CommandBeha
211212

212213
var transaction = YdbConnection.CurrentTransaction;
213214

214-
if (Transaction != null && Transaction != transaction) // assert on legacy DbTransaction property
215+
if (Transaction != null && Transaction != transaction)
215216
{
216217
throw new InvalidOperationException("Transaction mismatched! (Maybe using another connection)");
217218
}
218219

219-
var ydbDataReader = await YdbDataReader.CreateYdbDataReader(await YdbConnection.Session.ExecuteQuery(
220-
preparedSql.ToString(), ydbParameters, execSettings, transaction?.TransactionControl
221-
), YdbConnection.OnNotSuccessStatusCode, transaction, cancellationToken);
220+
var useImplicit = YdbConnection.EnableImplicitSession && transaction is null;
221+
var session = useImplicit
222+
? new ImplicitSession(YdbConnection.Session.Driver, new ImplicitSessionSource(YdbConnection.Session.Driver))
223+
: YdbConnection.Session;
224+
225+
YdbDataReader ydbDataReader;
226+
try
227+
{
228+
var execResult = await session.ExecuteQuery(
229+
preparedSql.ToString(),
230+
ydbParameters,
231+
execSettings,
232+
transaction?.TransactionControl
233+
);
234+
235+
ydbDataReader = await YdbDataReader.CreateYdbDataReader(
236+
execResult,
237+
YdbConnection.OnNotSuccessStatusCode,
238+
transaction,
239+
cancellationToken
240+
);
241+
}
242+
finally
243+
{
244+
if (useImplicit)
245+
session.Dispose();
246+
}
222247

223248
YdbConnection.LastReader = ydbDataReader;
224249
YdbConnection.LastCommand = CommandText;

src/Ydb.Sdk/src/Ado/YdbConnection.cs

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.Data.Common;
33
using System.Diagnostics.CodeAnalysis;
44
using Ydb.Sdk.Ado.BulkUpsert;
5-
using Ydb.Sdk.Ado.RetryPolicy;
65
using Ydb.Sdk.Ado.Session;
76
using static System.Data.IsolationLevel;
87

@@ -39,11 +38,6 @@ internal ISession Session
3938

4039
private ISession _session = null!;
4140

42-
internal bool EnableImplicitSession => ConnectionStringBuilder.EnableImplicitSession;
43-
44-
internal ISession GetExecutionSession(bool useImplicit)
45-
=> useImplicit ? PoolManager.GetImplicitSession(ConnectionStringBuilder) : Session;
46-
4741
public YdbConnection()
4842
{
4943
}
@@ -87,7 +81,11 @@ public YdbTransaction BeginTransaction(TransactionMode transactionMode = Transac
8781
return CurrentTransaction;
8882
}
8983

90-
public override void ChangeDatabase(string databaseName) => throw new NotSupportedException();
84+
public override void ChangeDatabase(string databaseName)
85+
{
86+
}
87+
88+
internal bool EnableImplicitSession => ConnectionStringBuilder.EnableImplicitSession;
9189

9290
public override void Close() => CloseAsync().GetAwaiter().GetResult();
9391

@@ -97,29 +95,13 @@ public override async Task OpenAsync(CancellationToken cancellationToken)
9795
{
9896
ThrowIfConnectionOpen();
9997

100-
var sessionSource = await PoolManager.Get(ConnectionStringBuilder, cancellationToken);
101-
102-
Session = await sessionSource.OpenSession(cancellationToken);
98+
Session = await PoolManager.GetSession(ConnectionStringBuilder, cancellationToken);
10399

104100
OnStateChange(ClosedToOpenEventArgs);
105101

106102
ConnectionState = ConnectionState.Open;
107103
}
108104

109-
internal async ValueTask OpenAsync(
110-
YdbRetryPolicyExecutor retryPolicyExecutor,
111-
CancellationToken cancellationToken = default
112-
)
113-
{
114-
ThrowIfConnectionOpen();
115-
116-
var sessionSource = await PoolManager.Get(ConnectionStringBuilder, cancellationToken);
117-
118-
Session = new RetryableSession(sessionSource, retryPolicyExecutor);
119-
120-
ConnectionState = ConnectionState.Open;
121-
}
122-
123105
public override async Task CloseAsync()
124106
{
125107
// ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault

src/Ydb.Sdk/src/Ado/YdbDataSource.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -390,8 +390,7 @@ public async ValueTask<YdbConnection> OpenRetryableConnectionAsync(CancellationT
390390
var ydbConnection = CreateDbConnection();
391391
try
392392
{
393-
await ydbConnection.OpenAsync(_retryPolicyExecutor, cancellationToken);
394-
393+
await ydbConnection.OpenAsync(cancellationToken);
395394
return ydbConnection;
396395
}
397396
catch
@@ -409,8 +408,7 @@ public async ValueTask<YdbConnection> OpenRetryableConnectionAsync(
409408
var ydbConnection = CreateDbConnection();
410409
try
411410
{
412-
await ydbConnection.OpenAsync(GetExecutor(ydbRetryPolicyConfig), cancellationToken);
413-
411+
await ydbConnection.OpenAsync(cancellationToken);
414412
return ydbConnection;
415413
}
416414
catch
@@ -428,8 +426,7 @@ public async ValueTask<YdbConnection> OpenRetryableConnectionAsync(
428426
var ydbConnection = CreateDbConnection();
429427
try
430428
{
431-
await ydbConnection.OpenAsync(new YdbRetryPolicyExecutor(retryPolicy), cancellationToken);
432-
429+
await ydbConnection.OpenAsync(cancellationToken);
433430
return ydbConnection;
434431
}
435432
catch

src/Ydb.Sdk/test/Ydb.Sdk.Ado.Tests/Session/YdbImplicitStressTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public async Task Dispose_WaitsForAllLeases_AndSignalsOnEmptyExactlyOnce()
4343

4444
await Task.Delay(rnd.Next(0, 5), cts.Token);
4545

46-
s.Close();
46+
s.Dispose();
4747
closed.Inc();
4848
}
4949
catch (ObjectDisposedException)
@@ -90,7 +90,7 @@ public async Task Stress_Counts_AreBalanced()
9090

9191
await Task.Delay(rnd.Next(0, 3), cts.Token);
9292

93-
s.Close();
93+
s.Dispose();
9494
closed.Inc();
9595
}
9696
catch (ObjectDisposedException)
@@ -123,7 +123,7 @@ public async Task Open_RacingWithDispose_StateRemainsConsistent()
123123
try
124124
{
125125
var s = await source.OpenSession(cts.Token);
126-
s.Close();
126+
s.Dispose();
127127
return 1;
128128
}
129129
catch (ObjectDisposedException)

src/Ydb.Sdk/test/Ydb.Sdk.Ado.Tests/YdbConnectionTests.cs

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Data;
22
using Xunit;
3+
using Ydb.Sdk.Ado.Session;
34
using Ydb.Sdk.Ado.Tests.Utils;
45
using Ydb.Sdk.Ado.YdbType;
56

@@ -487,9 +488,7 @@ public async Task EnableImplicitSession_WhenTrue_AndNoTransaction_UsesImplicitSe
487488
var result = Convert.ToInt64(await cmd.ExecuteScalarAsync());
488489
Assert.Equal(1L, result);
489490

490-
var implicitSession = conn.GetExecutionSession(useImplicit: true);
491-
var pooledSession = conn.GetExecutionSession(useImplicit: false);
492-
Assert.NotEqual(implicitSession, pooledSession);
491+
Assert.IsType<ImplicitSession>(conn.Session);
493492
}
494493

495494
[Fact]
@@ -507,11 +506,7 @@ public async Task EnableImplicitSession_WhenTrue_ButInsideTransaction_UsesPooled
507506
var result = Convert.ToInt64(await cmd.ExecuteScalarAsync());
508507
Assert.Equal(1L, result);
509508

510-
var pooledSession = conn.GetExecutionSession(useImplicit: false);
511-
var implicitSession = conn.GetExecutionSession(useImplicit: true);
512-
513-
Assert.Equal(pooledSession, conn.Session);
514-
Assert.NotEqual(pooledSession, implicitSession);
509+
Assert.IsNotType<ImplicitSession>(conn.Session);
515510
}
516511

517512
[Fact]
@@ -527,8 +522,7 @@ public async Task EnableImplicitSession_WhenFalse_AlwaysUsesPooledSession()
527522
var result = (long)(await cmd.ExecuteScalarAsync())!;
528523
Assert.Equal(1L, result);
529524

530-
var pooledSession = conn.GetExecutionSession(useImplicit: false);
531-
Assert.Equal(pooledSession, conn.Session);
525+
Assert.IsNotType<ImplicitSession>(conn.Session);
532526
}
533527

534528
[Fact]
@@ -539,28 +533,38 @@ public async Task EnableImplicitSession_DifferentConnectionStrings_HaveDifferent
539533

540534
await using var conn1 = new YdbConnection(cs1);
541535
await conn1.OpenAsync();
542-
var session1 = conn1.GetExecutionSession(useImplicit: true);
536+
var s1 = conn1.Session;
543537

544538
await using var conn2 = new YdbConnection(cs2);
545539
await conn2.OpenAsync();
546-
var session2 = conn2.GetExecutionSession(useImplicit: true);
540+
var s2 = conn2.Session;
547541

548-
Assert.NotEqual(session1, session2);
542+
Assert.NotEqual(s1, s2);
549543
}
550-
544+
551545
[Fact]
552-
public async Task EnableImplicitSession_TwoSequentialCommands_GetDifferentImplicitSessions()
546+
public async Task EnableImplicitSession_TwoSequentialCommands_ReusesSameSession()
553547
{
554548
var cs = ConnectionString + ";EnableImplicitSession=true";
555549
await using var conn = new YdbConnection(cs);
556550
await conn.OpenAsync();
557551

558-
var s1 = conn.GetExecutionSession(useImplicit: true);
559-
var s2 = conn.GetExecutionSession(useImplicit: true);
552+
var cmd1 = conn.CreateCommand();
553+
cmd1.CommandText = "SELECT 1;";
554+
var result1 = await cmd1.ExecuteScalarAsync();
560555

561-
Assert.NotEqual(s1, s2);
556+
var s1 = conn.Session;
557+
558+
var cmd2 = conn.CreateCommand();
559+
cmd2.CommandText = "SELECT 2;";
560+
var result2 = await cmd2.ExecuteScalarAsync();
561+
562+
var s2 = conn.Session;
563+
564+
Assert.Equal(s1, s2);
565+
562566
}
563-
567+
564568
[Fact]
565569
public async Task ClearPool_FireAndForget_DoesNotBlock_And_PoolsRecreate()
566570
{
@@ -572,10 +576,9 @@ public async Task ClearPool_FireAndForget_DoesNotBlock_And_PoolsRecreate()
572576
";ConnectTimeout=3" +
573577
";KeepAlivePingDelay=0;KeepAlivePingTimeout=0";
574578

575-
var csPooled = csBase; // pooled-пул (без флага)
576-
var csImplicit = csBase + ";EnableImplicitSession=true"; // implicit-пул (с флагом)
579+
var csPooled = csBase;
580+
var csImplicit = csBase + ";EnableImplicitSession=true";
577581

578-
// 1) Прогреваем оба пула (pooled и implicit), чтобы они точно были созданы.
579582
await using (var warmPooled = new YdbConnection(csPooled))
580583
{
581584
await warmPooled.OpenAsync();
@@ -592,34 +595,29 @@ public async Task ClearPool_FireAndForget_DoesNotBlock_And_PoolsRecreate()
592595
Assert.Equal(1L, Convert.ToInt64(await cmd.ExecuteScalarAsync()));
593596
}
594597

595-
// 2) Вызываем ClearPool для ОБОИХ ключей (по вашей реализации ключи разные).
596598
var clearPooledTask = YdbConnection.ClearPool(new YdbConnection(csPooled));
597599
var clearImplicitTask = YdbConnection.ClearPool(new YdbConnection(csImplicit));
598600

599-
// 3) Убеждаемся, что ClearPool не блокирует — завершается быстро (fail-fast).
600-
// (Если вдруг среда перегружена, можно поднять таймаут до 3–5 секунд.)
601601
var done = await Task.WhenAny(Task.WhenAll(clearPooledTask, clearImplicitTask), Task.Delay(TimeSpan.FromSeconds(2)));
602602
Assert.True(done is not null && done != Task.Delay(TimeSpan.FromSeconds(2)), "ClearPool() must not block.");
603603

604-
// 4) Проверяем, что пулы корректно пересоздаются после очистки:
605-
// pooled — без флага, implicit — с флагом.
606604
await using (var checkPooled = new YdbConnection(csPooled))
607605
{
608606
await checkPooled.OpenAsync();
609-
using var cmd = checkPooled.CreateCommand();
607+
await using var cmd = checkPooled.CreateCommand();
610608
cmd.CommandText = "SELECT 1";
611609
Assert.Equal(1L, Convert.ToInt64(await cmd.ExecuteScalarAsync()));
612610
}
613611

614612
await using (var checkImplicit = new YdbConnection(csImplicit))
615613
{
616614
await checkImplicit.OpenAsync();
617-
using var cmd = checkImplicit.CreateCommand();
615+
await using var cmd = checkImplicit.CreateCommand();
618616
cmd.CommandText = "SELECT 1";
619617
Assert.Equal(1L, Convert.ToInt64(await cmd.ExecuteScalarAsync()));
620618
}
621619
}
622-
620+
623621
[Fact]
624622
public async Task EnableImplicitSession_ParallelQueries_WorkFine()
625623
{
@@ -636,7 +634,7 @@ public async Task EnableImplicitSession_ParallelQueries_WorkFine()
636634
});
637635
await Task.WhenAll(tasks);
638636
}
639-
637+
640638
[Fact]
641639
public async Task EnableImplicitSession_WithDisableDiscovery_Works()
642640
{

0 commit comments

Comments
 (0)