fix: update write handle on every recv() by chandra-siri · Pull Request #1716 · googleapis/python-storage · GitHub
Skip to content
This repository was archived by the owner on Mar 31, 2026. It is now read-only.

fix: update write handle on every recv()#1716

Merged
chandra-siri merged 9 commits into
mainfrom
update_handle_on_recv
Jan 22, 2026
Merged

fix: update write handle on every recv()#1716
chandra-siri merged 9 commits into
mainfrom
update_handle_on_recv

Conversation

@chandra-siri

@chandra-siri chandra-siri commented Jan 21, 2026

Copy link
Copy Markdown
Collaborator

fix: update write_handle on every recv() from write object stream.

@chandra-siri chandra-siri requested review from a team January 21, 2026 18:37
@chandra-siri chandra-siri requested a review from a team as a code owner January 21, 2026 18:37
@product-auto-label product-auto-label Bot added size: xl Pull request size is extra large. api: storage Issues related to the googleapis/python-storage API. labels Jan 21, 2026
@gemini-code-assist

Copy link
Copy Markdown
Contributor

@chandra-siri chandra-siri changed the base branch from main to update_handle_type January 21, 2026 18:37

@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 a fix to update the write_handle on every recv() call, ensuring the most current handle is used. This is achieved by adding a new utility function and applying it across different stream operations. The changes also include updating type hints for handles from bytes to their specific proto types, which improves code clarity and correctness. Additionally, there's a significant and valuable refactoring of the system tests to use session-scoped event loops and gRPC clients, which should improve test performance and stability. I've identified one critical bug in async_write_object_stream.py where an AttributeError could occur when opening a stream with an existing write_handle. A code suggestion to fix this is provided.

I am having trouble creating individual review comments. Click here to see my feedback.

google/cloud/storage/_experimental/asyncio/async_write_object_stream.py (153-181)

critical

When opening a stream with is_open_via_write_handle=True, response.resource is not guaranteed to be populated. Accessing response.resource.generation will raise an AttributeError. The generation number is already known in this case, so it should only be updated from the response when a new stream is created without a handle.

self.generation_number = response.resource.generation should be moved inside the else block that handles the case where is_open_via_write_handle is false.

        if is_open_via_write_handle:
            # Don't use if not response.persisted_size because this will be true
            # if persisted_size==0 (0 is considered "Falsy" in Python)
            if response.persisted_size is None:
                raise ValueError(
                    "Failed to obtain persisted_size after opening the stream via write_handle"
                )
            self.persisted_size = response.persisted_size
        else:
            if not response.resource:
                raise ValueError(
                    "Failed to obtain object resource after opening the stream"
                )
            if not response.resource.generation:
                raise ValueError(
                    "Failed to obtain object generation after opening the stream"
                )
            if not response.resource.size:
                # Appending to a 0 byte appendable object.
                self.persisted_size = 0
            else:
                self.persisted_size = response.resource.size
            self.generation_number = response.resource.generation

        if not response.write_handle:
            raise ValueError("Failed to obtain write_handle after opening the stream")

        self.write_handle = response.write_handle

Base automatically changed from update_handle_type to main January 22, 2026 07:30
suni72
suni72 previously approved these changes Jan 22, 2026
@chandra-siri chandra-siri dismissed suni72’s stale review January 22, 2026 07:49

The merge-base changed after approval.

@product-auto-label product-auto-label Bot added size: m Pull request size is medium. and removed size: xl Pull request size is extra large. labels Jan 22, 2026
@chandra-siri chandra-siri enabled auto-merge (squash) January 22, 2026 07:52
@chandra-siri chandra-siri requested a review from suni72 January 22, 2026 08:29
@chandra-siri chandra-siri merged commit 5d9fafe into main Jan 22, 2026
18 checks passed
@chandra-siri chandra-siri deleted the update_handle_on_recv branch January 22, 2026 09:26
chandra-siri added a commit that referenced this pull request Feb 2, 2026
PR created by the Librarian CLI to initialize a release. Merging this PR
will auto trigger a release.

Librarian Version: v1.0.2-0.20251119154421-36c3e21ad3ac
Language Image:
us-central1-docker.pkg.dev/cloud-sdk-librarian-prod/images-prod/python-librarian-generator@sha256:8e2c32496077054105bd06c54a59d6a6694287bc053588e24debe6da6920ad91
<details><summary>google-cloud-storage: 3.9.0</summary>

##
[3.9.0](v3.8.0...v3.9.0)
(2026-02-02)

### Features

* update generation for MRD (#1730)
([08bc708](08bc7082))

* add get_object method for async grpc client (#1735)
([0e5ec29](0e5ec29b))

* Add micro-benchmarks for reads comparing standard (regional) vs rapid
(zonal) buckets. (#1697)
([1917649](1917649f))

* Add support for opening via `write_handle` and fix `write_handle` type
(#1715)
([2bc15fa](2bc15fa5))

* add samples for appendable objects writes and reads
([2e1a1eb](2e1a1eb5))

* add samples for appendable objects writes and reads (#1705)
([2e1a1eb](2e1a1eb5))

* add context manager to mrd (#1724)
([5ac2808](5ac2808a))

* Move Zonal Buckets features of `_experimental` (#1728)
([74c9ecc](74c9ecc5))

* add default user agent for grpc (#1726)
([7b31946](7b319469))

* expose finalized_time in blob.py applicable for GET_OBJECT in ZB
(#1719)
([8e21a7f](8e21a7fe))

* expose `DELETE_OBJECT` in `AsyncGrpcClient` (#1718)
([c8dd7a0](c8dd7a0b))

* send `user_agent` to grpc channel (#1712)
([cdb2486](cdb2486b))

* integrate writes strategy and appendable object writer (#1695)
([dbd162b](dbd162b3))

* Add micro-benchmarks for writes comparing standard (regional) vs rapid
(zonal) buckets. (#1707)
([dbe9d8b](dbe9d8b8))

* add support for `generation=0` to avoid overwriting existing objects
and add `is_stream_open` support (#1709)
([ea0f5bf](ea0f5bf8))

* add support for `generation=0` to prevent overwriting existing objects
([ea0f5bf](ea0f5bf8))

* add `is_stream_open` property to AsyncAppendableObjectWriter for
stream status check
([ea0f5bf](ea0f5bf8))

### Bug Fixes

* receive eof while closing reads stream (#1733)
([2ef6339](2ef63396))

* update write handle on every recv() (#1716)
([5d9fafe](5d9fafe1))

* implement requests_done method to signal end of requests in async
streams. Gracefully close streams. (#1700)
([6c16079](6c160794))

* implement requests_done method to signal end of requests in async
streams. Gracefully close streams.
([6c16079](6c160794))

* instance grpc client once per process in benchmarks (#1725)
([721ea2d](721ea2dd))

* Fix formatting in setup.py dependencies list (#1713)
([cc4831d](cc4831d7))

* Change contructors of MRD and AAOW AsyncGrpcClient.grpc_client to
AsyncGrpcClient (#1727)
([e730bf5](e730bf50))

</details>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

api: storage Issues related to the googleapis/python-storage API. size: m Pull request size is medium.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants