Article contains some cases for migrate from
github.com/yandex-cloud/ydb-go-sdk/v2
togithub.com/ydb-platform/ydb-go-sdk/v3
- Imports
- Connect to
YDB
byendpoint
anddatabase
- Connect to
YDB
using connection string - Make table client and session pool
- Execute query with table client and session pool
- About truncated result
- Scan query result into local variables
- Logging SDK's events
- Add metrics about SDK's events
- Add
Jaeger
traces about SDK's events
- in
v2
:"github.com/yandex-cloud/ydb-go-sdk/v2" "github.com/yandex-cloud/ydb-go-sdk/v2/table"
- in
v3
:"github.com/ydb-platform/ydb-go-sdk/v3" "github.com/ydb-platform/ydb-go-sdk/v3/table"
- in
v2
:config := &ydb.DriverConfig{ Database: cfg.Database, } driver, err := (&ydb.Dialer{ DriverConfig: config, }).Dial(ctx, cfg.Addr) if err != nil { // error fallback } defer func() { _ = driver.Close() }()
- in
v3
:import ( "github.com/ydb-platform/ydb-go-sdk/v3/sugar" ) ... db, err := ydb.Open(ctx, sugar.DSN(cfg.Endpoint, cfg.Database, sugar.WithSecure(cfg.Secure)) ) if err != nil { // error fallback } defer func() { _ = db.Close(ctx) }()
- in
v2
:import ( "github.com/yandex-cloud/ydb-go-sdk/v2/connect" ) ... params, err := connect.ConnectionString("grpc://ydb-ru.yandex.net:2135/?database=/ru/home/my/db") if err != nil { // error fallback } ... config.Database = params.Database() ... driver, err := (&ydb.Dialer{ DriverConfig: config, }).Dial(ctx, params.Endpoint())
- in
v3
:db, err := ydb.Open(ctx, "grpc://ydb-ru.yandex.net:2135/ru/home/my/db", ) if err != nil { // error fallback } defer func() { _ = db.Close(ctx) }()
- in
v2
:import ( "github.com/yandex-cloud/ydb-go-sdk/v2/table" ) ... tableClient := &table.Client{ Driver: driver, } sp := &table.SessionPool{ Builder: tableClient, } defer func() { _ = sp.Close(ctx) }()
- in
v3
: nothing to do, table client with internal session pool always available withdb.Table()
- in
v2
:var res *table.Result err := table.Retry(ctx, sp, table.OperationFunc( func(ctx context.Context, s *table.Session) (err error) { _, res, err = s.Execute(ctx, readTx, "SELECT 1+1") return err }, ) ) if err != nil { // error fallback }
- in
v3
:import ( "github.com/ydb-platform/ydb-go-sdk/v3/table/result" ) ... var res result.Result err := db.Table().Do(ctx, func(ctx context.Context, s table.Session) (err error) { _, res, err = s.Execute(ctx, readTx, "SELECT 1+1") return err }, table.WithIdempotent(), // only idempotent queries ) if err != nil { // error fallback }
Call of session.Execute
may return a result with a flag Truncated
because YDB
have a default limit of rows is a 1000.
In this case query must be changed for supporting pagination. Truncated flag in result must be checks explicitly.
- in
v2
:var res *table.Result err := table.Retry(ctx, sp, table.OperationFunc( func(ctx context.Context, s *table.Session) (err error) { _, res, err = s.Execute(ctx, readTx, "SELECT 1+1") if err != nil { // error fallback } for res.NextStreamSet(ctx) { for res.NextRow() { // process column values } } if err := res.Err(); err != nil { // error fallback } if res.Trucated() { // alarm to query developers } return nil }, ), } if err != nil { // error fallback }
- in
v3
: By default, truncated result wraps as non-retryable error forsession.Execute
and retryable error forsession.StreamExecuteScanQuery
But if default behaviour are not allowed, wrapping truncated result as error may be disabled with optionimport ( "github.com/ydb-platform/ydb-go-sdk/v3/table/result" ) ... var res result.Result err := db.Table().Do(ctx, func(ctx context.Context, s table.Session) (err error) { _, res, err = s.Execute(ctx, readTx, "SELECT 1+1") if err != nil { // error fallback } for res.NextStreamSet(ctx) { for res.NextRow() { // process column values } } // no need to check truncated result explicitly // if res.Truncated() { // // alarm to query developers // } return res.Err() }, table.WithIdempotent(), // only idempotent queries ) if err != nil { // error fallback }
ydb.WithIgnoreTruncated
- in
v2
:var ( id uint64 title string date uint64 description string duration uint64 ) for res.NextStreamSet(ctx) { for res.NextRow() { res.SeekItem("series_id") id = res.OUint64() res.SeekItem("title") title = res.OUTF8() res.SeekItem("release_date") date = res.OUint64() res.SeekItem("description") description = res.OUTF8() res.SeekItem("duration") duration = res.OUint64() log.Printf("# %d %s %s %s %v", id, title, time.UnixMilli(date).Format("02/01/2006, 15:04:05"), description, time.Duration(duration) * time.Millisecond, ) } } if err := res.Err(); err != nil { // error fallback }
- in
v3
:import ( "github.com/ydb-platform/ydb-go-sdk/v3/table/result/named" ) ... var ( id uint64 title *string date *time.Time description *string duration time.Duration ) for res.NextResultSet(ctx) { for res.NextRow() { err := res.ScanNamed( named.Required("series_id", &id), named.Optional("title", &title), named.Optional("release_date", &date), named.Optional("description", &description), named.OptionalWithDefault("duration", &duration), ) if err != nil { // error fallback } log.Printf("# %d %s %s %s %v", id, title, date.Format("02/01/2006, 15:04:05"), description, duration, ) } } if err := res.Err(); err != nil { // error fallback }
- in
v2
:config.Trace = ydb.DriverTrace{ OnDial: func(info ydb.DialStartInfo) func(info ydb.DialDoneInfo) { address := info.Address fmt.Printf(`dial start {address:"%s"}`, address) start := time.Now() return func(info ydb.DialDoneInfo) { if info.Error == nil { fmt.Printf(`dial done {latency:"%s",address:"%s"}`, time.Since(start), address) } else { fmt.Printf(`dial failed {latency:"%s",address:"%s",error:"%s"}`, time.Since(start), address, info.Error) } } }, // ... and more callbacks of ydb.DriverTrace need to define } sp.Trace = table.Trace{ // must callbacks of table.Trace }
- in
v3
:ydb-go-sdk/v3
contains internal logger, which may to enable with envYDB_LOG_SEVERITY_LEVEL=info
- external
zap
logger:import ydbZap "github.com/ydb-platform/ydb-go-sdk-zap" ... db, err := ydb.Open(ctx, connectionString, ... ydbZap.WithTraces(log, trace.DetailsAll), )
- external
zerolog
logger:import ydbZerolog "github.com/ydb-platform/ydb-go-sdk-zerolog" ... db, err := ydb.Open(ctx, connectionString, ... ydbZerolog.WithTraces(log, trace.DetailsAll), )
- in
v2
:config.Trace = ydb.DriverTrace{ // must define callbacks of ydb.DriverTrace } sp.Trace = table.Trace{ // must define callbacks of table.Trace }
- in
v3
:- metrics into
Prometheus
systemimport ( ydbMetrics "github.com/ydb-platform/ydb-go-sdk-prometheus" ) ... registry := prometheus.NewRegistry() db, err := ydb.Open(ctx, connectionString, ... ydbMetrics.WithTraces(registry, ydbMetrics.WithDetails(trace.DetailsAll)), )
- metrics to other monitoring systems may be add with common package
"github.com/ydb-platform/ydb-go-sdk-metrics"
- metrics into
- in
v2
:config.Trace = ydb.DriverTrace{ // must define callbacks of ydb.DriverTrace } sp.Trace = table.Trace{ // must define callbacks of table.Trace }
- in
v3
:import ( ydbTracing "github.com/ydb-platform/ydb-go-sdk-opentracing" ) ... db, err := ydb.Open(ctx, connectionString, ... ydbTracing.WithTraces(trace.DriverConnEvents | trace.DriverClusterEvents | trace.DriverRepeaterEvents | trace.DiscoveryEvents), )
See additional docs in code recipes.