Repository navigation
feat(bigtable): add protoRowToRow conversion helper for TableShim - #20257
Merged
sushanb merged 1 commit intoJul 29, 2026
Merged
Conversation
Adds an unexported protoRowToRow(*btpb.Row) Row helper in table_shim.go
plus 13-case TestProtoRowToRow that pins the wire-shape → Row-map
conversion contract.
Staged for the follow-up change that swaps TableShim.session for a
proto-native session backend whose SessionReadRowResponse carries a
*btpb.Row rather than the already-converted bigtable.Row. Keeping the
converter + its tests in a separate patch means the follow-up
introduces exactly one new call site — the conversion itself is
already reviewed and pinned.
Contract pinned by the test cases:
- nil / empty Families / family-with-no-columns / column-with-no-cells
all return nil, matching classic Table.ReadRow's row-not-found
signal (callers check `row == nil`).
- Cell order within a column, column order within a family, and
family-append semantics when the same family name appears twice in
Families are all preserved as wire order.
- Labels, empty qualifier ("cf:"), TimestampMicros=0, and
empty-Value ([]byte{}) all pass through unchanged.
No behavior change: protoRowToRow has no caller in this patch. Test
coverage exercises every branch.
Contributor
There was a problem hiding this comment.
Code Review
This pull request introduces the protoRowToRow helper function in bigtable/table_shim.go to convert proto-native Row objects into the classic bigtable.Row map format, along with comprehensive unit tests in bigtable/table_shim_test.go. The feedback suggests an optimization to append directly to the target map slice in protoRowToRow instead of allocating an intermediate slice, which reduces unnecessary allocations and improves performance.
mutianf
approved these changes
Jul 29, 2026
4 tasks done
sushanb
added a commit
that referenced
this pull request
Jul 29, 2026
…20258) ## Summary Follow-up to #20257 (protoRowToRow), which now has its sole consumer. Swaps `TableShim`'s session backend from the classic `TableAPI` shape (row string + `bigtable.Row`) to the internal `session.TableAPI` shape (proto-native `*btpb.SessionReadRow{Request,Response}` + `*btpb.SessionMutateRow{Request,Response}`). `TableShim` now owns the proto ↔ public-types translation so the `internal/session` package can stay proto-native. ## Behavior **`ReadRow`** — parses `ReadOption` using the classic `makeReadSettings` shape (so filter + full-read-stats callback plumbing stays in one place), builds a `*btpb.SessionReadRowRequest`, calls `session.ReadRow`, feeds any `resp.Stats` through the `WithFullReadStats` callback, and converts `resp.Row` via `protoRowToRow`. **`Apply`** — conditional mutations (`CheckAndMutateRow`) always route to classic since the session vRPC has no `CheckAndMutateRow` equivalent. Non-conditional mutations build a `*btpb.SessionMutateRowRequest` and call `session.MutateRow`. **`useSession()`** — nil-safe on both `session` and `diverter`, so callers can wire a `TableShim` with `nil` session (as `buildDivertible` does in #20256) and every routing decision falls through to classic. **`ReadRows` / `SampleRowKeys` / `ApplyBulk` / `ApplyReadModifyWrite` always classic** — no session equivalent in the vRPC. ## API-visible signature change `NewTableShim`'s `session` parameter type becomes `session.TableAPI` (an internal-package interface). Existing in-repo callers pass `nil` for session today; nil is the zero value of any interface, so the change is source-compatible for those. External callers writing tests can mock `session.TableAPI` directly — the new test file has an example (`mockSessionTable`). ## Tests Replaces the `mockTableAPI`-as-session pattern with a proto-native `mockSessionTable`. New coverage: - `TestTableShim_ReadRow_RoutesByDiverter` — classic when `SessionLoad=0.0`; session when `SessionLoad=1.0`; classic fallback when session is nil even with `SessionLoad=1.0`; session error propagation (no automatic fallback to classic on failure). - `TestTableShim_Apply_ConditionalAlwaysClassic` — pins that conditional mutations bypass the session path. - `TestTableShim_Apply_NonConditionalRoutesByDiverter` — pins that non-conditional mutations follow the diverter. - `TestTableShim_ReadRows_AlwaysClassic`, `TestTableShim_SampleRowKeys_AlwaysClassic`, `TestTableShim_ApplyBulk_AlwaysClassic`, `TestTableShim_ApplyReadModifyWrite_AlwaysClassic` — pin the no-session-equivalent methods. - `TestTableShim_NilSession_AllMethodsFallBackToClassic` — the classic-only wiring path (what #20256's `buildDivertible` will use until the session backend lands). - `TestTableShim_SessionErrorNotRetriedOnClassic` — session-side failures surface as-is instead of silently falling back. ## Test plan - [x] `go build ./...` clean - [x] `go vet ./...` clean - [x] `go test ./bigtable/ -run 'TestTableShim|TestProtoRowToRow' -count=1 -v` — all pass - [x] Live sandbox smoke against `autonomous-mote-782 / sushanb-uc1` — classic path via `client.Open(...).Apply/ReadRow` still succeeds end-to-end (session backend not exercised on this branch since it isn't wired yet) ## Depends on - #20257 (merged as `1297143a4f`) — `protoRowToRow` helper. ## Follows Consumed by a future PR that wires an actual `session.TableAPI` implementation from the `internal/session` package into `Client.buildDivertible` (see #20256 for the `buildDivertible` shape).
sushanb
added a commit
to sushanb/google-cloud-go
that referenced
this pull request
Jul 29, 2026
Folds PR googleapis#20258 into this PR. TableShim's session backend changes from the classic-shaped TableAPI (row string + bigtable.Row) to the internal/session.TableAPI shape (proto-native *btpb.SessionReadRow{Request,Response} + *btpb.SessionMutateRow {Request,Response}). TableShim owns the proto ↔ public-types translation so the session package can stay proto-native. - ReadRow: parses ReadOptions via classic makeReadSettings/readSettings so every existing option (RowFilter, WithFullReadStats, etc.) works on the session path; then translates (row, filter) → SessionReadRowRequest, calls session.ReadRow, feeds resp.Stats through WithFullReadStats, and converts resp.Row via protoRowToRow (added in googleapis#20257, now on main). - Apply: nil mutations and conditional mutations (CheckAndMutateRow) route to classic — CheckAndMutateRow has no session vRPC equivalent, and nil-m to classic surfaces the classic client's existing nil-handling error rather than panicking on m.ops here. - useSession() helper is nil-safe on both session and diverter (replaces the earlier pickSession); callers can wire a TableShim with nil session and every routing decision falls through to classic. Signature change (internal-only): NewTableShim's session parameter type is now session.TableAPI (an internal package). In-repo callers pass nil for session today; nil is the zero value of any interface, so the change is source-compatible for those. Tests: replaces the mockTableAPI-as-session pattern with a proto-native mockSessionTable. Covers routing, nil-session fallback, session error propagation, conditional-always-classic, and the already-existing TestProtoRowToRow contract. Closes PR googleapis#20258 (the standalone version); folded here so PR googleapis#20256's review scope is one coherent unit — Diverter wiring + TableShim proto-native shape together.
sushanb
pushed a commit
that referenced
this pull request
Aug 3, 2026
🤖 I have created a release *beep* *boop* --- ## [1.52.0](bigtable/v1.51.0...bigtable/v1.52.0) (2026-08-03) ### Features * **bigtable:** Add AFE picker (Simple / LeastInFlight / LeastLatency) ([#20204](#20204)) ([bcbf714](bcbf714)) * **bigtable:** Add ClientConfig.DisableSession to opt out of session backend ([#20297](#20297)) ([7ee5e44](7ee5e44)) * **bigtable:** Add getClientConfigDirectAccessChecker for session pools ([#20209](#20209)) ([3b8d30a](3b8d30a)) * **bigtable:** Add NoOpChannelPrimer for session channel pools ([#20208](#20208)) ([d055a8a](d055a8a)) * **bigtable:** Add per-AFE sessionList for the two-tier session pool ([#20224](#20224)) ([dbf0c3f](dbf0c3f)) * **bigtable:** Add protoRowToRow conversion helper for TableShim ([#20257](#20257)) ([1297143](1297143)) * **bigtable:** Add Session debug surface (observability fields + methods) ([#20211](#20211)) ([d8d3e16](d8d3e16)) * **bigtable:** Add Session lifecycle (Start, Close, ForceClose, readLoop, heartBeatLoop) ([#20215](#20215)) ([b9e53c6](b9e53c6)) * **bigtable:** Add Session struct + state machine ([#20117](#20117)) ([09acbb3](09acbb3)) * **bigtable:** Add session.Config.EnableDebug to gate sessionz debug state ([#20247](#20247)) ([ce74c31](ce74c31)) * **bigtable:** Add SessionClient + SessionTable + lazyPool ([#20228](#20228)) ([ab2c96c](ab2c96c)) * **bigtable:** Add SessionPoolImpl (two-tier pool + scaling + debug) ([#20225](#20225)) ([683eda8](683eda8)) * **bigtable:** Rename session pool display to <resource-id>-<PERM> ([#20248](#20248)) ([35e146e](35e146e)) * **bigtable:** Route Client.Open()-returned *Table through the Diverter ([#20273](#20273)) ([2b81c7d](2b81c7d)) * **bigtable:** State-based classification for abnormal session close ([#20243](#20243)) ([f2905b7](f2905b7)) * **bigtable:** TableShim fallback to classic on session UNIMPLEMENTED ([#20269](#20269)) ([36540af](36540af)) * **bigtable:** TTL-on-idle cache for per-resource session.TableAPI ([#20263](#20263)) ([00b2a49](00b2a49)) * **bigtable:** Wire Diverter on Client and route Open* via TableShim ([#20256](#20256)) ([b32fbd7](b32fbd7)) ### Bug Fixes * **bigtable:** AFE picker latency signal — subtract poolWait and compute TransportLatency = wire − backend at source ([#20281](#20281)) ([bb8c4d5](bb8c4d5)) * **bigtable:** Guard NewStream OnFinish against grpc-go double-fire ([#20295](#20295)) ([b51da29](b51da29)) * **bigtable:** Real per-resource pool teardown on sessionTable.Close + cache close-race gate ([#20264](#20264)) ([599aea9](599aea9)) * **bigtable:** Session.durations / session.uptime — set explicit histogram bucket boundaries ([#20276](#20276)) ([97eee22](97eee22)) * **bigtable:** SessionTableHandle self-heals across cache eviction ([#20296](#20296)) ([0dd98cd](0dd98cd)) * **bigtable:** Translate ctx errors to gRPC status on session vRPC ([#20299](#20299)) ([0f3b2a5](0f3b2a5)) * **bigtable:** Treat PingAndWarm NotFound as a successful prime ([#20219](#20219)) ([a1557ad](a1557ad)) ### Performance Improvements * **bigtable:** Delete periodic Tick loop; sizing is event-driven ([#20285](#20285)) ([2c096bd](2c096bd)) * **bigtable:** Drop pick_lost_race debug tag from CheckoutSession hot path ([#20280](#20280)) ([bd0e400](bd0e400)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an unexported
protoRowToRow(*btpb.Row) Rowhelper totable_shim.goplus a 13-caseTestProtoRowToRowthat pins thewire-shape →
Row-map conversion contract.Staged for the follow-up change that swaps
TableShim.sessionfor aproto-native session backend whose
SessionReadRowResponsecarries a*btpb.Rowrather than the already-convertedbigtable.Row. Keepingthe converter + its tests in a separate patch means the follow-up
introduces exactly one new call site — the conversion itself is already
reviewed and pinned by tests.
Contract pinned by the test cases
FamiliesRowFamiliesReadItemTimestampMicros = 0Value([]byte{})The nil-on-empty behavior matches classic
Table.ReadRow's row-not-foundsignal — callers rely on
row == nilfor the not-found check, soreturning an empty-but-non-nil
Rowwould be a subtle contract break.Files
bigtable/table_shim.go—protoRowToRowhelper (+49 LOC, unused in this patch)bigtable/table_shim_test.go—TestProtoRowToRow(+115 LOC, 13 subtests)Test plan
go build ./...cleango vet ./...cleango test ./bigtable/ -run 'TestProtoRowToRow|TestTableShim' -count=1 -v— 13/13 subtests pass