Skip to content

chore(spanner): clean up leader routing headers and fix commonHeaders_ mutation - #9317

Open
olavloite wants to merge 1 commit into
mainfrom
spanner-cleanup-lar-headers
Open

olavloite wants to merge 1 commit into
mainfrom
spanner-cleanup-lar-headers

Conversation

@olavloite

Copy link
Copy Markdown
Contributor
  • Precomputes 'x-goog-spanner-route-to-leader: true' once in Transaction and PartitionedDml constructors when routeToLeaderEnabled is true.
  • Removes redundant per-request header mutations and option checks across Snapshot and Transaction methods (begin, read, runStream, batchUpdate, commit, rollback).
  • Uses safe navigation in Snapshot.prototype._getSpanner to support lightweight sessions without full parent chains.
  • Fixes latent in-place mutation in Database.prototype.batchCreateSessions where database.commonHeaders_ was mutated, which caused subsequent read-only snapshots to inadvertently route to the leader.
  • Passes a shallow copy of commonHeaders_ in Transaction.prototype.rollback to protect against downstream in-place header modifications.

@olavloite
olavloite requested a review from a team as a code owner September 14, 2026 08:17
@product-auto-label product-auto-label Bot added the api: spanner Issues related to the Spanner API. label Sep 14, 2026

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request refactors how leader-aware routing headers are applied to Spanner requests. Instead of injecting these headers dynamically during individual operations (such as begin, read, query, commit, and rollback), they are now precomputed in the constructors of Transaction and PartitionedDml when routeToLeaderEnabled is active. Additionally, _getSpanner() has been updated to safely navigate the session hierarchy, and extensive unit tests have been added to verify header behavior. However, the reviewer identified a critical issue in both Transaction and PartitionedDml constructors: mutating this.commonHeaders_ directly will mutate the shared, pooled session.commonHeaders_ reference. This would cause subsequent read-only snapshots using the same session to incorrectly inherit the route-to-leader header. To resolve this, this.commonHeaders_ should be shallow-copied before applying the leader-aware routing header.

Comment thread handwritten/spanner/src/transaction.ts
Comment thread handwritten/spanner/src/transaction.ts
…_ mutation

- Precomputes 'x-goog-spanner-route-to-leader: true' once in Transaction and
  PartitionedDml constructors when routeToLeaderEnabled is true.
- Removes redundant per-request header mutations and option checks across
  Snapshot and Transaction methods (begin, read, runStream, batchUpdate, commit, rollback).
- Uses safe navigation in Snapshot.prototype._getSpanner to support lightweight
  sessions without full parent chains.
- Fixes latent in-place mutation in Database.prototype.batchCreateSessions where
  database.commonHeaders_ was mutated, which caused subsequent read-only snapshots
  to inadvertently route to the leader.
- Passes a shallow copy of commonHeaders_ in Transaction.prototype.rollback to protect
  against downstream in-place header modifications.
@olavloite
olavloite force-pushed the spanner-cleanup-lar-headers branch from b3fb625 to b1f43e9 Compare September 14, 2026 13:36
@olavloite

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request refactors how leader-aware routing headers are managed and applied to requests in the Spanner client. Instead of repeatedly adding the header on individual operations (which risked mutating shared commonHeaders_), the header is now precomputed and added to commonHeaders_ during the initialization of Transaction and PartitionedDml when routeToLeaderEnabled is true. For Database.batchCreateSessions, the header is safely added to the request-specific headers instead of mutating commonHeaders_. Additionally, optional chaining is introduced in _getSpanner() to safely retrieve the Spanner instance. Comprehensive unit tests have been added to verify these changes. There are no review comments, so I have no feedback to provide.

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

Labels

api: spanner Issues related to the Spanner API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant