11package tech .ydb .jdbc .context ;
22
33import java .sql .SQLException ;
4+ import java .util .Map ;
45import java .util .Objects ;
6+ import java .util .concurrent .atomic .AtomicInteger ;
57import java .util .logging .Level ;
68import java .util .logging .Logger ;
79
810import tech .ydb .core .grpc .GrpcTransport ;
11+ import tech .ydb .core .grpc .GrpcTransportBuilder ;
912import tech .ydb .jdbc .exception .YdbConfigurationException ;
1013import tech .ydb .jdbc .query .YdbQueryOptions ;
14+ import tech .ydb .jdbc .settings .ParsedProperty ;
1115import tech .ydb .jdbc .settings .YdbClientProperties ;
16+ import tech .ydb .jdbc .settings .YdbClientProperty ;
1217import tech .ydb .jdbc .settings .YdbConnectionProperties ;
18+ import tech .ydb .jdbc .settings .YdbConnectionProperty ;
1319import tech .ydb .jdbc .settings .YdbOperationProperties ;
1420import tech .ydb .scheme .SchemeClient ;
1521import tech .ydb .table .TableClient ;
22+ import tech .ydb .table .impl .PooledTableClient ;
23+ import tech .ydb .table .rpc .grpc .GrpcTableRpc ;
1624
1725/**
1826 *
2230public class YdbContext implements AutoCloseable {
2331 private static final Logger LOGGER = Logger .getLogger (YdbContext .class .getName ());
2432
33+ private static final int SESSION_POOL_DEFAULT_MIN_SIZE = 0 ;
34+ private static final int SESSION_POOL_DEFAULT_MAX_SIZE = 50 ;
35+ private static final int SESSION_POOL_RESIZE_STEP = 50 ;
36+ private static final int SESSION_POOL_RESIZE_THRESHOLD = 10 ;
37+
2538 private final YdbConfig config ;
2639
2740 private final GrpcTransport grpcTransport ;
28- private final TableClient tableClient ;
41+ private final PooledTableClient tableClient ;
2942 private final SchemeClient schemeClient ;
30-
3143 private final YdbQueryOptions queryOptions ;
3244
33- private YdbContext (YdbConfig config , GrpcTransport grpcTransport , TableClient tableClient ) {
45+ private final boolean autoResizeSessionPool ;
46+ private final AtomicInteger connectionsCount = new AtomicInteger ();
47+
48+ private YdbContext (YdbConfig config , GrpcTransport transport , PooledTableClient tableClient , boolean autoResize ) {
3449 this .config = config ;
35- this .grpcTransport = Objects .requireNonNull (grpcTransport );
50+ this .grpcTransport = Objects .requireNonNull (transport );
3651 this .tableClient = Objects .requireNonNull (tableClient );
37- this .schemeClient = SchemeClient .newClient (grpcTransport ).build ();
52+ this .schemeClient = SchemeClient .newClient (transport ).build ();
3853 this .queryOptions = new YdbQueryOptions (config .getOperationProperties ());
54+ this .autoResizeSessionPool = autoResize ;
3955 }
4056
4157 public String getDatabase () {
@@ -58,6 +74,10 @@ public YdbQueryOptions getQueryOptions() {
5874 return queryOptions ;
5975 }
6076
77+ public int getConnectionsCount () {
78+ return connectionsCount .get ();
79+ }
80+
6181 public YdbOperationProperties getOperationProperties () {
6282 return config .getOperationProperties ();
6383 }
@@ -73,20 +93,90 @@ public void close() {
7393 }
7494 }
7595
96+ public void register () {
97+ int actual = connectionsCount .incrementAndGet ();
98+ int maxSize = tableClient .sessionPoolStats ().getMaxSize ();
99+ if (autoResizeSessionPool && actual > maxSize - SESSION_POOL_RESIZE_THRESHOLD ) {
100+ int newSize = maxSize + SESSION_POOL_RESIZE_STEP ;
101+ if (maxSize == tableClient .sessionPoolStats ().getMaxSize ()) {
102+ tableClient .updatePoolMaxSize (newSize );
103+ }
104+ }
105+ }
106+
107+ public void deregister () {
108+ int actual = connectionsCount .decrementAndGet ();
109+ int maxSize = tableClient .sessionPoolStats ().getMaxSize ();
110+ if (autoResizeSessionPool && maxSize > SESSION_POOL_RESIZE_STEP ) {
111+ if (actual < maxSize - SESSION_POOL_RESIZE_STEP - 2 * SESSION_POOL_RESIZE_THRESHOLD ) {
112+ int newSize = maxSize - SESSION_POOL_RESIZE_STEP ;
113+ if (maxSize == tableClient .sessionPoolStats ().getMaxSize ()) {
114+ tableClient .updatePoolMaxSize (newSize );
115+ }
116+ }
117+ }
118+ }
119+
76120 public static YdbContext createContext (YdbConfig config ) throws SQLException {
77121 try {
78122 YdbConnectionProperties connProps = config .getConnectionProperties ();
79123 YdbClientProperties clientProps = config .getClientProperties ();
80124
81125 LOGGER .log (Level .INFO , "Creating new YDB connection to {0}" , connProps .getConnectionString ());
82126
83- GrpcTransport grpcTransport = connProps .toGrpcTransport ();
84-
85- TableClient tableClient = clientProps .toTableClient (grpcTransport );
127+ GrpcTransport grpcTransport = buildGrpcTransport (connProps );
128+ PooledTableClient .Builder tableClient = PooledTableClient .newClient (
129+ GrpcTableRpc .useTransport (grpcTransport )
130+ );
131+ boolean autoResize = buildTableClient (tableClient , clientProps );
86132
87- return new YdbContext (config , grpcTransport , tableClient );
133+ return new YdbContext (config , grpcTransport , tableClient . build (), autoResize );
88134 } catch (Exception ex ) {
89135 throw new YdbConfigurationException ("Cannot connect to YDB" , ex );
90136 }
91137 }
138+
139+ public static GrpcTransport buildGrpcTransport (YdbConnectionProperties props ) {
140+ GrpcTransportBuilder builder = GrpcTransport .forConnectionString (props .getConnectionString ());
141+ for (Map .Entry <YdbConnectionProperty <?>, ParsedProperty > entry : props .getParams ().entrySet ()) {
142+ if (entry .getValue () != null ) {
143+ entry .getKey ().getSetter ().accept (builder , entry .getValue ().getParsedValue ());
144+ }
145+ }
146+
147+ if (props .hasStaticCredentials ()) {
148+ builder = builder .withAuthProvider (props .getStaticCredentials ());
149+ }
150+
151+ return builder .build ();
152+ }
153+
154+ private static boolean buildTableClient (TableClient .Builder builder , YdbClientProperties props ) {
155+ for (Map .Entry <YdbClientProperty <?>, ParsedProperty > entry : props .getParams ().entrySet ()) {
156+ if (entry .getValue () != null ) {
157+ entry .getKey ().getSetter ().accept (builder , entry .getValue ().getParsedValue ());
158+ }
159+ }
160+
161+ ParsedProperty minSizeConfig = props .getProperty (YdbClientProperty .SESSION_POOL_SIZE_MIN );
162+ ParsedProperty maxSizeConfig = props .getProperty (YdbClientProperty .SESSION_POOL_SIZE_MAX );
163+
164+ if (minSizeConfig == null && maxSizeConfig == null ) {
165+ return true ;
166+ }
167+
168+ int minSize = SESSION_POOL_DEFAULT_MIN_SIZE ;
169+ int maxSize = SESSION_POOL_DEFAULT_MAX_SIZE ;
170+
171+ if (minSizeConfig != null ) {
172+ minSize = Math .max (0 , minSizeConfig .getParsedValue ());
173+ maxSize = Math .max (maxSize , minSize );
174+ }
175+ if (maxSizeConfig != null ) {
176+ maxSize = Math .max (minSize + 1 , maxSizeConfig .getParsedValue ());
177+ }
178+
179+ builder .sessionPoolSize (minSize , maxSize );
180+ return false ;
181+ }
92182}
0 commit comments