Skip to content

Commit

Permalink
Merge pull request Azure#224 from daschult/SupportLocationPolling
Browse files Browse the repository at this point in the history
Add support for Location and Azure-AsyncOperation long running operations
  • Loading branch information
Dan Schulte authored Sep 21, 2017
2 parents 02dace9 + 0538c84 commit f83d9f1
Show file tree
Hide file tree
Showing 9 changed files with 817 additions and 316 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for
* license information.
*/

package com.microsoft.azure.v2;

import com.microsoft.rest.protocol.SerializerAdapter;
import com.microsoft.rest.v2.http.HttpRequest;
import com.microsoft.rest.v2.http.HttpResponse;
import rx.Single;
import rx.functions.Func1;

import java.io.IOException;

/**
* A PollStrategy type that uses the Azure-AsyncOperation header value to check the status of a long
* running operation.
*/
public final class AzureAsyncOperationPollStrategy extends PollStrategy {
private final String fullyQualifiedMethodName;
private final String operationResourceUrl;
private final String originalResourceUrl;
private final SerializerAdapter<?> serializer;
private boolean pollingCompleted;
private boolean pollingSucceeded;
private boolean gotResourceResponse;

/**
* The name of the header that indicates that a long running operation will use the
* Azure-AsyncOperation strategy.
*/
public static final String HEADER_NAME = "Azure-AsyncOperation";

/**
* The provisioning state of the operation resource if the operation is still in progress.
*/
public static final String IN_PROGRESS = "InProgress";

/**
* The provisioning state of the operation resource if the operation is successful.
*/
public static final String SUCCEEDED = "Succeeded";

/**
* Create a new AzureAsyncOperationPollStrategy object that will poll the provided operation
* resource URL.
* @param fullyQualifiedMethodName The fully qualified name of the method that initiated the
* long running operation.
* @param operationResourceUrl The URL of the operation resource this pollStrategy will poll.
* @param originalResourceUrl The URL of the resource that the long running operation is
* operating on.
* @param serializer The serializer that will deserialize the operation resource and the
* final operation result.
*/
private AzureAsyncOperationPollStrategy(String fullyQualifiedMethodName, String operationResourceUrl, String originalResourceUrl, SerializerAdapter<?> serializer) {
super(AzureProxy.defaultDelayInMilliseconds());

this.fullyQualifiedMethodName = fullyQualifiedMethodName;
this.operationResourceUrl = operationResourceUrl;
this.originalResourceUrl = originalResourceUrl;
this.serializer = serializer;
}

@Override
public HttpRequest createPollRequest() {
String pollUrl = null;
if (!pollingCompleted) {
pollUrl = operationResourceUrl;
}
else if (pollingSucceeded) {
pollUrl = originalResourceUrl;
}
return new HttpRequest(fullyQualifiedMethodName, "GET", pollUrl);
}

@Override
public void updateFrom(HttpResponse httpPollResponse) throws IOException {
updateFromAsync(httpPollResponse).toBlocking().value();
}

@Override
public Single<HttpResponse> updateFromAsync(final HttpResponse httpPollResponse) {
updateDelayInMillisecondsFrom(httpPollResponse);

Single<HttpResponse> result;
if (!pollingCompleted) {
result = httpPollResponse.bodyAsStringAsync()
.flatMap(new Func1<String, Single<HttpResponse>>() {
@Override
public Single<HttpResponse> call(String bodyString) {
Single<HttpResponse> result;
try {
final OperationResource operationResource = serializer.deserialize(bodyString, OperationResource.class);
if (operationResource != null) {
final String provisioningState = provisioningState(operationResource);
pollingCompleted = !IN_PROGRESS.equalsIgnoreCase(provisioningState);
if (pollingCompleted) {
pollingSucceeded = SUCCEEDED.equalsIgnoreCase(provisioningState);
clearDelayInMilliseconds();
}
}
result = Single.just(httpPollResponse);
} catch (IOException e) {
result = Single.error(e);
}
return result;
}
});
}
else {
if (pollingSucceeded) {
gotResourceResponse = true;
}

result = Single.just(httpPollResponse);
}

return result;
}

private static String provisioningState(OperationResource operationResource) {
String provisioningState = null;

final OperationResource.Properties properties = operationResource.properties();
if (properties != null) {
provisioningState = properties.provisioningState();
}

return provisioningState;
}

@Override
public boolean isDone() {
return pollingCompleted && (!pollingSucceeded || gotResourceResponse);
}

/**
* Try to create a new AzureAsyncOperationPollStrategy object that will poll the provided
* operation resource URL. If the provided HttpResponse doesn't have an Azure-AsyncOperation
* header or if the header is empty, then null will be returned.
* @param fullyQualifiedMethodName The fully qualified name of the method that initiated the
* long running operation.
* @param httpResponse The HTTP response that the required header values for this pollStrategy
* will be read from.
*/
static AzureAsyncOperationPollStrategy tryToCreate(String fullyQualifiedMethodName, HttpResponse httpResponse, String originalResourceUrl, SerializerAdapter<?> serializer) {
final String azureAsyncOperationUrl = httpResponse.headerValue(HEADER_NAME);
return azureAsyncOperationUrl != null && !azureAsyncOperationUrl.isEmpty()
? new AzureAsyncOperationPollStrategy(fullyQualifiedMethodName, azureAsyncOperationUrl, originalResourceUrl, serializer)
: null;
}
}
Loading

0 comments on commit f83d9f1

Please sign in to comment.