Skip to content

Conversation

@daniel-sanche
Copy link
Contributor

@daniel-sanche daniel-sanche commented Feb 3, 2026

Proof of concept of the routing cookie feature. Grab routing cookie metadata from ffailed attempts, and pass it in with future attempts

TODO:

  • feature flags?
  • increment attempt counter?
  • keep cookie value between operations?
  • tests

@product-auto-label product-auto-label bot added size: s Pull request size is small. api: bigtable Issues related to the googleapis/python-bigtable API. labels Feb 3, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @daniel-sanche, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces foundational support for a routing cookie feature. It establishes a mechanism to capture routing cookie metadata from failed operation attempts and subsequently inject this information into future retry attempts. This aims to improve routing efficiency and consistency across retries by leveraging server-provided routing hints.

Highlights

  • Routing Cookie Data Model: Introduced a new routing_cookie field to the ActiveOperationMetric dataclass, allowing for the storage of routing cookie key-value pairs (strings or bytes) with a default empty dictionary.
  • Routing Cookie Extraction: Modified the tracked_retry.py module to extract x-goog-cbt-cookie headers from RPC error metadata (both trailing and initial) and store them in the operation.routing_cookie for subsequent retry attempts.
  • Routing Cookie Injection: Implemented logic in metrics_interceptor.py to iterate through the operation.routing_cookie and add each key-value pair as metadata to client_call_details before the continuation of unary-stream calls, ensuring routing cookies are propagated.
Changelog
  • google/cloud/bigtable/data/_async/metrics_interceptor.py
    • Added a loop to iterate through operation.routing_cookie and add each key-value pair to client_call_details.metadata before invoking the continuation.
  • google/cloud/bigtable/data/_metrics/data_model.py
    • Added routing_cookie: dict[str, str|bytes] = field(default_factory=dict) to the ActiveOperationMetric class to store routing cookie data.
  • google/cloud/bigtable/data/_metrics/tracked_retry.py
    • Refactored metadata processing to first create a dictionary from RPC error metadata.
    • Added logic to identify and extract headers starting with "x-goog-cbt-cookie" from the metadata dictionary and assign them to operation.routing_cookie.
Activity
  • This pull request is currently marked as a [DRAFT], indicating it's a work in progress or a proof of concept.
  • The author has outlined TODO items, specifically questioning whether to increment an attempt counter and if the cookie value should persist between operations, suggesting further design considerations or implementation details are pending.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

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 routing cookies as a proof-of-concept. The changes add a routing_cookie field to ActiveOperationMetric, extract cookie information from failed request metadata, and include it in subsequent requests.

My review has identified a couple of areas for improvement:

  • The implementation for adding the cookie to request metadata in metrics_interceptor.py is not compatible with the synchronous client and doesn't follow gRPC interceptor best practices. I've suggested a fix.
  • The logic for extracting the cookie from response metadata in tracked_retry.py could be refactored to avoid code duplication. I've recommended refactoring it into a shared helper function to improve maintainability and ensure consistency.

Comment on lines +133 to +134
for k,v in operation.routing_cookie.items():
client_call_details.metadata.add(k, v)
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The client_call_details object is immutable (it's a namedtuple). While metadata might be a mutable object in the async version, you should not modify it in place. The idiomatic way to add metadata in an interceptor is to create a new ClientCallDetails object with the updated metadata.

Furthermore, the add method does not exist on the metadata list in the synchronous version of the client, which will cause an AttributeError. The synchronous metadata is a list of tuples.

To fix this, you should create a copy of the metadata, append the new headers, and then create a new ClientCallDetails object using _replace. This new object will then be used in the continuation call.

Suggested change
for k,v in operation.routing_cookie.items():
client_call_details.metadata.add(k, v)
metadata = list(client_call_details.metadata or []) + list(operation.routing_cookie.items())
client_call_details = client_call_details._replace(metadata=metadata)

Comment on lines +61 to +66
metadata_dict = {k: v for k, v in metadata}
operation.add_response_metadata(metadata_dict)
# check for routing cookie:
cookie_headers = {k:v for k,v in metadata_dict.items() if k.startswith("x-goog-cbt-cookie")}
if cookie_headers:
operation.routing_cookie = cookie_headers
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This logic for processing metadata and extracting the routing cookie is also needed in _track_terminal_error. To avoid code duplication and ensure consistency, consider extracting this block into a helper function that can be called from both _track_retryable_error and _track_terminal_error.

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

Labels

api: bigtable Issues related to the googleapis/python-bigtable API. size: s Pull request size is small.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant