-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Storage: Updated Listing Operation Return Types #4803
Conversation
sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobServiceAsyncClient.java
Outdated
Show resolved
Hide resolved
sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/ContainerAsyncClient.java
Outdated
Show resolved
Hide resolved
sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAPITest.groovy
Outdated
Show resolved
Hide resolved
Flux<ContainerItem> response = blobServiceAsyncClient.listContainers(options); | ||
|
||
return timeout == null ? response.toIterable() : response.timeout(timeout).toIterable(); | ||
return timeout == null ? response.toStream() : response.timeout(timeout).toStream(); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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( |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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( |
There was a problem hiding this comment.
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.
sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/PageBlobAsyncClient.java
Outdated
Show resolved
Hide resolved
For the sync case, the current plan is, rather than return Iterable or Stream, to return |
…into OLD-paged-flux
…into OLD-paged-flux
87d8c41
to
dbf403a
Compare
Updated sync clients to use |
sdk/core/azure-core/src/main/java/com/azure/core/http/rest/PagedIterable.java
Outdated
Show resolved
Hide resolved
sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAPITest.groovy
Outdated
Show resolved
Hide resolved
sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAPITest.groovy
Outdated
Show resolved
Hide resolved
sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAPITest.groovy
Show resolved
Hide resolved
There was a problem hiding this 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
sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlockBlobAsyncClient.java
Outdated
Show resolved
Hide resolved
@@ -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, |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tracked separately under #5097
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAPITest.groovy
Outdated
Show resolved
Hide resolved
sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAPITest.groovy
Outdated
Show resolved
Hide resolved
There was a problem hiding this 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
There was a problem hiding this 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
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.