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: Updated Listing Operation Return Types #4803

Merged
merged 7 commits into from
Aug 23, 2019

Conversation

jaschrep-msft
Copy link
Member

Storage SDK upated to new listing API standards. (Not yet paged listing
for sync APIs)
Async listing return types updated from Flux to PagedFlux
Sync listing return types updated from Iterable to Stream

Bug Fixes:
Fixed bug where Flux<PagedResponse> returned from PagedFlux::byPage()
would attempt to follow non-existent continuation tokens.

@jaschrep-msft jaschrep-msft added Storage Storage Service (Queues, Blobs, Files) Azure.Core azure-core labels Aug 2, 2019
@jaschrep-msft jaschrep-msft requested a review from sima-zhu as a code owner August 2, 2019 16:40
Flux<ContainerItem> response = blobServiceAsyncClient.listContainers(options);

return timeout == null ? response.toIterable() : response.timeout(timeout).toIterable();
return timeout == null ? response.toStream() : response.timeout(timeout).toStream();
Copy link
Contributor

Choose a reason for hiding this comment

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

Alan's PR has a helper method for the timeout in Utility. Is that visible to you?

Copy link
Member

Choose a reason for hiding this comment

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

That method is only for Mono responses, this is a Flux.

});

return new PagedFlux<>(
() -> postProcessResponse(this.azureBlobStorage.blockBlobs().getBlockListWithRestResponseAsync(
Copy link
Contributor

Choose a reason for hiding this comment

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

It is too complex to understand. Could you please have a helper method?

.collect(Collectors.toList()),
null /* nextLink */,
response.deserializedHeaders())),
(marker) -> null);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is there no next page? If there is a justification, could you have it in Javadoc?

Copy link
Member

Choose a reason for hiding this comment

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

This is a single response Flux, this is a current gap in our Flux and PagedFlux returns as it doesn't fit either cleanly. This will be a discussion for Preview 3

Copy link
Contributor

Choose a reason for hiding this comment

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

If other list APIs have a way to do pagination, then customer would expect this one has pagination as well. It is better to have javadoc to make it clear.

final BlobAccessConditions finalAccessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions;

return new PagedFlux<>(
() -> postProcessResponse(this.azureBlobStorage.pageBlobs().getPageRangesWithRestResponseAsync(
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you have a local variable for the postResponse? Too complex to digest.

@JonathanGiles
Copy link
Member

For the sync case, the current plan is, rather than return Iterable or Stream, to return IterableResponse or PagedIterable, which are both in azure-core now. Please take a look and consider making use of these.

@jaschrep-msft jaschrep-msft force-pushed the storage-listing-pageflux branch from 87d8c41 to dbf403a Compare August 22, 2019 21:18
@jaschrep-msft
Copy link
Member Author

Updated sync clients to use PagedIterable<T>. Added overloads to PagedIterable<T> to bring it up to speed with PagedFlux<T> functionality.

@jaschrep-msft jaschrep-msft requested a review from sima-zhu August 22, 2019 22:24
Copy link
Member

@gapra-msft gapra-msft left a comment

Choose a reason for hiding this comment

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

Made some comments about commented out tests

@@ -379,19 +377,12 @@ private String getBlockID() {
*
* @return A reactive response containing the list of blocks.
*/
public Flux<BlockItem> listBlocks(BlockListType listType,
public Mono<Response<BlockList>> listBlocks(BlockListType listType,
Copy link
Contributor

Choose a reason for hiding this comment

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

Did we have a conversation with Jonathan about non-paged listing operations returning Mono? It seems to me that Flux is more natural, but if that discussion has been had, then I'll go along with it.

Copy link
Member Author

Choose a reason for hiding this comment

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

@JonathanGiles has there been a decision on return types for listing operations that aren't paginated?

Copy link
Member Author

Choose a reason for hiding this comment

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

Tracked separately under #5097

Copy link
Member

Choose a reason for hiding this comment

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

Yeah - this change isn't what I expected to see either. I would have preferred to see a PagedFlux here, even though there is only one page. I'll clarify the spec on this this week. I also suspect you would like to see improvements to the PagedFlux constructors for situations where there is no follow-up pages in the response - please do feel free to submit PRs to improve that (or else let me know and I will ensure it gets improved).

@@ -707,111 +760,19 @@ public URL getContainerUrl() {
* [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=list_blobs_hierarchy_helper "helper code for ContainerAsyncClient.listBlobsHierarchySegment")] \n
* For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
*/
private Mono<ContainersListBlobHierarchySegmentResponse> listBlobsHierarchySegment(String marker, String delimiter, ListBlobsOptions options) {
private Mono<ContainersListBlobHierarchySegmentResponse> listBlobsHierarchySegment(String marker, String delimiter,
ListBlobsOptions options, Duration timeout) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we generally accept timeout as a parameter on async apis. I'd also be surprised if we wanted this overload that returns ContainersListBlobHierarchySegmentResponse. I think we always want it to be PagedFlux, no?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is a private helper method for the paginated methods above. The PagedFlux implementation makes use of this to lazily fetch the next page.

Regarding the timeout, this is because of the synchronous wrappers for the paginated method; none of the public async methods accept a timeout. The synchronous methods for paginated listings must wrap the PagedFlux in a PagedIterable. However, if the user specifies a timeout for this operation, we cannot apply a timeout on the PagedFlux BEFORE the user decides if they want this by-item or by-page (Flux::timeout(Duration) returns TimeoutFlux, a hidden implementation of Flux, destroying our ability to use PagedFlux functionality). Since we cannot apply the timeout at the syncrhonous convenience layer, we need to find a new place. The chosen method here is diving down and applying the timeout to each individual Mono in the lazily-fetched pages. Considering Flux::timeout(Duration) applies the timeout between each individual emission, this is nearly identical to how a timeout would be applied to the Flux as a whole.


then:
headers.value("x-ms-request-id") != null
headers.value("x-ms-version") != null
headers.value("x-ms-content-crc64") != null
headers.value("x-ms-request-server-encrypted") != null

def response = bu2.listBlocks(BlockListType.ALL)
response.uncommittedBlocks().size() == 1
Copy link
Contributor

Choose a reason for hiding this comment

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

What was the conversation around spliting up these two lists? It seems like we'd want to be consistent with the fact that blobItems and prefixes are presented in one list

Copy link
Member Author

Choose a reason for hiding this comment

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

My understanding is this:

For listing blobs in a container, this is a paginated listing operation that returns two different lists, so auto-continuing two lists at the same time while someone is likely only consuming one at a time is a problematic approach. Therefore we join the lists and have a flag to tell you what is what. Since this API simulates listing blobs and "directories," this is actually useful, as the JDK provides similar functionality when browsing the local filesystem.

For listing blocks in a blob, this is not paginated. In the world where we are not using the PagedFlux listing approach for operations that are not paged, we are already returning a Mono of a buffered data structure, and so we can keep the two lists pre-separated for the user.

Copy link
Member Author

Choose a reason for hiding this comment

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

@JonathanGiles may have input on this.

Copy link
Member Author

@jaschrep-msft jaschrep-msft Aug 23, 2019

Choose a reason for hiding this comment

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

Answer to this is likely dependent on outcome of #5097, which is tracked separately.

Copy link
Contributor

@rickle-msft rickle-msft left a comment

Choose a reason for hiding this comment

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

A few questions/thoughts

Copy link
Contributor

@sima-zhu sima-zhu left a comment

Choose a reason for hiding this comment

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

Much clearer structure. Ship it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Azure.Core azure-core Storage Storage Service (Queues, Blobs, Files)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants