22using Grpc . Net . Client ;
33using Microsoft . Extensions . Logging ;
44using Ydb . Sdk . Auth ;
5+ using Ydb . Sdk . Pool ;
6+ using Ydb . Sdk . Services . Auth ;
57
68namespace Ydb . Sdk ;
79
@@ -45,16 +47,35 @@ public interface IBidirectionalStream<in TRequest, out TResponse> : IDisposable
4547
4648public abstract class BaseDriver : IDriver
4749{
50+ private readonly ICredentialsProvider ? _credentialsProvider ;
51+
4852 protected readonly DriverConfig Config ;
4953 protected readonly ILogger Logger ;
5054
55+ internal readonly GrpcChannelFactory GrpcChannelFactory ;
56+ internal readonly ChannelPool < GrpcChannel > ChannelPool ;
57+
5158 protected int Disposed ;
5259
53- protected BaseDriver ( DriverConfig config , ILoggerFactory loggerFactory , ILogger logger )
60+ internal BaseDriver (
61+ DriverConfig config ,
62+ ILoggerFactory loggerFactory ,
63+ ILogger logger
64+ )
5465 {
5566 Config = config ;
5667 Logger = logger ;
5768 LoggerFactory = loggerFactory ;
69+
70+ GrpcChannelFactory = new GrpcChannelFactory ( LoggerFactory , Config ) ;
71+ ChannelPool = new ChannelPool < GrpcChannel > ( LoggerFactory , GrpcChannelFactory ) ;
72+
73+ _credentialsProvider = Config . User != null
74+ ? new CachedCredentialsProvider (
75+ new StaticCredentialsAuthClient ( Config , GrpcChannelFactory , LoggerFactory ) ,
76+ LoggerFactory
77+ )
78+ : Config . Credentials ;
5879 }
5980
6081 public async Task < TResponse > UnaryCall < TRequest , TResponse > (
@@ -64,7 +85,9 @@ public async Task<TResponse> UnaryCall<TRequest, TResponse>(
6485 where TRequest : class
6586 where TResponse : class
6687 {
67- var ( endpoint , channel ) = GetChannel ( settings . NodeId ) ;
88+ var endpoint = GetEndpoint ( settings . NodeId ) ;
89+ var channel = ChannelPool . GetChannel ( endpoint ) ;
90+
6891 var callInvoker = channel . CreateCallInvoker ( ) ;
6992
7093 Logger . LogTrace ( "Unary call, method: {MethodName}, endpoint: {Endpoint}" , method . Name , endpoint ) ;
@@ -97,7 +120,9 @@ public async ValueTask<ServerStream<TResponse>> ServerStreamCall<TRequest, TResp
97120 where TRequest : class
98121 where TResponse : class
99122 {
100- var ( endpoint , channel ) = GetChannel ( settings . NodeId ) ;
123+ var endpoint = GetEndpoint ( settings . NodeId ) ;
124+ var channel = ChannelPool . GetChannel ( endpoint ) ;
125+
101126 var callInvoker = channel . CreateCallInvoker ( ) ;
102127
103128 var call = callInvoker . AsyncServerStreamingCall (
@@ -115,7 +140,9 @@ public async ValueTask<IBidirectionalStream<TRequest, TResponse>> BidirectionalS
115140 where TRequest : class
116141 where TResponse : class
117142 {
118- var ( endpoint , channel ) = GetChannel ( settings . NodeId ) ;
143+ var endpoint = GetEndpoint ( settings . NodeId ) ;
144+ var channel = ChannelPool . GetChannel ( endpoint ) ;
145+
119146 var callInvoker = channel . CreateCallInvoker ( ) ;
120147
121148 var call = callInvoker . AsyncDuplexStreamingCall (
@@ -126,36 +153,29 @@ public async ValueTask<IBidirectionalStream<TRequest, TResponse>> BidirectionalS
126153 return new BidirectionalStream < TRequest , TResponse > (
127154 call ,
128155 e => { OnRpcError ( endpoint , e ) ; } ,
129- CredentialsProvider
156+ _credentialsProvider
130157 ) ;
131158 }
132159
133- protected abstract ( string , GrpcChannel ) GetChannel ( long nodeId ) ;
160+ protected abstract string GetEndpoint ( long nodeId ) ;
134161
135162 protected abstract void OnRpcError ( string endpoint , RpcException e ) ;
136163
137164 protected async ValueTask < CallOptions > GetCallOptions ( GrpcRequestSettings settings )
138165 {
139- var meta = new Grpc . Core . Metadata
140- {
141- { Metadata . RpcDatabaseHeader , Config . Database } ,
142- { Metadata . RpcSdkInfoHeader , Config . SdkVersion }
143- } ;
166+ var meta = Config . GetCallMetadata ;
144167
145- if ( CredentialsProvider != null )
168+ if ( _credentialsProvider != null )
146169 {
147- meta . Add ( Metadata . RpcAuthHeader , await CredentialsProvider . GetAuthInfoAsync ( ) ) ;
170+ meta . Add ( Metadata . RpcAuthHeader , await _credentialsProvider . GetAuthInfoAsync ( ) ) ;
148171 }
149172
150173 if ( settings . TraceId . Length > 0 )
151174 {
152175 meta . Add ( Metadata . RpcTraceIdHeader , settings . TraceId ) ;
153176 }
154177
155- var options = new CallOptions (
156- headers : meta ,
157- cancellationToken : settings . CancellationToken
158- ) ;
178+ var options = new CallOptions ( headers : meta , cancellationToken : settings . CancellationToken ) ;
159179
160180 if ( settings . TransportTimeout != TimeSpan . Zero )
161181 {
@@ -165,8 +185,6 @@ protected async ValueTask<CallOptions> GetCallOptions(GrpcRequestSettings settin
165185 return options ;
166186 }
167187
168- protected abstract ICredentialsProvider ? CredentialsProvider { get ; }
169-
170188 public ILoggerFactory LoggerFactory { get ; }
171189
172190 public void Dispose ( ) => DisposeAsync ( ) . AsTask ( ) . GetAwaiter ( ) . GetResult ( ) ;
@@ -175,11 +193,11 @@ public async ValueTask DisposeAsync()
175193 {
176194 if ( Interlocked . CompareExchange ( ref Disposed , 1 , 0 ) == 0 )
177195 {
178- await InternalDispose ( ) ;
196+ await ChannelPool . DisposeAsync ( ) ;
197+
198+ GC . SuppressFinalize ( this ) ;
179199 }
180200 }
181-
182- protected abstract ValueTask InternalDispose ( ) ;
183201}
184202
185203public sealed class ServerStream < TResponse > : IAsyncEnumerator < TResponse > , IAsyncEnumerable < TResponse >
0 commit comments