11using System . Collections . Concurrent ;
2- using System . ComponentModel ;
32using System . Diagnostics . CodeAnalysis ;
43using System . Runtime . CompilerServices ;
5- using System . Threading . Channels ;
4+ using Ydb . Query ;
5+ using Ydb . Sdk . Value ;
66
77namespace Ydb . Sdk . Ado . Session ;
88
9- internal sealed class PoolingSessionSource : ISessionSource < PoolingSession >
9+ internal sealed class PoolingSessionSource : ISessionSource < PoolingSessionBase >
1010{
11- private readonly ConcurrentStack < PoolingSession > _idleSessions = new ( ) ;
12- private readonly ConcurrentQueue < TaskCompletionSource < PoolingSession ? > > _waiters = new ( ) ;
11+ private readonly ConcurrentStack < PoolingSessionBase > _idleSessions = new ( ) ;
12+ private readonly ConcurrentQueue < TaskCompletionSource < PoolingSessionBase ? > > _waiters = new ( ) ;
1313
1414 private readonly IPoolingSessionFactory _sessionFactory ;
1515
1616 private readonly int _minSessionSize ;
1717 private readonly int _maxSessionSize ;
1818
19- private readonly PoolingSession ? [ ] _sessions ;
19+ private readonly PoolingSessionBase ? [ ] _sessions ;
2020
2121 private readonly int _createSessionTimeout ;
2222 private readonly TimeSpan _sessionIdleTimeout ;
@@ -39,19 +39,19 @@ YdbConnectionStringBuilder settings
3939 $ "Connection can't have 'Max Session Pool' { _maxSessionSize } under 'Min Session Pool' { _minSessionSize } ") ;
4040 }
4141
42- _sessions = new PoolingSession ? [ _maxSessionSize ] ;
42+ _sessions = new PoolingSessionBase ? [ _maxSessionSize ] ;
4343 _createSessionTimeout = settings . CreateSessionTimeout ;
4444 _sessionIdleTimeout = TimeSpan . FromSeconds ( settings . SessionIdleTimeout ) ;
4545 _cleanerTimer = new Timer ( CleanIdleSessions , this , _sessionIdleTimeout , _sessionIdleTimeout ) ;
4646 }
4747
48- public ValueTask < PoolingSession > OpenSession ( CancellationToken cancellationToken = default ) =>
48+ public ValueTask < PoolingSessionBase > OpenSession ( CancellationToken cancellationToken = default ) =>
4949 TryGetIdleSession ( out var session )
50- ? new ValueTask < PoolingSession > ( session )
50+ ? new ValueTask < PoolingSessionBase > ( session )
5151 : RentAsync ( cancellationToken ) ;
5252
5353 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
54- private bool TryGetIdleSession ( [ NotNullWhen ( true ) ] out PoolingSession ? session )
54+ private bool TryGetIdleSession ( [ NotNullWhen ( true ) ] out PoolingSessionBase ? session )
5555 {
5656 while ( _idleSessions . TryPop ( out session ) )
5757 {
@@ -65,7 +65,7 @@ private bool TryGetIdleSession([NotNullWhen(true)] out PoolingSession? session)
6565 }
6666
6767 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
68- private bool CheckIdleSession ( [ NotNullWhen ( true ) ] PoolingSession ? session )
68+ private bool CheckIdleSession ( [ NotNullWhen ( true ) ] PoolingSessionBase ? session )
6969 {
7070 if ( session == null || session . State == PoolingSessionState . Clean )
7171 {
@@ -82,7 +82,7 @@ private bool CheckIdleSession([NotNullWhen(true)] PoolingSession? session)
8282 return session . CompareAndSet ( PoolingSessionState . In , PoolingSessionState . Out ) ;
8383 }
8484
85- private async ValueTask < PoolingSession > RentAsync ( CancellationToken cancellationToken )
85+ private async ValueTask < PoolingSessionBase > RentAsync ( CancellationToken cancellationToken )
8686 {
8787 using var ctsGetSession = CancellationTokenSource . CreateLinkedTokenSource ( cancellationToken ) ;
8888 if ( _createSessionTimeout > 0 )
@@ -97,7 +97,7 @@ private async ValueTask<PoolingSession> RentAsync(CancellationToken cancellation
9797 while ( true )
9898 {
9999 var waiterTcs =
100- new TaskCompletionSource < PoolingSession ? > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
100+ new TaskCompletionSource < PoolingSessionBase ? > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
101101 _waiters . Enqueue ( waiterTcs ) ;
102102 await using var _ = finalToken . Register ( ( ) => waiterTcs . TrySetCanceled ( ) , useSynchronizationContext : false ) ;
103103 session = await waiterTcs . Task . ConfigureAwait ( false ) ;
@@ -111,7 +111,7 @@ private async ValueTask<PoolingSession> RentAsync(CancellationToken cancellation
111111 }
112112 }
113113
114- private async ValueTask < PoolingSession ? > OpenNewSession ( CancellationToken cancellationToken )
114+ private async ValueTask < PoolingSessionBase ? > OpenNewSession ( CancellationToken cancellationToken )
115115 {
116116 // As long as we're under max capacity, attempt to increase the session count and open a new session.
117117 for ( var numSessions = _numSessions ; numSessions < _maxSessionSize ; numSessions = _numSessions )
@@ -156,7 +156,7 @@ private void WakeUpWaiter()
156156 waiter . TrySetResult ( null ) ; // wake up waiter!
157157 }
158158
159- public void Return ( PoolingSession session )
159+ public void Return ( PoolingSessionBase session )
160160 {
161161 if ( session . IsBroken )
162162 {
@@ -181,7 +181,7 @@ public void Return(PoolingSession session)
181181 WakeUpWaiter ( ) ;
182182 }
183183
184- private void CloseSession ( PoolingSession session )
184+ private void CloseSession ( PoolingSessionBase session )
185185 {
186186 var i = 0 ;
187187 for ( ; i < _maxSessionSize ; i ++ )
@@ -224,7 +224,7 @@ private static void CleanIdleSessions(object? state)
224224
225225internal interface IPoolingSessionFactory
226226{
227- PoolingSession NewSession ( PoolingSessionSource source ) ;
227+ PoolingSessionBase NewSession ( PoolingSessionSource source ) ;
228228}
229229
230230internal enum PoolingSessionState
@@ -233,3 +233,44 @@ internal enum PoolingSessionState
233233 Out ,
234234 Clean
235235}
236+
237+ internal abstract class PoolingSessionBase : ISession
238+ {
239+ private readonly PoolingSessionSource _source ;
240+
241+ private int _state = ( int ) PoolingSessionState . In ;
242+
243+ protected PoolingSessionBase ( PoolingSessionSource source )
244+ {
245+ _source = source ;
246+ }
247+
248+ internal bool CompareAndSet ( PoolingSessionState expected , PoolingSessionState actual ) =>
249+ Interlocked . CompareExchange ( ref _state , ( int ) expected , ( int ) actual ) == ( int ) expected ;
250+
251+ internal void Set ( PoolingSessionState state ) => Interlocked . Exchange ( ref _state , ( int ) state ) ;
252+
253+ internal PoolingSessionState State => ( PoolingSessionState ) Volatile . Read ( ref _state ) ;
254+
255+ internal DateTime IdleStartTime { get ; set ; }
256+
257+ public abstract IDriver Driver { get ; }
258+
259+ public abstract bool IsBroken { get ; }
260+
261+ internal abstract Task Open ( CancellationToken cancellationToken ) ;
262+
263+ internal abstract Task DeleteSession ( ) ;
264+
265+ public abstract ValueTask < IServerStream < ExecuteQueryResponsePart > > ExecuteQuery ( string query ,
266+ Dictionary < string , YdbValue > parameters , GrpcRequestSettings settings ,
267+ TransactionControl ? txControl ) ;
268+
269+ public abstract Task CommitTransaction ( string txId , CancellationToken cancellationToken = default ) ;
270+
271+ public abstract Task RollbackTransaction ( string txId , CancellationToken cancellationToken = default ) ;
272+
273+ public abstract void OnNotSuccessStatusCode ( StatusCode code ) ;
274+
275+ public void Close ( ) => _source . Return ( this ) ;
276+ }
0 commit comments