Skip to content

feat(spanner): add client-level CallContextConfigurator to SpannerOptions - #14256

Merged
rahul2393 merged 4 commits into
mainfrom
spanner-client-call-context-config
Sep 4, 2026
Merged

feat(spanner): add client-level CallContextConfigurator to SpannerOptions#14256
rahul2393 merged 4 commits into
mainfrom
spanner-client-call-context-config

Conversation

@olavloite

Copy link
Copy Markdown
Contributor

Adds support for configuring a client-wide CallContextConfigurator via SpannerOptions.Builder#setCallContextConfigurator.

This allows applications (such as async and reactive pipelines where operations span across multiple executor threads) to customize gRPC options, timeouts, and headers across all RPCs without relying on thread-local io.grpc.Context propagation.

Key changes:

  • SpannerOptions: Added setCallContextConfigurator/getCallContextConfigurator. SpannerCallContextTimeoutConfigurator now derives from the supplied context rather than creating a blank default context.
  • GapicSpannerRpc:
    • Evaluates client-level configurator first, followed by thread-local configurator (allowing per-call overrides).
    • Reliably detects derived vs standalone delta contexts using an internal CallOptions.Key marker, preventing extra header duplication while preserving custom CallOptions and internal Spanner routing state.
    • Wraps configurator execution exceptions in SpannerException.
    • Fixed streaming reads in GapicSpannerRpc to pass getStreamingReadMethod() instead of getReadMethod().

…ions

Adds support for configuring a client-wide CallContextConfigurator via
SpannerOptions.Builder#setCallContextConfigurator.

This allows applications (such as async and reactive pipelines where
operations span across multiple executor threads) to customize gRPC
options, timeouts, and headers across all RPCs without relying on
thread-local io.grpc.Context propagation.

Key changes:
- SpannerOptions: Added setCallContextConfigurator/getCallContextConfigurator.
  SpannerCallContextTimeoutConfigurator now derives from the supplied
  context rather than creating a blank default context.
- GapicSpannerRpc:
  - Evaluates client-level configurator first, followed by thread-local
    configurator (allowing per-call overrides).
  - Reliably detects derived vs standalone delta contexts using an internal
    CallOptions.Key marker, preventing extra header duplication while
    preserving custom CallOptions and internal Spanner routing state.
  - Wraps configurator execution exceptions in SpannerException.
  - Fixed streaming reads in GapicSpannerRpc to pass getStreamingReadMethod()
    instead of getReadMethod().
@olavloite
olavloite requested review from a team as code owners September 3, 2026 16:49

@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 introduces support for configuring a client-level CallContextConfigurator in SpannerOptions, allowing users to apply custom gRPC options, timeouts, or credentials client-wide without relying solely on thread-local context propagation. The changes sequentially evaluate client-level and thread-level configurators, merging their options appropriately, and include comprehensive unit tests to verify these behaviors. Feedback on the implementation points out a critical issue where call credentials from a CallCredentialsProvider could be silently wiped out during a merge if a custom configurator returns a standalone delta context with custom CallOptions. A code suggestion is provided to preserve the base credentials in this scenario.

@olavloite

Copy link
Copy Markdown
Contributor Author

/gemini review

@olavloite
olavloite requested a review from rahul2393 September 3, 2026 16:58

@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 introduces support for configuring a client-level CallContextConfigurator in SpannerOptions, allowing users to apply custom gRPC options, timeouts, or credentials client-wide across all RPCs. It updates GapicSpannerRpc to sequentially evaluate both client-level and thread-local configurators, ensuring proper merging of contexts, options, and headers. Additionally, comprehensive unit tests have been added to verify these behaviors. As there are no review comments provided, I have no feedback to evaluate.

@rahul2393
rahul2393 merged commit eef74d2 into main Sep 4, 2026
206 checks passed
@rahul2393
rahul2393 deleted the spanner-client-call-context-config branch September 4, 2026 07:42
lqiu96 pushed a commit that referenced this pull request Sep 4, 2026
🤖 I have created a release *beep* *boop*
---


<details><summary>1.91.0</summary>

##
[1.91.0](v1.90.0...v1.91.0)
(2026-09-04)


### ⚠ BREAKING CHANGES

* **datalabeling:** remove java-datalabeling library
([#14189](#14189))
* **datacatalog:** remove java-datacatalog library
([#14178](#14178))

### Features

* **apptopology:** onboard a new library
([#14204](#14204))
([f871a07](f871a07))
* **bigtable:** Option to disable direct access fallback
([#14193](#14193))
([5b6a974](5b6a974))
* **datacatalog:** remove java-datacatalog library
([#14178](#14178))
([2910f63](2910f63))
* **datalabeling:** remove java-datalabeling library
([#14189](#14189))
([334d35a](334d35a)),
refs
[#14176](#14176)
* **gax:** add getSingleHeader to HttpHeadersUtils
([#14137](#14137))
([f114422](f114422))
* **gax:** add ResumableUploadClient.startUpload() and supporting types
([#14138](#14138))
([d7e2be2](d7e2be2))
* **gax:** add ResumableUploadResponseParser
([#14135](#14135))
([e1a0b17](e1a0b17))
* **gax:** allow non-JSON HttpContent and absolute request URLs in
HttpRequestRunnable
([#14134](#14134))
([ac4a49a](ac4a49a))
* **gax:** implement queryStatusCallable for resumable uploads
([#14155](#14155))
([67719c0](67719c0))
* **gax:** implement startUploadCallable for resumable uploads
([#14139](#14139))
([4e65b6c](4e65b6c))
* **gax:** implement uploadChunkCallable for resumable uploads
([#14140](#14140))
([1c643de](1c643de))
* **google/shopping/merchant/loyaltycustomers/v1:** onboard new library
([#14257](#14257))
([590a51c](590a51c))
* **grpc-gcp:** drain scaled-down channels
([#14216](#14216))
([bbbd18c](bbbd18c))
* **grpc-gcp:** move scale-up to background worker
([#14206](#14206))
([41f0a2e](41f0a2e))
* **grpc-gcp:** penalize retryable channel errors
([#14219](#14219))
([829872e](829872e))
* **grpc-gcp:** prime scaled channels before publish
([#14232](#14232))
([dd75645](dd75645))
* **spanner:** add client-level CallContextConfigurator to
SpannerOptions
([#14256](#14256))
([eef74d2](eef74d2))
* **spanner:** prime scaled-up dynamic channel pool channels with SELECT
1
([#14254](#14254))
([4d26645](4d26645))


### Bug Fixes

* **auth:** refine JSpecify nullability annotations for external account
credentials
([#14164](#14164))
([385e1f2](385e1f2))
* **bigquery-jdbc:** resolve `statementType` via `getJob` fallback to
avoid post-execution dry run for DDL
([#14265](#14265))
([d38d9f0](d38d9f0))
* **bigtable:** truncate client generated timestamps on the emulator c…
([#14234](#14234))
([94e680f](94e680f))
* **gax:** propagate structured LRO error details to ApiException
([#14022](#14022))
([865a15b](865a15b))
* **grpc-gcp:** correct channel lifecycle bookkeeping
([#14196](#14196))
([3df32ba](3df32ba))
* **grpc-gcp:** prevent hot-channel skew
([#14198](#14198))
([07a7505](07a7505))
* **java-sql:** temp fix for lint and skip generate
([#14005](#14005))
([b6f73db](b6f73db))
* **spanner:** prioritize leader replica for read-write transactions in
location-aware routing
([#14195](#14195))
([6383f81](6383f81))
* **spanner:** route ExecuteBatchDml through transaction affinity
endpoint
([#14192](#14192))
([5e9e3cd](5e9e3cd))
* **storage:** resolve GraalVM Native Image test failure for
java-storage
([#14226](#14226))
([93e0920](93e0920))


### Performance Improvements

* **bigquery-jdbc:** eliminate sync getJob RPC call
([#14197](#14197))
([ccf12b0](ccf12b0))
* **ci:** replace mvn help:evaluate with native bash and sed extraction
([#14218](#14218))
([744a522](744a522))


### Dependencies

* Upgrade grpc-java to 1.83.0
([#13967](#13967))
([0cdc695](0cdc695))
</details>

---
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants