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

Add LRO support #42

Merged
merged 24 commits into from
Jan 3, 2017
Merged

Add LRO support #42

merged 24 commits into from
Jan 3, 2017

Conversation

michaelbausor
Copy link
Contributor

This is a possible OperationResponse object for use with LRO in PHP. Some points to note:

  • I'm not sure if we want to support promises, so I have commented them as optional. We can add support for them later in a non-breaking way
  • Calling getResult() returns null when the operation is not complete, and throws when it has completed with an error. Maybe it should return null when completed with an error?
  • A consequence of getResult() throwing is that pollUntilComplete() does not have a return value (it can't return getResult() because that might throw), which complicates the simple case

@jdpedrie
Copy link
Contributor

jdpedrie commented Oct 31, 2016

Thanks for this, Michael! I'm excited to get my hands on it.

@dwsupplee and I agree that if an LRO completes with an error, it should not throw an exception. Instead, the response should be returned, and left to the implementor to deal with.

If there is an error in any of the requests, (i.e. an invalid argument or a server error), those exceptions should certainly still be thrown.

@michaelbausor
Copy link
Contributor Author

OK no worries. If we are returning either the response or error, do you prefer:

  • Just return either the unpacked response, or the Status object containing the error, and let the user figure it out
  • Return an array, which would look like [true, response] for success or [false, status] for error
  • Return an array, which would look like [Status.code.OK, response] for success or [Status.code, status] for error

The reason to prefer either the second or third option over the first is to provide an easy way for people to check for success or failure, instead of having to interrogate the return type. Alternatively, we could provide helpers on the OperationResponse object, but this feels more awkward to me.

Thanks for having a look so quickly!

@jdpedrie
Copy link
Contributor

jdpedrie commented Oct 31, 2016

I should have been more careful in my previous comment. When I said "response", I was thinking in HTTP terms (i.e. response means the entire result returned from a call). I'd like to have the entire Operation available to manage as I see fit in a given situation. So I could check whether Operation.response or Operation.error were set and handle things as needed in either case. Apologies!

@michaelbausor
Copy link
Contributor Author

No worries, you are right that we should make the proto object available. I had intended to do that but missed that method :-( There is now an added method to get the operation proto object.

That still leaves the question of what to return from the getResult() method, which I think is a useful helper so that it isn't necessary to get the operation proto in most cases.

// Simple case
$op = $sampleApi->longRunningRpc();
// ... do stuff ...
$op->pollUntilComplete();

This comment was marked as spam.

This comment was marked as spam.

// TODO: use poll settings
sleep(1);
$this->refresh();
}

This comment was marked as spam.

This comment was marked as spam.

@jdpedrie
Copy link
Contributor

jdpedrie commented Nov 1, 2016

@michaelbausor WDYT about having getResult() and getError() methods, both of which are null when done is false. Once complete, on success, getResult() will return the response and getError() will remain null. On error, vice versa.

I think explicitly choosing the result or the error makes it easier to prevent errors in mishandling an unexpected result (i.e. if you code around what a success should look like and instead get an error, will your code break?).

$op = $sampleApi->longRunningRpc();
$op->pollUntilComplete();

if (!is_null($op->getError())) {
    // handle errors
}

return $op->getResult();

@michaelbausor
Copy link
Contributor Author

I think that sounds sensible. That makes the OperationResponse object very similar in structure to the proto object, will helpers for refresh(), cancel(), pollUntilComplete() and using promises.

@dwsupplee
Copy link
Contributor

@michaelbausor do we have the ability to make async calls with gRPC yet? If yes, it would be great if we could set some time aside to come up with a good plan for how to handle promises. For example, I have a WIP branch right now that introduces Async versions of all our veneer methods that trigger network requests by utilizing guzzle's promises library. If we could match a similar style in the generated code that would be really awesome.

@michaelbausor
Copy link
Contributor Author

Not right now through Veneer toolkit, but I am looking into what would be required to add that support. Definitely it would be great to pick a time to discuss how we want to handle promises more generally - how about Thursday or Friday this week some time?

@dwsupplee
Copy link
Contributor

Friday should work for me!

@michaelbausor
Copy link
Contributor Author

Following up re status - it seems that the latest is your open issue in gRPC (grpc/grpc#6654), which hasn't been given a priority yet. So we aren't able to support async over gRPC at this time. But it would still be worth having the discussion so that we are on the same page. Friday sounds good, I have created an event at 10:30 PST as a placeholder, please edit or ping me if that doesn't work for you.

@codecov-io
Copy link

codecov-io commented Nov 21, 2016

Current coverage is 89.78% (diff: 88.15%)

Merging #42 into master will increase coverage by 0.31%

@@             master        #42   diff @@
==========================================
  Files            16         18     +2   
  Lines          1130       1341   +211   
  Methods         123        147    +24   
  Messages          0          0          
  Branches          0          0          
==========================================
+ Hits           1011       1204   +193   
- Misses          119        137    +18   
  Partials          0          0          

Powered by Codecov. Last update b4930f6...545efa8

@michaelbausor
Copy link
Contributor Author

I have updated the proposed LRO surface, PTAL when you have a chance. It uses getResult() and getError() as @jdpedrie suggested above.

pollUntilComplete() accepts an optional callback, but I am not sure if this is adding very much value - perhaps it should be removed.

cc @bshaffer

@michaelbausor michaelbausor changed the title DO NOT MERGE: LRO sample Add LRO support Dec 20, 2016
@michaelbausor
Copy link
Contributor Author

@garrettjonesgoogle @shinfan PTAL for review before merging

/**
* The default address of the service.
*/
const SERVICE_ADDRESS = 'longrunning.googleapis.com';

This comment was marked as spam.

This comment was marked as spam.

*
* @type string $serviceAddress The domain name of the API remote host.
* Default 'longrunning.googleapis.com'.
* @type string $serviceAddress Required. The domain name of the API remote host.

This comment was marked as spam.

This comment was marked as spam.

Copy link
Contributor

@dwsupplee dwsupplee left a comment

Choose a reason for hiding this comment

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

This is looking nice overall! Just a few comments and things I am curious on.

@@ -17,7 +17,8 @@
},
"autoload": {
"psr-4": {
"Google\\GAX\\":"src/"
"Google\\GAX\\":"src/",
"Google\\Longrunning\\":"src/Longrunning/"

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

* interface to receive the real response asynchronously by polling the
* operation resource, or pass the operation resource to another API (such as
* Google Cloud Pub/Sub API) to receive the response. Any API service that
* returns long-running operations should implement the `Operations` interface

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

* ```
*
* Many parameters require resource names to be formatted in a particular way. To assist
* with these names, this class includes a format method for each type of name, and additionally

This comment was marked as spam.

This comment was marked as spam.

* Service Description: Manages long-running operations with an API service.
*
* When an API method normally takes long time to complete, it can be designed
* to return [Operation][google.longrunning.Operation] to the client, and the client can use this

This comment was marked as spam.

This comment was marked as spam.

* ```
*
* @param string $name The name of the operation collection.
* @param string $filter The standard list filter.

This comment was marked as spam.

This comment was marked as spam.

* Return true if the operation completed successfully, otherwise return
* false.
*
* The $pollSettings optional argument can be used to control the polling loop.

This comment was marked as spam.

This comment was marked as spam.

}

/**
* @return \google\longrunning\Operation The last Operation object received from the server.

This comment was marked as spam.

This comment was marked as spam.

* Starts asynchronous cancellation on a long-running operation. The server
* makes a best effort to cancel the operation, but success is not
* guaranteed. If the server doesn't support this method, it will throw an
* ApiException with code \google\rpc\Code::UNIMPLEMENTED. Clients can continue

This comment was marked as spam.

This comment was marked as spam.


$anyResponse = $this->lastProtoResponse->getResponse();
if (is_null($this->operationReturnType)) {
return $anyResponse;

This comment was marked as spam.

This comment was marked as spam.

* @param array $options {
* Options for configuring the polling behaviour.
*
* @type float $pollingIntervalSeconds The polling interval to use, in seconds.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

Copy link
Contributor Author

@michaelbausor michaelbausor left a comment

Choose a reason for hiding this comment

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

Thanks @dwsupplee !

I have made changes and/or commented, PTAL

* @param array $options {
* Options for configuring the polling behaviour.
*
* @type float $pollingIntervalSeconds The polling interval to use, in seconds.

This comment was marked as spam.

@dwsupplee
Copy link
Contributor

The updates look great, nice work!

* OperationResponse constructor.
*
* @param string $operationName
* @param \Google\Longrunning\OperationsClient $operationsClient

This comment was marked as spam.

This comment was marked as spam.

}

/**
* @return \Google\Longrunning\OperationsClient The OperationsClient object used to make

This comment was marked as spam.

This comment was marked as spam.

* backwards compatibility.
*/

namespace Google\GAX\Longrunning;

This comment was marked as spam.

This comment was marked as spam.

@michaelbausor
Copy link
Contributor Author

PTAL

@michaelbausor michaelbausor merged commit 0189f6f into googleapis:master Jan 3, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants