Skip to content

Commit 8cb1931

Browse files
authored
Merge pull request #1458 from ydb-platform/fix-tx
* Added option `ydb.WithSessionPoolSessionIdleTimeToLive` for restric…
2 parents 200688b + d26f929 commit 8cb1931

24 files changed

+748
-301
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
* Added option `ydb.WithSessionPoolSessionIdleTimeToLive` for restrict idle time of query sessions
2+
* Fixed bug with leak of query transactions
13
* Changed `ydb_go_sdk_ydb_driver_conn_requests` metrics splitted to `ydb_go_sdk_ydb_driver_conn_request_statuses` and `ydb_go_sdk_ydb_driver_conn_request_methods`
24
* Fixed metadata for operation service connection
35
* Fixed composing query traces in call `db.Query.Do[Tx]` using option `query.WithTrace`

internal/pool/pool.go

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,18 @@ type (
2626
Item
2727
}
2828
Config[PT ItemConstraint[T], T any] struct {
29-
trace *Trace
30-
clock clockwork.Clock
31-
limit int
32-
createTimeout time.Duration
33-
createItem func(ctx context.Context) (PT, error)
34-
closeTimeout time.Duration
35-
closeItem func(ctx context.Context, item PT)
36-
idleThreshold time.Duration
29+
trace *Trace
30+
clock clockwork.Clock
31+
limit int
32+
createTimeout time.Duration
33+
createItem func(ctx context.Context) (PT, error)
34+
closeTimeout time.Duration
35+
closeItem func(ctx context.Context, item PT)
36+
idleTimeToLive time.Duration
3737
}
3838
itemInfo[PT ItemConstraint[T], T any] struct {
39-
idle *xlist.Element[PT]
40-
touched time.Time
39+
idle *xlist.Element[PT]
40+
lastUsage time.Time
4141
}
4242
waitChPool[PT ItemConstraint[T], T any] interface {
4343
GetOrNew() *chan PT
@@ -99,9 +99,9 @@ func WithTrace[PT ItemConstraint[T], T any](t *Trace) Option[PT, T] {
9999
}
100100
}
101101

102-
func WithIdleThreshold[PT ItemConstraint[T], T any](idleThreshold time.Duration) Option[PT, T] {
102+
func WithIdleTimeToLive[PT ItemConstraint[T], T any](idleTTL time.Duration) Option[PT, T] {
103103
return func(c *Config[PT, T]) {
104-
c.idleThreshold = idleThreshold
104+
c.idleTimeToLive = idleTTL
105105
}
106106
}
107107

@@ -218,7 +218,7 @@ func makeAsyncCreateItemFunc[PT ItemConstraint[T], T any]( //nolint:funlen
218218
if newItem != nil {
219219
p.mu.WithLock(func() {
220220
p.index[newItem] = itemInfo[PT, T]{
221-
touched: p.config.clock.Now(),
221+
lastUsage: p.config.clock.Now(),
222222
}
223223
})
224224
}
@@ -461,7 +461,7 @@ func (p *Pool[PT, T]) peekFirstIdle() (item PT, touched time.Time) {
461461
panic(fmt.Sprintf("inconsistent index: (%v, %+v, %+v)", has, el, info.idle))
462462
}
463463

464-
return item, info.touched
464+
return item, info.lastUsage
465465
}
466466

467467
// removes first session from idle and resets the keepAliveCount
@@ -547,7 +547,7 @@ func (p *Pool[PT, T]) pushIdle(item PT, now time.Time) {
547547
}
548548

549549
p.changeState(func() Stats {
550-
info.touched = now
550+
info.lastUsage = now
551551
info.idle = p.idle.PushBack(item)
552552
p.index[item] = info
553553

@@ -595,7 +595,7 @@ func (p *Pool[PT, T]) getItem(ctx context.Context) (item PT, finalErr error) { /
595595
return info
596596
})
597597

598-
if p.config.idleThreshold > 0 && p.config.clock.Since(info.touched) > p.config.idleThreshold {
598+
if p.config.idleTimeToLive > 0 && p.config.clock.Since(info.lastUsage) > p.config.idleTimeToLive {
599599
p.closeItem(ctx, item)
600600
p.mu.WithLock(func() {
601601
p.changeState(func() Stats {

internal/pool/pool_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -394,22 +394,22 @@ func TestPool(t *testing.T) {
394394
// replace default async closer for sync testing
395395
WithSyncCloseItem[*testItem, testItem](),
396396
WithClock[*testItem, testItem](fakeClock),
397-
WithIdleThreshold[*testItem, testItem](idleThreshold),
397+
WithIdleTimeToLive[*testItem, testItem](idleThreshold),
398398
WithTrace[*testItem, testItem](defaultTrace),
399399
)
400400

401401
s1 := mustGetItem(t, p)
402402
s2 := mustGetItem(t, p)
403403

404404
// Put both items at the absolutely same time.
405-
// That is, both items must be updated their touched timestamp.
405+
// That is, both items must be updated their lastUsage timestamp.
406406
mustPutItem(t, p, s1)
407407
mustPutItem(t, p, s2)
408408

409409
require.Len(t, p.index, 2)
410410
require.Equal(t, 2, p.idle.Len())
411411

412-
// Move clock to longer than idleThreshold
412+
// Move clock to longer than idleTimeToLive
413413
fakeClock.Advance(idleThreshold + time.Nanosecond)
414414

415415
// on get item from idle list the pool must check the item idle timestamp
@@ -423,15 +423,15 @@ func TestPool(t *testing.T) {
423423
t.Fatal("unexpected number of closed items")
424424
}
425425

426-
// Move time to idleThreshold / 2 - this emulate a "spent" some time working within item.
426+
// Move time to idleTimeToLive / 2 - this emulate a "spent" some time working within item.
427427
fakeClock.Advance(idleThreshold / 2)
428428

429429
// Now put that item back
430-
// pool must update a touched timestamp of item
430+
// pool must update a lastUsage timestamp of item
431431
mustPutItem(t, p, s3)
432432

433-
// Move time to idleThreshold / 2
434-
// Total time since last updating touched timestampe is more than idleThreshold
433+
// Move time to idleTimeToLive / 2
434+
// Total time since last updating lastUsage timestampe is more than idleTimeToLive
435435
fakeClock.Advance(idleThreshold/2 + time.Nanosecond)
436436

437437
require.Len(t, p.index, 1)

internal/query/client.go

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,7 @@ func do(
205205

206206
err := op(ctx, s)
207207
if err != nil {
208-
if xerrors.IsOperationError(err) {
209-
s.SetStatus(session.StatusClosed)
210-
}
208+
s.SetStatus(session.StatusError)
211209

212210
return xerrors.WithStackTrace(err)
213211
}
@@ -263,27 +261,27 @@ func doTx(
263261
txSettings tx.Settings,
264262
opts ...retry.Option,
265263
) (finalErr error) {
266-
err := do(ctx, pool, func(ctx context.Context, s *Session) (err error) {
264+
err := do(ctx, pool, func(ctx context.Context, s *Session) (opErr error) {
267265
tx, err := s.Begin(ctx, txSettings)
268266
if err != nil {
269267
return xerrors.WithStackTrace(err)
270268
}
271-
err = op(ctx, tx)
272-
if err != nil {
273-
errRollback := tx.Rollback(ctx)
274-
if errRollback != nil {
275-
return xerrors.WithStackTrace(xerrors.Join(err, errRollback))
269+
270+
defer func() {
271+
_ = tx.Rollback(ctx)
272+
273+
if opErr != nil {
274+
s.SetStatus(session.StatusError)
276275
}
276+
}()
277277

278+
err = op(ctx, tx)
279+
if err != nil {
278280
return xerrors.WithStackTrace(err)
279281
}
282+
280283
err = tx.CommitTx(ctx)
281284
if err != nil {
282-
errRollback := tx.Rollback(ctx)
283-
if errRollback != nil {
284-
return xerrors.WithStackTrace(xerrors.Join(err, errRollback))
285-
}
286-
287285
return xerrors.WithStackTrace(err)
288286
}
289287

@@ -338,12 +336,12 @@ func (c *Client) QueryRow(ctx context.Context, q string, opts ...options.Execute
338336
func clientExec(ctx context.Context, pool sessionPool, q string, opts ...options.Execute) (finalErr error) {
339337
settings := options.ExecuteSettings(opts...)
340338
err := do(ctx, pool, func(ctx context.Context, s *Session) (err error) {
341-
_, r, err := execute(ctx, s.ID(), s.client, q, settings, withTrace(s.trace))
339+
streamResult, err := execute(ctx, s.ID(), s.client, q, settings, withTrace(s.trace))
342340
if err != nil {
343341
return xerrors.WithStackTrace(err)
344342
}
345343

346-
err = readAll(ctx, r)
344+
err = readAll(ctx, streamResult)
347345
if err != nil {
348346
return xerrors.WithStackTrace(err)
349347
}
@@ -382,7 +380,7 @@ func clientQuery(ctx context.Context, pool sessionPool, q string, opts ...option
382380
) {
383381
settings := options.ExecuteSettings(opts...)
384382
err = do(ctx, pool, func(ctx context.Context, s *Session) (err error) {
385-
_, streamResult, err := execute(ctx, s.ID(), s.client, q,
383+
streamResult, err := execute(ctx, s.ID(), s.client, q,
386384
options.ExecuteSettings(opts...), withTrace(s.trace),
387385
)
388386
if err != nil {
@@ -434,12 +432,12 @@ func clientQueryResultSet(
434432
ctx context.Context, pool sessionPool, q string, settings executeSettings, resultOpts ...resultOption,
435433
) (rs result.ClosableResultSet, finalErr error) {
436434
err := do(ctx, pool, func(ctx context.Context, s *Session) error {
437-
_, r, err := execute(ctx, s.ID(), s.client, q, settings, resultOpts...)
435+
streamResult, err := execute(ctx, s.ID(), s.client, q, settings, resultOpts...)
438436
if err != nil {
439437
return xerrors.WithStackTrace(err)
440438
}
441439

442-
rs, err = readMaterializedResultSet(ctx, r)
440+
rs, err = readMaterializedResultSet(ctx, streamResult)
443441
if err != nil {
444442
return xerrors.WithStackTrace(err)
445443
}
@@ -530,6 +528,7 @@ func New(ctx context.Context, cc grpc.ClientConnInterface, cfg *config.Config) *
530528
pool.WithTrace[*Session, Session](poolTrace(cfg.Trace())),
531529
pool.WithCreateItemTimeout[*Session, Session](cfg.SessionCreateTimeout()),
532530
pool.WithCloseItemTimeout[*Session, Session](cfg.SessionDeleteTimeout()),
531+
pool.WithIdleTimeToLive[*Session, Session](cfg.SessionIdleTimeToLive()),
533532
pool.WithCreateItemFunc(func(ctx context.Context) (_ *Session, err error) {
534533
var (
535534
createCtx context.Context

0 commit comments

Comments
 (0)