Skip to content

feat(storage): refactor the async code to accomodate JSON and GRPC implementation.#1747

Open
googlyrahman wants to merge 4 commits intogoogleapis:asyncfrom
googlyrahman:feb8
Open

feat(storage): refactor the async code to accomodate JSON and GRPC implementation.#1747
googlyrahman wants to merge 4 commits intogoogleapis:asyncfrom
googlyrahman:feb8

Conversation

@googlyrahman
Copy link

  • Removed private methods from AsyncClient and BaseClient: To support using the same asynchronous client for both HTTP and gRPC, we removed several private methods. These methods required HTTP-specific arguments (such as method) that are not applicable to gRPC interactions, making them unnecessary for the unified async client implementation.

  • Refactored AsyncConnection: Split the AsyncConnection (was HTTP based) class into an AsyncConnection (Abstract Base Class) and an AsyncJSONConnection (Implementation) to allow for more flexible protocol support.

@product-auto-label product-auto-label bot added size: l Pull request size is large. api: storage Issues related to the googleapis/python-storage API. labels Feb 8, 2026
@googlyrahman googlyrahman changed the title Refactor the async code to accomodate JSON and GRPC implementation. feat(storage): refactor the async code to accomodate JSON and GRPC implementation. Feb 8, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @googlyrahman, 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 a significant architectural refactoring to the asynchronous client and connection layers. The primary goal is to establish a flexible foundation that can seamlessly accommodate both JSON-based HTTP and gRPC communication protocols. By abstracting the connection logic and specializing the JSON implementation, the system is now better positioned for future expansion and protocol diversity, enhancing modularity and maintainability.

Highlights

  • Abstract Base Class for Async Connections: A new abstract base class, AsyncConnection, has been introduced to provide a common interface for asynchronous connections, designed to be compatible with both JSON (HTTP) and gRPC implementations.
  • Refactored AsyncClient: The AsyncClient has been refactored to remove HTTP-specific private methods and now manages separate internal connections for JSON and gRPC, allowing for a unified client that can handle different protocols.
  • Dedicated AsyncJSONConnection: The original AsyncConnection class has been renamed to AsyncJSONConnection and now serves as a concrete implementation of the new AsyncConnection abstract base class, specifically handling JSON-based HTTP requests.
  • Streamlined BaseClient: Several abstract resource-handling methods have been removed from BaseClient, delegating their implementation details to protocol-specific connection classes.
Changelog
  • google/cloud/storage/_experimental/asyncio/abstracts/async_connection.py
    • Added new file: AsyncConnection abstract base class for generic async connections.
    • Includes common properties like extra_headers and user_agent.
    • Defines an abstract close method for connection management.
  • google/cloud/storage/_experimental/asyncio/async_client.py
    • Removed _AIO_AVAILABLE check and associated ImportError logic.
    • Replaced direct _connection attribute with _json_connection_internal and _grpc_connection_internal properties.
    • Removed HTTP-specific private resource methods (_get_resource, _list_resource, _patch_resource, _put_resource, _post_resource, _delete_resource).
    • Updated close method to close both JSON and gRPC connections if they exist.
  • google/cloud/storage/_experimental/asyncio/async_connection.py
    • File renamed to google/cloud/storage/_experimental/asyncio/utility/async_json_connection.py.
  • google/cloud/storage/_experimental/asyncio/utility/async_json_connection.py
    • New file created from renamed async_connection.py.
    • Class renamed to AsyncJSONConnection and now inherits from abstracts.AsyncConnection.
    • Moved _AIO_AVAILABLE check and AsyncSession import into __init__.
    • The async_http property and close method are now specific to AsyncJSONConnection.
    • Removed client_info, user_agent, and extra_headers properties, as they are handled by the base AsyncConnection class.
  • google/cloud/storage/abstracts/base_client.py
    • Removed abstract methods for _get_resource, _list_resource, _patch_resource, _put_resource, _post_resource, and _delete_resource.
  • tests/unit/asyncio/test_async_client.py
    • Removed imports for AsyncHTTPIterator and _marker.
    • Updated mocks from AsyncConnection to AsyncJSONConnection.
    • Removed tests related to _async_http_internal, _async_http_passed_by_user, async_http property, and the previously removed resource methods.
    • Adjusted test_ctor_w_async_http_passed to reflect AsyncJSONConnection instantiation.
  • tests/unit/asyncio/test_async_connection.py
    • File renamed to tests/unit/asyncio/test_async_json_connection.py.
  • tests/unit/asyncio/test_async_json_connection.py
    • New file created from renamed test_async_connection.py.
    • Updated imports to use AsyncJSONConnection and AsyncConnection abstract base class.
    • Modified fixtures to instantiate AsyncJSONConnection and removed mock_client fixture.
    • Added tests for AsyncJSONConnection's async_http property and close method.
    • Adjusted existing tests to align with AsyncJSONConnection changes (e.g., removed mock_client argument from test functions).
Activity
  • The pull request introduces new files for abstracting asynchronous connection logic.
  • Existing client and connection implementations have been modified to conform to the new architectural design.
  • Test files have been updated and renamed to reflect the refactoring and ensure continued functionality.
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 is a solid architectural refactoring that separates connection logic from the async client, preparing for both JSON and gRPC support. My review has identified a critical issue in the new AsyncClient.close() method, which violates a repository rule regarding resource cleanup and would cause it to fail. Additionally, there are a couple of medium-severity suggestions for code cleanup and improving test coverage.

@googlyrahman googlyrahman force-pushed the feb8 branch 2 times, most recently from ed21dee to 0e9a775 Compare February 8, 2026 10:40
@product-auto-label product-auto-label bot added size: xl Pull request size is extra large. and removed size: l Pull request size is large. labels Feb 8, 2026
@googlyrahman googlyrahman force-pushed the feb8 branch 2 times, most recently from 5c6297f to b8d1a13 Compare February 8, 2026 11:30
@googlyrahman
Copy link
Author

/gemini review

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

The pull request refactors the asynchronous storage client to support both JSON and gRPC protocols by introducing an abstract AsyncConnection base class and a protocol-specific AsyncJSONConnection. Overall, the refactoring improves modularity and aligns the async implementation with the library's multi-protocol goals. I have identified a few issues regarding consistency with the existing synchronous implementation, specifically around user agent string construction and a minor typo in a copyright header.

Comment on lines +40 to +45
if self._client_info.user_agent is None:
self._client_info.user_agent = AGENT_VERSION
else:
self._client_info.user_agent = (
f"{self._client_info.user_agent} {AGENT_VERSION}"
)
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The user agent string construction should be kept consistent with the existing JSON client implementation in google/cloud/storage/_http.py. The current implementation is missing the leading and trailing spaces around the AGENT_VERSION string, which are present in the synchronous implementation to ensure proper formatting when concatenated with other identifiers.

        if self._client_info.user_agent is None:
            self._client_info.user_agent = ""
        if AGENT_VERSION not in self._client_info.user_agent:
            self._client_info.user_agent += f" {AGENT_VERSION} "
References
  1. The user agent string construction, including extra spaces, should be kept consistent with the existing JSON client implementation.

@googlyrahman googlyrahman added kokoro:run Add this label to force Kokoro to re-run the tests. kokoro:force-run Add this label to force Kokoro to re-run the tests. labels Feb 10, 2026
@yoshi-kokoro yoshi-kokoro removed kokoro:run Add this label to force Kokoro to re-run the tests. kokoro:force-run Add this label to force Kokoro to re-run the tests. labels Feb 10, 2026
@googlyrahman googlyrahman added kokoro:run Add this label to force Kokoro to re-run the tests. kokoro:force-run Add this label to force Kokoro to re-run the tests. labels Feb 11, 2026
@yoshi-kokoro yoshi-kokoro removed kokoro:run Add this label to force Kokoro to re-run the tests. kokoro:force-run Add this label to force Kokoro to re-run the tests. labels Feb 11, 2026
chore: remove python 3.9 support. 

Details in b/483015736
@googlyrahman googlyrahman marked this pull request as ready for review February 12, 2026 06:32
@googlyrahman googlyrahman requested review from a team as code owners February 12, 2026 06:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api: storage Issues related to the googleapis/python-storage API. size: xl Pull request size is extra large.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants