Skip to content

feat(storage): add Preconditions to AsyncAppendableObjectWriter - #18641

Open
yuxin00j wants to merge 2 commits into
googleapis:mainfrom
yuxin00j:storage-if-generation-match
Open

yuxin00j wants to merge 2 commits into
googleapis:mainfrom
yuxin00j:storage-if-generation-match

Conversation

@yuxin00j

@yuxin00j yuxin00j commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Summary

AsyncAppendableObjectWriter overloads generation: None / 0 creates a new object via WriteObjectSpec(if_generation_match=generation), while N > 0 reopens an existing object via AppendObjectSpec(generation=N). There was no way to pass if_generation_match=N (N > 0) on WriteObjectSpec (overwrite only if the current generation matches N) or other write preconditions (if_generation_not_match, if_metageneration_match, if_metageneration_not_match).

This adds a Preconditions dataclass (if_generation_match, if_generation_not_match, if_metageneration_match, if_metageneration_not_match) accepted via preconditions: Optional[Preconditions] = None on AsyncAppendableObjectWriter.__init__, AsyncAppendableObjectWriter.from_blob, and _AsyncWriteObjectStream.__init__:

  • When creating or overwriting an object (generation is None or 0), all 4 precondition fields are populated on WriteObjectSpec (preconditions.if_generation_match takes precedence over generation=0, while generation=0 without preconditions continues to set if_generation_match=0).
  • When appending to an existing object (generation > 0, including redirect takeover and reconnects after creation), if_metageneration_match and if_metageneration_not_match are forwarded on AppendObjectSpec and generation preconditions are ignored.

Motivation: fsspec/gcsfs#1101 (compare-and-swap writes in gcsfs).

Test plan

cd packages/google-cloud-storage
PYTHONPATH=$PWD python -m pytest tests/unit/asyncio/test_async_write_object_stream.py tests/unit/asyncio/test_async_appendable_object_writer.py   # 82 passed
ruff check --select I --target-version=py310 --line-length=88 <changed files>
ruff format --check --target-version=py310 --line-length=88 <changed files>
flake8 <changed files>

This change was authored with an AI assistant; the description above was reviewed by the author.

`AsyncAppendableObjectWriter` and `_AsyncWriteObjectStream` overloaded a
single `generation` argument: `None`/`0` created a new object via
`WriteObjectSpec(if_generation_match=generation)`, while `N > 0` reopened
an existing object via `AppendObjectSpec(generation=N)`. There was no way
to request `WriteObjectSpec(appendable=True, if_generation_match=N)`,
i.e. overwrite an object only if its current generation is still `N`,
although the gRPC API and the other GCS client libraries support it.

This adds an explicit `if_generation_match` parameter. It is set on
`WriteObjectSpec` when creating a new object (`generation` is `None` or
`0`; `generation=0` keeps meaning `if_generation_match=0` when the new
parameter is not given) and is ignored when `generation > 0` selects an
existing object to append to, so the redirect-retry path that reopens
with the redirected generation is unaffected.

Test Plan:

```
cd packages/google-cloud-storage
PYTHONPATH=$PWD python -m pytest tests/unit/asyncio/test_async_write_object_stream.py tests/unit/asyncio/test_async_appendable_object_writer.py  # 73 passed
ruff check --select I --target-version=py310 --line-length=88 <changed files>
ruff format --check --target-version=py310 --line-length=88 <changed files>
flake8 <changed files>
```

Authored with an AI assistant.

@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 adds support for the if_generation_match precondition parameter to the asynchronous appendable object writer and write object stream classes. It updates AsyncAppendableObjectWriter and _AsyncWriteObjectStream to accept, document, and propagate this parameter to the underlying BidiWriteObjectRequest. Unit tests have also been added to verify the correct handling of this parameter. There are no review comments to address, and I have no feedback to provide.

@yuxin00j
yuxin00j requested a review from chandra-siri October 13, 2026 05:41
@yuxin00j
yuxin00j marked this pull request as ready for review October 13, 2026 05:41
@yuxin00j
yuxin00j requested a review from a team as a code owner October 13, 2026 05:41
@chandra-siri chandra-siri self-assigned this Oct 22, 2026
@chandra-siri

Copy link
Copy Markdown
Contributor

@chandra-siri

Copy link
Copy Markdown
Contributor

@yuxin00j , please see my comment http://shortn/_bOdi6IPxm9

@yuxin00j
yuxin00j requested a review from a team as a code owner October 29, 2026 07:44
@yuxin00j yuxin00j changed the title feat(storage): add if_generation_match to AsyncAppendableObjectWriter feat(storage): add Preconditions to AsyncAppendableObjectWriter Oct 29, 2026
@yuxin00j

Copy link
Copy Markdown
Contributor Author

/gcbrun

This branch has not been deployed

No deployments
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.

3 participants