Skip to content

best practices in examples #2117

Open
asmyasnikov wants to merge 14 commits into
masterfrom
ctx-err
Open

best practices in examples #2117
asmyasnikov wants to merge 14 commits into
masterfrom
ctx-err

Conversation

@asmyasnikov

@asmyasnikov asmyasnikov commented May 5, 2026

Copy link
Copy Markdown
Member

Related ticket: https://nda.ya.ru/t/bsuUPpPR7bPRvr

Pull request type

Please check the type of change your PR introduces:

  • Bugfix
  • Feature
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • Documentation content changes
  • Other (please describe):

What is the current behavior?

Issue Number: N/A

What is the new behavior?

Other information

@codecov-commenter

codecov-commenter commented May 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.93%. Comparing base (9955e4c) to head (86a2f47).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2117      +/-   ##
==========================================
- Coverage   75.16%   74.93%   -0.23%     
==========================================
  Files         427      427              
  Lines       36974    36974              
==========================================
- Hits        27792    27708      -84     
- Misses       7993     8066      +73     
- Partials     1189     1200      +11     
Flag Coverage Δ
experiment 74.81% <ø> (-0.13%) ⬇️
go-1.21.x 72.42% <ø> (-0.24%) ⬇️
go-1.26.x 74.92% <ø> (-0.21%) ⬇️
integration 56.98% <ø> (-0.40%) ⬇️
macOS 46.19% <ø> (-0.03%) ⬇️
ubuntu 74.93% <ø> (-0.24%) ⬇️
unit 46.21% <ø> (-0.03%) ⬇️
windows 46.20% <ø> (-0.02%) ⬇️
ydb-24.4 56.48% <ø> (-0.47%) ⬇️
ydb-edge 56.78% <ø> (-0.39%) ⬇️
ydb-latest 56.69% <ø> (-0.38%) ⬇️
ydb-nightly 74.81% <ø> (-0.13%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

github-actions Bot commented May 5, 2026

Copy link
Copy Markdown

summary

Inferred base version: v3.135.11
Suggested version: v3.135.12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the pagination example to surface context cancellation/timeouts when a query produces no result set / rows, instead of silently treating it as end-of-data.

Changes:

  • Added an explicit ctx.Err() check in the “no more rows” branch of selectPaging().

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread examples/pagination/cities.go Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@asmyasnikov

Copy link
Copy Markdown
Member Author

@copilot find the same problems in other examples and fix

Copilot AI and others added 2 commits May 5, 2026 16:09
…rl_shortener, webserver)

Agent-Logs-Url: https://github.com/ydb-platform/ydb-go-sdk/sessions/7f8e6c7c-194a-4622-aead-567f90cfd21a

Co-authored-by: asmyasnikov <14202262+asmyasnikov@users.noreply.github.com>
…ies.go; update changelog

Agent-Logs-Url: https://github.com/ydb-platform/ydb-go-sdk/sessions/7f8e6c7c-194a-4622-aead-567f90cfd21a

Co-authored-by: asmyasnikov <14202262+asmyasnikov@users.noreply.github.com>

Copilot AI commented May 5, 2026

Copy link
Copy Markdown
Contributor

@copilot find the same problems in other examples and fix

Found and fixed the same context cancellation issue in three additional examples (commit cb32275):

  1. examples/ttl/series.go (deleteExpired): Used the same combined !NextResultSet(ctx) || !HasNextRow() pattern from cities.go — previously, empty=true was set before an ignored NextResultSet call, so context cancellation silently ended pagination.

  2. examples/serverless/url_shortener/service.go (selectLong): Added ctx.Err() and res.Err() checks before returning the "hash not found" error — previously, context cancellation caused a misleading "not found" error instead of surfacing the cancellation.

  3. examples/topic/cdc-cache-bus-freeseats/webserver.go (IndexPageHandler): Replaced ignored res.NextResultSet(ctx, "id") with res.NextResultSetErr(ctx, "id") and added res.Err() check at the end — previously, context cancellation was silently swallowed and the function returned nil.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • invalid_host
    • Triggering command: /tmp/go-build3582934768/b561/credentials.test /tmp/go-build3582934768/b561/credentials.test -test.paniconexit0 -test.count=1 -test.timeout=1m0s /tmp/go-build3582934768/b474/vet.cfg g_.a 4105633/b559/ ux_amd64/compile pkg/mod/github.c/opt/hostedtoolcache/go/1.24.13/x64/pkg/tool/linux_amd64/vet ttpcommon/httpco-atomic l/linux_amd64/co-bool fZkGkww0f4ei -o 1.78.0/internal/-errorsas upported.go ux_amd64/cgo -p iscovery/config =0 ux_amd64/cgo (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Comment thread CHANGELOG.md Outdated
Comment thread examples/pagination/cities.go Outdated
Comment thread examples/ttl/series.go Outdated
@asmyasnikov

Copy link
Copy Markdown
Member Author

@copilot migrate all examples from db,Table() usage to db.Query() usage

@asmyasnikov asmyasnikov changed the title Update cities.go best practices in examples May 6, 2026
Copilot AI and others added 2 commits May 6, 2026 15:20
Migrate the following example files from using db.Table() to db.Query():

- examples/ddl: executeQuery uses c.Exec() with ImplicitTxControl
- examples/pagination: createTable, fillTableWithData, selectPaging use query.Client
- examples/ttl/series.go: createTables, addDocument, readDocument, deleteExpired
  use query.Client; readExpiredBatchTransaction returns ClosableResultSet
- examples/decimal/main.go: use db.Query().Exec() for DDL and DoTx for read/write
- examples/serverless/url_shortener/service.go: createTable, insertShort, selectLong
- examples/serverless/healthcheck/service.go: createTableIfNotExists, upsertRows
- examples/topic/cdc-cache-bus-freeseats/database.go: DROP TABLE via Query.Exec
- examples/topic/cdc-fill-and-read/tables.go: dropTableIfExists, createTable,
  fillTable, removeFromTable use query.Client and query.TxActor
- examples/opensource_night2024/main.go: fillTableWeather uses Query.Exec with
  UPSERT INTO ... AS_TABLE instead of BulkUpsert

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Co-authored-by: asmyasnikov <14202262+asmyasnikov@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Co-authored-by: asmyasnikov <14202262+asmyasnikov@users.noreply.github.com>
Copilot AI and others added 2 commits May 6, 2026 15:28

Copilot AI commented May 6, 2026

Copy link
Copy Markdown
Contributor

@copilot migrate all examples from db,Table() usage to db.Query() usage

Done in commit f8a1f3a. All applicable examples have been migrated from db.Table() to db.Query():

  • examples/ddl/s.ExecuteSchemeQuery()c.Exec() with ImplicitTxControl()
  • examples/pagination/s.Execute()s.QueryResultSet(), s.CreateTable() → DDL SQL
  • examples/ttl/ — data/DDL ops migrated to Query API
  • examples/decimal/s.CreateTable() and s.Execute() migrated
  • examples/serverless/url_shortener/ — fully migrated
  • examples/serverless/healthcheck/ — fully migrated
  • examples/topic/cdc-cache-bus-freeseats/ — all DoTx calls migrated
  • examples/topic/cdc-fill-and-read/CreateTable/DropTable/ExecuteSchemeQuery migrated
  • examples/opensource_night2024/BulkUpsert replaced with db.Query().Exec() UPSERT

Examples kept as-is (use Table-specific APIs with no Query equivalent): basic/native/table, transaction/table, read_table, ttl_readtable, describe.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • invalid_host
    • Triggering command: /tmp/go-build718871106/b561/credentials.test /tmp/go-build718871106/b561/credentials.test -test.paniconexit0 -test.count=1 -test.timeout=2m0s /tmp/go-build718871106/b459/vet.cfg ck/main.go /libexec/gcc/x86_64-linux-gnu/13-c=4 p/bin/bash s-through=-lgcc base s-through=-lpthr-bool s-through=-lc s-th�� /config/config.g-errorsas /config/defaults-ifaceassert x64/pkg/tool/lin-nilfunc -go-sdk/internal/opt/hostedtoolcache/go/1.24.13/x64/pkg/tool/linux_amd64/vet -go-sdk/internal-atomic (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@robot-vibe-db robot-vibe-db Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Severity: Major
Confidence: Medium

In readExpiredBatchTransaction, the query.ClosableResultSet is created via s.QueryResultSet() inside a c.Do() closure (lines 54–68) and then returned to the caller (line 74). When the closure returns, the session is returned to the pool and may be reused or closed. Unlike the old table.Session.Execute() which fully materialized results in memory, the new query.Session.QueryResultSet() is backed by a streaming gRPC connection (streamResult) tied to the session.

The caller deleteExpired (line 115) then attempts to iterate rs.Rows(ctx) on a result set whose underlying session has already been released. This can lead to reading stale/invalid data or a closed-stream error.

The safe pattern (already used in readDocument at lines 172–222) is to consume the result set inside the c.Do() closure while the session is still held.

Suggested fix: move the row iteration into the c.Do() closure, or use c.QueryResultSet() at the client level (which manages the session internally).

@robot-vibe-db robot-vibe-db Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Review Summary

Verdict: ❌ 1 critical issue(s) found

Critical issues

  • Major | Medium: readExpiredBatchTransaction returns a streaming ClosableResultSet after its session has been returned to the pool — examples/ttl/series.go:53-74

Other findings

  • Minor | Medium: selectLong lost the explicit "hash not found" error; callers now see a raw query.ErrNoRows instead — examples/serverless/url_shortener/service.go:207-234
  • Minor | Medium: selectPaging scans into pointer types (*string, *uint32) for NOT NULL columns and dereferences without nil checks — examples/pagination/cities.go:77-91
  • Minor | Low: createTables lost WithUniformPartitions partitioning for the documents table; docTablePartitionCount is now dead code — examples/ttl/series.go:264-275
  • Nit | Low: Multiple CREATE TABLE statements changed column types from Optional (nullable) to non-nullable, which is a schema compatibility change for pre-existing tables

This review was generated automatically. Critical issues require attention; other findings are advisory.
If this comment was useful, please give it a 👍 — it helps us improve the review bot.

@robot-vibe-db

robot-vibe-db Bot commented May 6, 2026

Copy link
Copy Markdown

Severity: Major | Confidence: Medium
File: examples/ttl/series.go:53-74

readExpiredBatchTransaction captures rs (a query.ClosableResultSet) inside a c.Do() closure (lines 54-68) and returns it at line 74. When the closure returns, the session is released back to the pool and may be reused or closed.

Unlike the old table.Session.Execute() which fully materialized results in memory, query.Session.QueryResultSet() is backed by a streaming gRPC connection (streamResult). The caller deleteExpired (line 124) then iterates rs.Rows(ctx) on a result set whose underlying session stream may already be invalidated.

The correct pattern (already used in readDocument at lines 172-222) is to consume the result set inside the c.Do() closure while the session is still held.

Suggested fix: either move the row iteration into the c.Do() closure, or use c.QueryResultSet() at the client level which manages the session lifetime internally.

@robot-vibe-db

robot-vibe-db Bot commented May 6, 2026

Copy link
Copy Markdown

Severity: Minor | Confidence: Medium
File: examples/serverless/url_shortener/service.go:207-234

The old code returned a descriptive error fmt.Errorf("hash '%s' is not found", hash) when no rows matched. The new code propagates query.ErrNoRows from QueryRow, which carries the internal message "no rows in result set".

The caller handleLonger (line 362) does not distinguish "not found" from other errors and returns HTTP 500 with err.Error() as the response body. Users now see a database-internal error message instead of a meaningful "hash not found" message.

Suggested fix: check for errors.Is(err, query.ErrNoRows) and return the original descriptive error:

if errors.Is(err, query.ErrNoRows) {
    return "", fmt.Errorf("hash '%s' is not found", hash)
}

@robot-vibe-db

robot-vibe-db Bot commented May 6, 2026

Copy link
Copy Markdown

Severity: Minor | Confidence: Medium
File: examples/pagination/cities.go:77-91

city and number are scanned into pointer types (*string, *uint32) at lines 77-79 and dereferenced at lines 90-91 without nil checks. While the new schema defines these columns as NOT NULL (so nil values should not occur for freshly created tables), the old schema used types.Optional() (nullable columns).

If the table already exists from a previous run using the old nullable schema, or if the schema is changed in the future, these lines will panic on nil dereference.

Suggested fix: either use non-pointer types (var city string; var number uint32) since the columns are NOT NULL, or add nil guards before dereferencing.

@robot-vibe-db

robot-vibe-db Bot commented May 6, 2026

Copy link
Copy Markdown

Severity: Minor | Confidence: Low
File: examples/ttl/series.go:264-275

The old createTables used options.WithPartitions(options.WithUniformPartitions(uint64(docTablePartitionCount))) to create the documents table with uniform partitioning. The new SQL-based CREATE TABLE IF NOT EXISTS does not include any partitioning specification.

The docTablePartitionCount constant (line 15) is now unused dead code.

If the partitioning was intentional for performance, consider adding WITH (UNIFORM_PARTITIONS = 4) or similar to the CREATE TABLE statement, and removing the unused constant if not needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants