@@ -19,7 +19,6 @@ import (
1919 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsync"
2020 "github.com/ydb-platform/ydb-go-sdk/v3/retry"
2121 "github.com/ydb-platform/ydb-go-sdk/v3/table"
22- "github.com/ydb-platform/ydb-go-sdk/v3/table/options"
2322 "github.com/ydb-platform/ydb-go-sdk/v3/testutil/timeutil"
2423 "github.com/ydb-platform/ydb-go-sdk/v3/trace"
2524)
@@ -32,7 +31,7 @@ type sessionBuilder func(ctx context.Context, opts ...sessionBuilderOption) (*se
3231type balancerNotifier interface {
3332 grpc.ClientConnInterface
3433
35- OnDiscovery (onDiscovery func (ctx context.Context , endpoints []endpoint.Info ))
34+ OnUpdate (onDiscovery func (ctx context.Context , endpoints []endpoint.Info ))
3635}
3736
3837func New (balancer balancerNotifier , config config.Config ) * Client {
@@ -55,6 +54,7 @@ func newClient(
5554 cc : balancer ,
5655 build : builder ,
5756 index : make (map [* session ]sessionInfo ),
57+ nodes : make (map [uint32 ]map [* session ]struct {}),
5858 idle : list .New (),
5959 waitq : list .New (),
6060 limit : config .SizeLimit (),
@@ -67,7 +67,7 @@ func newClient(
6767 done : make (chan struct {}),
6868 }
6969 if balancer != nil {
70- balancer .OnDiscovery (c .onDiscovery )
70+ balancer .OnUpdate (c .updateNodes )
7171 }
7272 if idleThreshold := config .IdleThreshold (); idleThreshold > 0 {
7373 c .spawnedGoroutines .Add (1 )
@@ -88,6 +88,7 @@ type Client struct {
8888 // read-write fields
8989 mu xsync.Mutex
9090 index map [* session ]sessionInfo
91+ nodes map [uint32 ]map [* session ]struct {}
9192 createInProgress int // KIKIMR-9163: in-create-process counter
9293 limit int // Upper bound for Client size.
9394 idle * list.List // list<*session>
@@ -118,7 +119,7 @@ func withCreateSessionOnClose(onClose func(s *session)) createSessionOption {
118119 }
119120}
120121
121- func (c * Client ) onDiscovery (ctx context.Context , endpoints []endpoint.Info ) {
122+ func (c * Client ) updateNodes (ctx context.Context , endpoints []endpoint.Info ) {
122123 nodeIDs := make ([]uint32 , len (endpoints ))
123124 for i , e := range endpoints {
124125 nodeIDs [i ] = e .NodeID ()
@@ -127,26 +128,17 @@ func (c *Client) onDiscovery(ctx context.Context, endpoints []endpoint.Info) {
127128 return nodeIDs [i ] < nodeIDs [j ]
128129 })
129130 c .mu .WithLock (func () {
130- touched := make (map [* session ]struct {}, len (c .index ))
131- for e := c .idle .Front (); e != nil ; e = e .Next () {
132- s := e .Value .(* session )
133- nodeID := s .NodeID ()
131+ for nodeID := range c .nodes {
134132 if sort .Search (len (nodeIDs ), func (i int ) bool {
135133 return nodeIDs [i ] >= nodeID
136134 }) == len (nodeIDs ) {
137- c .internalPoolAsyncCloseSession (ctx , s )
138- }
139- touched [s ] = struct {}{}
140- }
141- for s := range c .index {
142- if _ , has := touched [s ]; has {
143- continue
144- }
145- nodeID := s .NodeID ()
146- if sort .Search (len (nodeIDs ), func (i int ) bool {
147- return nodeIDs [i ] >= nodeID
148- }) == len (nodeIDs ) {
149- s .SetStatus (options .SessionClosing )
135+ for s := range c .nodes [nodeID ] {
136+ if info , has := c .index [s ]; has && info .idle != nil {
137+ c .internalPoolAsyncCloseSession (ctx , s )
138+ } else {
139+ s .SetStatus (table .SessionClosing )
140+ }
141+ }
150142 }
151143 }
152144 })
@@ -256,13 +248,51 @@ func (c *Client) createSession(ctx context.Context, opts ...createSessionOption)
256248 }
257249}
258250
251+ func (c * Client ) appendSessionToNodes (s * session ) {
252+ c .mu .WithLock (func () {
253+ nodeID := s .NodeID ()
254+ sessions , has := c .nodes [nodeID ]
255+ if ! has {
256+ sessions = make (map [* session ]struct {})
257+ }
258+ sessions [s ] = struct {}{}
259+ c .nodes [nodeID ] = sessions
260+ })
261+ }
262+
263+ func (c * Client ) removeSessionFromNodes (s * session ) {
264+ c .mu .WithLock (func () {
265+ nodeID := s .NodeID ()
266+ sessions , has := c .nodes [nodeID ]
267+ if ! has {
268+ sessions = make (map [* session ]struct {})
269+ }
270+ delete (sessions , s )
271+ if len (sessions ) == 0 {
272+ delete (c .nodes , nodeID )
273+ } else {
274+ c .nodes [nodeID ] = sessions
275+ }
276+ })
277+ }
278+
259279func (c * Client ) CreateSession (ctx context.Context , opts ... table.Option ) (_ table.ClosableSession , err error ) {
260280 if c == nil {
261281 return nil , xerrors .WithStackTrace (errNilClient )
262282 }
263283 var s * session
284+ createSession := func (ctx context.Context ) (* session , error ) {
285+ s , err = c .createSession (ctx ,
286+ withCreateSessionOnCreate (c .appendSessionToNodes ),
287+ withCreateSessionOnClose (c .removeSessionFromNodes ),
288+ )
289+ if err != nil {
290+ return nil , xerrors .WithStackTrace (err )
291+ }
292+ return s , nil
293+ }
264294 if ! c .config .AutoRetry () {
265- s , err = c . createSession (ctx )
295+ s , err = createSession (ctx )
266296 if err != nil {
267297 return nil , xerrors .WithStackTrace (err )
268298 }
@@ -272,7 +302,7 @@ func (c *Client) CreateSession(ctx context.Context, opts ...table.Option) (_ tab
272302 err = retry .Retry (
273303 ctx ,
274304 func (ctx context.Context ) (err error ) {
275- s , err = c . createSession (ctx )
305+ s , err = createSession (ctx )
276306 if err != nil {
277307 return xerrors .WithStackTrace (err )
278308 }
@@ -328,40 +358,45 @@ func (c *Client) internalPoolCreateSession(ctx context.Context) (s *session, err
328358 })
329359 }()
330360
331- s , err = c .createSession (meta .WithAllowFeatures (ctx ,
332- meta .HintSessionBalancer ,
333- ), withCreateSessionOnCreate (func (s * session ) {
334- c .mu .WithLock (func () {
335- c .index [s ] = sessionInfo {
336- touched : timeutil .Now (),
337- }
338- trace .TableOnPoolSessionAdd (c .config .Trace (), s )
339- trace .TableOnPoolStateChange (c .config .Trace (), len (c .index ), "append" )
340- })
341- }), withCreateSessionOnClose (func (s * session ) {
342- c .mu .WithLock (func () {
343- info , has := c .index [s ]
344- if ! has {
345- panic ("session not found in pool" )
346- }
361+ s , err = c .createSession (
362+ meta .WithAllowFeatures (ctx ,
363+ meta .HintSessionBalancer ,
364+ ),
365+ withCreateSessionOnCreate (c .appendSessionToNodes ),
366+ withCreateSessionOnClose (c .removeSessionFromNodes ),
367+ withCreateSessionOnCreate (func (s * session ) {
368+ c .mu .WithLock (func () {
369+ c .index [s ] = sessionInfo {
370+ touched : timeutil .Now (),
371+ }
372+ trace .TableOnPoolSessionAdd (c .config .Trace (), s )
373+ trace .TableOnPoolStateChange (c .config .Trace (), len (c .index ), "append" )
374+ })
375+ }), withCreateSessionOnClose (func (s * session ) {
376+ c .mu .WithLock (func () {
377+ info , has := c .index [s ]
378+ if ! has {
379+ panic ("session not found in pool" )
380+ }
347381
348- delete (c .index , s )
382+ delete (c .index , s )
349383
350- trace .TableOnPoolSessionRemove (c .config .Trace (), s )
351- trace .TableOnPoolStateChange (c .config .Trace (), len (c .index ), "remove" )
384+ trace .TableOnPoolSessionRemove (c .config .Trace (), s )
385+ trace .TableOnPoolStateChange (c .config .Trace (), len (c .index ), "remove" )
352386
353- if ! c .isClosed () {
354- c .internalPoolNotify (nil )
355- }
387+ if ! c .isClosed () {
388+ c .internalPoolNotify (nil )
389+ }
356390
357- if info .idle != nil {
358- c .idle .Remove (info .idle )
359- }
360- })
361- }))
391+ if info .idle != nil {
392+ c .idle .Remove (info .idle )
393+ }
394+ })
395+ }))
362396 if err != nil {
363397 return nil , xerrors .WithStackTrace (err )
364398 }
399+
365400 return s , nil
366401}
367402
@@ -596,7 +631,7 @@ func (c *Client) Close(ctx context.Context) (err error) {
596631 for e := c .idle .Front (); e != nil ; e = e .Next () {
597632 wg .Add (1 )
598633 s := e .Value .(* session )
599- s .SetStatus (options .SessionClosing )
634+ s .SetStatus (table .SessionClosing )
600635 go func () {
601636 defer wg .Done ()
602637 c .internalPoolSyncCloseSession (ctx , s )
@@ -770,7 +805,7 @@ func (c *Client) internalPoolNotify(s *session) (notified bool) {
770805}
771806
772807func (c * Client ) internalPoolAsyncCloseSession (ctx context.Context , s * session ) {
773- s .SetStatus (options .SessionClosing )
808+ s .SetStatus (table .SessionClosing )
774809 c .spawnedGoroutines .Add (1 )
775810 go func () {
776811 defer c .spawnedGoroutines .Done ()
0 commit comments