github.com/ydb-platform/ydb-go-sdk/v3@v3.89.2/internal/table/retry.go (about) 1 package table 2 3 import ( 4 "context" 5 6 "github.com/ydb-platform/ydb-go-sdk/v3/internal/closer" 7 "github.com/ydb-platform/ydb-go-sdk/v3/internal/pool" 8 "github.com/ydb-platform/ydb-go-sdk/v3/internal/table/config" 9 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xcontext" 10 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" 11 "github.com/ydb-platform/ydb-go-sdk/v3/retry" 12 "github.com/ydb-platform/ydb-go-sdk/v3/table" 13 "github.com/ydb-platform/ydb-go-sdk/v3/trace" 14 ) 15 16 // sessionPool is the interface that holds session lifecycle logic. 17 type sessionPool interface { 18 closer.Closer 19 20 Stats() pool.Stats 21 With(ctx context.Context, f func(ctx context.Context, s *session) error, opts ...retry.Option) error 22 } 23 24 func do( 25 ctx context.Context, 26 pool sessionPool, 27 config *config.Config, 28 op table.Operation, 29 onAttempt func(err error), 30 opts ...retry.Option, 31 ) (err error) { 32 return retryBackoff(ctx, pool, 33 func(ctx context.Context, s table.Session) (err error) { 34 defer func() { 35 if onAttempt != nil { 36 onAttempt(err) 37 } 38 }() 39 40 err = func() error { 41 if panicCallback := config.PanicCallback(); panicCallback != nil { 42 defer func() { 43 if e := recover(); e != nil { 44 panicCallback(e) 45 } 46 }() 47 } 48 49 return op(xcontext.MarkRetryCall(ctx), s) 50 }() 51 if err != nil { 52 return xerrors.WithStackTrace(err) 53 } 54 55 return nil 56 }, 57 opts..., 58 ) 59 } 60 61 func retryBackoff( 62 ctx context.Context, 63 pool sessionPool, 64 op table.Operation, 65 opts ...retry.Option, 66 ) error { 67 return pool.With(ctx, func(ctx context.Context, s *session) error { 68 if err := op(ctx, s); err != nil { 69 s.checkError(err) 70 71 return xerrors.WithStackTrace(err) 72 } 73 74 return nil 75 }, opts...) 76 } 77 78 func (c *Client) retryOptions(opts ...table.Option) *table.Options { 79 options := &table.Options{ 80 Trace: c.config.Trace(), 81 TxSettings: table.TxSettings( 82 table.WithSerializableReadWrite(), 83 ), 84 RetryOptions: []retry.Option{ 85 retry.WithTrace(c.config.TraceRetry()), 86 retry.WithBudget(c.config.RetryBudget()), 87 }, 88 } 89 for _, opt := range opts { 90 if opt != nil { 91 opt.ApplyTableOption(options) 92 } 93 } 94 if options.Trace == nil { 95 options.Trace = &trace.Table{} 96 } 97 98 return options 99 }