Skip to content

Commit

Permalink
Merge pull request #46 from Azure/daschult/lroresponse
Browse files Browse the repository at this point in the history
Add HttpLongRunningOperationResponse
  • Loading branch information
Dan Schulte authored Aug 15, 2018
2 parents cd71ffe + 6c48368 commit 27c50fa
Show file tree
Hide file tree
Showing 4 changed files with 326 additions and 159 deletions.
39 changes: 26 additions & 13 deletions lib/azureServiceClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
// Licensed under the MIT License. See License.txt in the project root for license information.

import { HttpOperationResponse, RequestOptionsBase, RequestPrepareOptions, ServiceClient, ServiceClientCredentials, ServiceClientOptions, WebResource } from "ms-rest-js";
import { createLROPollStrategy, LROPollStrategy } from "./lroPollStrategy";
import { HttpLongRunningOperationResponse, createHttpLongRunningOperationResponseFromInitialResponse, createHttpLongRunningOperationResponseFromMemento } from "./httpLongRunningOperationResponse";
import * as Constants from "./util/constants";
import { LROMemento } from "./lroPollStrategy";

/**
* Options to be provided while creating the client.
Expand Down Expand Up @@ -58,7 +59,20 @@ export class AzureServiceClient extends ServiceClient {
* @returns {Promise<msRest.HttpOperationResponse>} The HttpOperationResponse containing the final polling request, response and the responseBody.
*/
async sendLongRunningRequest(request: RequestPrepareOptions | WebResource, options?: RequestOptionsBase): Promise<HttpOperationResponse> {
return this.sendRequest(request).then((response: HttpOperationResponse) => this.getLongRunningOperationResult(response, options));
return this.beginLongRunningRequest(request, options).then((lroResponse: HttpLongRunningOperationResponse) => lroResponse.pollUntilFinished());
}

/**
* Send the initial request of a LRO (long running operation) and get back an
* HttpLongRunningOperationResponse that provides methods for polling the LRO and checking if the
* LRO is finished.
* @param {msRest.RequestPrepareOptions|msRest.WebResource} request - The request object
* @param {AzureRequestOptionsBase} [options] Additional options to be sent while making the request
* @returns {Promise<HttpLongRunningOperationResponse>} The HttpLongRunningOperationResponse
* that provides methods for interacting with the LRO.
*/
async beginLongRunningRequest(request: RequestPrepareOptions | WebResource, options?: RequestOptionsBase): Promise<HttpLongRunningOperationResponse> {
return this.sendRequest(request).then((initialResponse: HttpOperationResponse) => createHttpLongRunningOperationResponseFromInitialResponse(this, initialResponse, options));
}

/**
Expand All @@ -68,17 +82,16 @@ export class AzureServiceClient extends ServiceClient {
* @returns {Promise<HttpOperationResponse>} The final response after polling is complete.
*/
async getLongRunningOperationResult(initialResponse: HttpOperationResponse, options?: RequestOptionsBase): Promise<HttpOperationResponse> {
const lroPollStrategy: LROPollStrategy | undefined = createLROPollStrategy(initialResponse, this, options);
if (!lroPollStrategy) {
return initialResponse;
} else {
const succeeded: boolean = await lroPollStrategy.pollUntilFinished();
if (succeeded) {
return lroPollStrategy.getOperationResponse();
} else {
throw lroPollStrategy.getRestError();
}
}
const lroResponse: HttpLongRunningOperationResponse = createHttpLongRunningOperationResponseFromInitialResponse(this, initialResponse, options);
return lroResponse.pollUntilFinished();
}

/**
* Restore an HttpLongRunningOperationResponse from the provided LROMemento. This method can be
* used to recreate an HttpLongRunningOperationResponse on a different process or machine.
*/
restoreHttpLongRunningOperationResponse(lroMemento: LROMemento): HttpLongRunningOperationResponse {
return createHttpLongRunningOperationResponseFromMemento(this, lroMemento);
}
}

Expand Down
88 changes: 88 additions & 0 deletions lib/httpLongRunningOperationResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

import { HttpOperationResponse, RequestOptionsBase } from "ms-rest-js";
import { AzureServiceClient } from "./azureServiceClient";
import { createLROPollStrategyFromInitialResponse, createLROPollStrategyFromMemento, LROMemento, LROPollStrategy } from "./lroPollStrategy";
import { LongRunningOperationStates } from "./util/constants";

/**
* An HTTP operation response that provides special methods for interacting with LROs (long running
* operations).
*/
export class HttpLongRunningOperationResponse {
/**
* Create a new HttpLongRunningOperationResponse.
* @param _lroPollStrategy The LROPollStrategy that this HttpLongRunningOperationResponse will
* use to interact with the LRO.
*/
constructor(private readonly _lroPollStrategy: LROPollStrategy | undefined, private readonly _initialResponse: HttpOperationResponse) {
}

/**
* Get the current status of the LRO.
* @returns The current status of the LRO.
*/
public getOperationStatus(): LongRunningOperationStates {
const lroPollStrategy: LROPollStrategy | undefined = this._lroPollStrategy;
return !lroPollStrategy ? "Succeeded" : lroPollStrategy.getOperationStatus();
}

/**
* Send a single poll request and return the LRO's state.
* @returns The LRO's state.
*/
public poll(): Promise<LongRunningOperationStates> {
let result: Promise<LongRunningOperationStates>;
const lroPollStrategy: LROPollStrategy | undefined = this._lroPollStrategy;
if (!lroPollStrategy) {
result = Promise.resolve<LongRunningOperationStates>("Succeeded");
} else {
result = lroPollStrategy.sendPollRequest().then(() => {
return lroPollStrategy.getOperationStatus();
});
}
return result;
}

/**
* Send poll requests that check the LRO's status until it is determined that the LRO is finished.
* @returns Whether or not the LRO succeeded.
*/
public async pollUntilFinished(): Promise<HttpOperationResponse> {
let result: Promise<HttpOperationResponse>;
const lroPollStrategy: LROPollStrategy | undefined = this._lroPollStrategy;
if (!lroPollStrategy) {
result = Promise.resolve(this._initialResponse);
} else {
result = lroPollStrategy.pollUntilFinished().then((succeeded: boolean) => {
if (succeeded) {
return lroPollStrategy.getOperationResponse();
} else {
throw lroPollStrategy.getRestError();
}
});
}
return result;
}

/**
* Get an LROMemento object that can be used to poll this LRO in a different context (such as on a
* different process or a different machine). If the LRO couldn't produce an LRO polling strategy,
* then this will return undefined.
*/
public getMemento(): LROMemento | undefined {
const lroPollStrategy: LROPollStrategy | undefined = this._lroPollStrategy;
return !lroPollStrategy ? undefined : lroPollStrategy.getMemento();
}
}

export function createHttpLongRunningOperationResponseFromInitialResponse(azureServiceClient: AzureServiceClient, initialResponse: HttpOperationResponse, options?: RequestOptionsBase): HttpLongRunningOperationResponse {
const lroPollStrategy: LROPollStrategy | undefined = createLROPollStrategyFromInitialResponse(initialResponse, azureServiceClient, options);
return new HttpLongRunningOperationResponse(lroPollStrategy, initialResponse);
}

export function createHttpLongRunningOperationResponseFromMemento(azureServiceClient: AzureServiceClient, lroMemento: LROMemento): HttpLongRunningOperationResponse {
const lroPollStrategy: LROPollStrategy | undefined = createLROPollStrategyFromMemento(azureServiceClient, lroMemento);
return new HttpLongRunningOperationResponse(lroPollStrategy, lroMemento.initialResponse);
}
Loading

0 comments on commit 27c50fa

Please sign in to comment.