Skip to content

feat(gax): add mutable extension accessors to RequestOptions - #6254

Merged
olavloite merged 2 commits into
googleapis:mainfrom
olavloite:gax-mutable-extension-accessors
Aug 17, 2026
Merged

feat(gax): add mutable extension accessors to RequestOptions#6254
olavloite merged 2 commits into
googleapis:mainfrom
olavloite:gax-mutable-extension-accessors

Conversation

@olavloite

Copy link
Copy Markdown
Contributor

Add get_extension_mut and get_extension_or_default_mut to the RequestOptionsExt trait and implement them for RequestOptions.

These methods allow client library layers to mutate request option extensions in place (such as injecting or updating headers in an existing HeaderMap) without needing to clone or re-insert the extension.

@olavloite
olavloite requested a review from a team as a code owner August 1, 2026 09:57

@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 bumps the version of google-cloud-gax to 1.14.0 and adds get_extension_mut and get_extension_or_default_mut methods to RequestOptions to support mutable extension retrieval. The review feedback correctly points out that the Clone trait bound on get_extension_or_default_mut is unnecessary because the default value is inserted directly by value, and removing it would make the API more flexible.

Comment thread src/gax/src/options.rs
Comment thread src/gax/src/options.rs
@codecov

codecov Bot commented Aug 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.17%. Comparing base (f1fdfa8) to head (c3e1d4a).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #6254   +/-   ##
=======================================
  Coverage   96.17%   96.17%           
=======================================
  Files         288      288           
  Lines       75433    75464   +31     
=======================================
+ Hits        72545    72580   +35     
+ Misses       2888     2884    -4     

☔ View full report in Codecov by Harness.
📢 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.

Add `get_extension_mut` and `get_extension_or_default_mut` to the
`RequestOptionsExt` trait and implement them for `RequestOptions`.

These methods allow client library layers to mutate request option
extensions in place (such as injecting or updating headers in an
existing `HeaderMap`) without needing to clone or re-insert the
extension.
@olavloite
olavloite force-pushed the gax-mutable-extension-accessors branch from 615ee69 to 01be876 Compare August 1, 2026 10:19
@olavloite
olavloite requested a review from a team as a code owner August 1, 2026 10:19
@coryan coryan added the api: spanner Issues related to the Spanner API. label Aug 7, 2026

@coryan coryan 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.

I think you intended this as an example:

These methods allow client library layers to mutate request option extensions in place (such as injecting or updating headers in an existing HeaderMap) without needing to clone or re-insert the extension.

I must ask, if this is the only use-case you had in mind, would the changes in #6260 satisfy your needs? I would like to avoid two different ways to set headers.

If you had other cases in mind, then this looks good.

@olavloite

Copy link
Copy Markdown
Contributor Author

@coryan Thanks for taking a look at this.

I think you intended this as an example:

These methods allow client library layers to mutate request option extensions in place (such as injecting or updating headers in an existing HeaderMap) without needing to clone or re-insert the extension.

No, this was actually for a specific use case that we have in Spanner. And it serves a different purpose than #6260. #6260 is to give external users access to adding headers. This is to allow our clients to directly mutate extensions (that again can contain headers) without the need to clone them. The Spanner client includes at least one header with every request (x-goog-request-id), and that currently leads to a clone of the current headers on every request:

  1. Every RPC execution in Spanner receives an owned options: RequestOptions (which may already hold user-configured headers like RPC priority or request tags).
  2. Inside the client dispatch pipeline, we must attach the x-goog-spanner-request-id header.
  3. Because RequestOptions only has get_extension::<T>(&self) -> Option<&T> and insert_extension<T>(self, value: T) -> Self, we are forced to clone the full HeaderMap on every call:

Current code:

// Current code in Spanner client:
let mut headers = options
    .get_extension::<HeaderMap>()
    .cloned() // <-- clones the entire map of existing headers
    .unwrap_or_default();
headers.insert(REQUEST_ID_HEADER.clone(), val);
options.insert_extension(headers)

However, with this PR, we can change the above code to this:

// With this PR:
options
    .get_extension_or_default_mut::<HeaderMap>()
    .insert(REQUEST_ID_HEADER.clone(), val);

@olavloite
olavloite merged commit 2662072 into googleapis:main Aug 17, 2026
42 checks passed
@github-actions github-actions Bot mentioned this pull request Aug 17, 2026
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.

3 participants