Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Storage: Use RequestConditions and return exploding responses #8275

Merged
merged 4 commits into from
Oct 22, 2019

Conversation

tg-msft
Copy link
Member

@tg-msft tg-msft commented Oct 21, 2019

It's probably best to review this by commit:

/// a semicolon.
/// </summary>
/// <param name="conditions">The collected conditions.</param>
internal virtual void AddConditions(StringBuilder conditions)
Copy link
Contributor

Choose a reason for hiding this comment

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

Filed #8292

sdk/storage/Azure.Storage.Blobs/src/LeaseClient.cs Outdated Show resolved Hide resolved
sdk/storage/Azure.Storage.Blobs/src/LeaseClient.cs Outdated Show resolved Hide resolved
sdk/storage/Azure.Storage.Blobs/src/LeaseClient.cs Outdated Show resolved Hide resolved
sdk/storage/Azure.Storage.Blobs/src/LeaseClient.cs Outdated Show resolved Hide resolved
// Return an exploding Response on 304
if (response.IsExplodingResponse())
{
return response.GetRawResponse().AsExplodingResponse<BlockList>();
Copy link
Member

Choose a reason for hiding this comment

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

What is an ExplodingResponse?

Copy link
Member Author

Choose a reason for hiding this comment

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

That's an affectionate name for Response<T>s that will throw if you try to access Value. It's the pattern we've settled on for 304s per Azure/azure-sdk#638.

We want to avoid throwing exceptions if we can because they're not great for performance and clutter up logs. If you add an HTTP precondition on a GET/HEAD operation, Storage will return a 304. Instead of throwing, we'll give you back a Response<T> that has a Status == 304 and will still throw if you try to access Response<T>.Value. This gives us the best of both worlds because it'll still throw for customers who don't check, but there's a way for customers who know better to avoid the exception. All other HTTP verbs will return a Status == 412 and we always throw for those.

We just need to be careful in our code that we don't accidentally touch Response<T>.Value if it might explode.

/// a semicolon.
/// </summary>
/// <param name="conditions">The collected conditions.</param>
internal override void AddConditions(StringBuilder conditions)
Copy link
Member

Choose a reason for hiding this comment

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

Where are these AddConditions() methods used?

Copy link
Member Author

Choose a reason for hiding this comment

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

These are used by the base ToString. Instead of having [BlobRequestConditions:IfMatch=null;IfNoneMatch=null;...] we'll just list the conditions that are actually present so it'll be [BlobRequestConditions:IfMatch=...;LeaseId=...] if you're only using IfMatch/LeaseId.

CancellationToken cancellationToken = default) =>
Upload(
content,
conditions: overwrite ? null : new BlobRequestConditions { IfNoneMatch = new ETag(Constants.Wildcard) },
Copy link
Member

Choose a reason for hiding this comment

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

The wildcard makes the semantics here "update if the blob (however identified from its unique identifier) is not present."
This means it will fail if you try to upload a blob that is the same version as the one you're holding, which technically is not overwriting it. I would have expected IfNoneMatch to take the Etag of the blob, so it would fail if you're trying the update with a different version, which would overwrite existing data. If theses are the semantics the service defines, though, I'm not concerned.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, 99% of the time this API is called we won't have an ETag to use. That's part of why we called this overwrite instead of onlyIfUnchanged like you're doing in AppConfig since it's not relative to an existing ETag. Any customer who wants that behavior could the overload that allows them to pass BlobAccessConditions.

Copy link
Member

@annelo-msft annelo-msft left a comment

Choose a reason for hiding this comment

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

LGTM

@tg-msft tg-msft merged commit 640488d into Azure:master Oct 22, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants