Repository navigation
Conversation
`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.
There was a problem hiding this comment.
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 Please add system tests for these changes in https://github.com/googleapis/google-cloud-python/blob/main/packages/google-cloud-storage/tests/system/test_rapid.py |
|
@yuxin00j , please see my comment http://shortn/_bOdi6IPxm9 |
…ss on AsyncAppendableObjectWriter
|
/gcbrun |
…p resending preconditions after create
|
/gcbrun |
1 similar comment
|
/gcbrun |
|
/gcbrun |
…le with metageneration preconditions Passing generation=None to from_blob overwrites a fetched Blob (for example with if_generation_match=blob.generation) while keeping its metadata. Metageneration preconditions are rejected together with write_handle because GCS only checks them when the handle is empty. Also consolidates the precondition unit tests.
|
/gcbrun |
Summary
AsyncAppendableObjectWriteroverloadsgeneration:None/0creates a new object viaWriteObjectSpec(if_generation_match=generation), whileN > 0reopens an existing object viaAppendObjectSpec(generation=N). There was no way to passif_generation_match=N(N > 0) onWriteObjectSpec(overwrite only if the current generation matchesN) or other write preconditions (if_generation_not_match,if_metageneration_match,if_metageneration_not_match).This adds a
Preconditionsdataclass (if_generation_match,if_generation_not_match,if_metageneration_match,if_metageneration_not_match) accepted viapreconditions: Optional[Preconditions] = NoneonAsyncAppendableObjectWriter.__init__,AsyncAppendableObjectWriter.from_blob, and_AsyncWriteObjectStream.__init__:if_generation_match,if_generation_not_match) requiregeneration=None. Combining them withgenerationraisesValueError, includingfrom_blobwhenblob.generationis set. To overwrite a fetched Blob, passgeneration=Nonetofrom_blob, for example withPreconditions(if_generation_match=blob.generation).generation=0withoutpreconditionsstill meansif_generation_match=0.generationisNoneor0) sets all 4 fields onWriteObjectSpec. Appending to an existing object (generation > 0) sets the metageneration preconditions onAppendObjectSpec. Metageneration preconditions cannot be combined withwrite_handle(raisesValueError), because GCS only checks them when no write handle is sent.AppendObjectSpecwithout preconditions, because they describe the object that was replaced.Motivation: fsspec/gcsfs#1101 (compare-and-swap writes in gcsfs).
Test plan