← All changes
|
includes/sdk/google/google/gax/src/OperationResponse.php
+76
-34
1.2.0
→
1.4.2
View file →
| @@ -29,14 +29,19 @@ | ||
| 29 | 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 30 | 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 31 | 31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 32 | 32 | */ |
| 33 | -namespace Dudlewebs\WPMCS\Google\ApiCore; | |
| 33 | +namespace Dudlewebs\WPMCS\GCP\Google\ApiCore; | |
| 34 | 34 | |
| 35 | -use Dudlewebs\WPMCS\Google\LongRunning\Operation; | |
| 36 | -use Dudlewebs\WPMCS\Google\Protobuf\Any; | |
| 37 | -use Dudlewebs\WPMCS\Google\Protobuf\Internal\Message; | |
| 38 | -use Dudlewebs\WPMCS\Google\Rpc\Status; | |
| 35 | +use Dudlewebs\WPMCS\GCP\Google\LongRunning\CancelOperationRequest; | |
| 36 | +use Dudlewebs\WPMCS\GCP\Google\LongRunning\Client\OperationsClient; | |
| 37 | +use Dudlewebs\WPMCS\GCP\Google\LongRunning\DeleteOperationRequest; | |
| 38 | +use Dudlewebs\WPMCS\GCP\Google\LongRunning\GetOperationRequest; | |
| 39 | +use Dudlewebs\WPMCS\GCP\Google\LongRunning\Operation; | |
| 40 | +use Dudlewebs\WPMCS\GCP\Google\LongRunning\OperationsClient as LegacyOperationsClient; | |
| 41 | +use Dudlewebs\WPMCS\GCP\Google\Protobuf\Any; | |
| 42 | +use Dudlewebs\WPMCS\GCP\Google\Protobuf\Internal\Message; | |
| 43 | +use Dudlewebs\WPMCS\GCP\Google\Rpc\Status; | |
| 39 | 44 | use LogicException; |
| 40 | 45 | /** |
| 41 | 46 | * Response object from a long running API method. |
| 42 | 47 | * |
| @@ -49,8 +54,10 @@ | ||
| 49 | 54 | * Operations API, which is used by the OperationResponse object. If |
| 50 | 55 | * more control is required, it is possible to make calls against the |
| 51 | 56 | * Operations API directly instead of via the OperationResponse object |
| 52 | 57 | * using an Operations Client instance. |
| 58 | + * | |
| 59 | + * @template T = mixed | |
| 53 | 60 | */ |
| 54 | 61 | class OperationResponse |
| 55 | 62 | { |
| 56 | 63 | use PollingTrait; |
| @@ -57,8 +64,9 @@ | ||
| 57 | 64 | const DEFAULT_POLLING_INTERVAL = 1000; |
| 58 | 65 | const DEFAULT_POLLING_MULTIPLIER = 2; |
| 59 | 66 | const DEFAULT_MAX_POLLING_INTERVAL = 60000; |
| 60 | 67 | const DEFAULT_MAX_POLLING_DURATION = 0; |
| 68 | + private const NEW_CLIENT_NAMESPACE = '\\Client\\'; | |
| 61 | 69 | private string $operationName; |
| 62 | 70 | private ?object $operationsClient; |
| 63 | 71 | private ?string $operationReturnType; |
| 64 | 72 | private ?string $metadataReturnType; |
| @@ -68,8 +76,11 @@ | ||
| 68 | 76 | private array $additionalArgs; |
| 69 | 77 | private string $getOperationMethod; |
| 70 | 78 | private ?string $cancelOperationMethod; |
| 71 | 79 | private ?string $deleteOperationMethod; |
| 80 | + private string $getOperationRequest; | |
| 81 | + private ?string $cancelOperationRequest; | |
| 82 | + private ?string $deleteOperationRequest; | |
| 72 | 83 | private string $operationStatusMethod; |
| 73 | 84 | /** @var mixed */ |
| 74 | 85 | private $operationStatusDoneValue; |
| 75 | 86 | private ?string $operationErrorCodeMethod; |
| @@ -102,9 +113,9 @@ | ||
| 102 | 113 | public function __construct(string $operationName, $operationsClient, array $options = []) |
| 103 | 114 | { |
| 104 | 115 | $this->operationName = $operationName; |
| 105 | 116 | $this->operationsClient = $operationsClient; |
| 106 | - $options += ['operationReturnType' => null, 'metadataReturnType' => null, 'lastProtoResponse' => null, 'getOperationMethod' => 'getOperation', 'cancelOperationMethod' => 'cancelOperation', 'deleteOperationMethod' => 'deleteOperation', 'operationStatusMethod' => 'getDone', 'operationStatusDoneValue' => \true, 'additionalOperationArguments' => [], 'operationErrorCodeMethod' => null, 'operationErrorMessageMethod' => null]; | |
| 117 | + $options += ['operationReturnType' => null, 'metadataReturnType' => null, 'lastProtoResponse' => null, 'getOperationMethod' => 'getOperation', 'cancelOperationMethod' => 'cancelOperation', 'deleteOperationMethod' => 'deleteOperation', 'operationStatusMethod' => 'getDone', 'operationStatusDoneValue' => \true, 'additionalOperationArguments' => [], 'operationErrorCodeMethod' => null, 'operationErrorMessageMethod' => null, 'getOperationRequest' => GetOperationRequest::class, 'cancelOperationRequest' => CancelOperationRequest::class, 'deleteOperationRequest' => DeleteOperationRequest::class]; | |
| 107 | 118 | $this->operationReturnType = $options['operationReturnType']; |
| 108 | 119 | $this->metadataReturnType = $options['metadataReturnType']; |
| 109 | 120 | $this->lastProtoResponse = $options['lastProtoResponse']; |
| 110 | 121 | $this->getOperationMethod = $options['getOperationMethod']; |
| @@ -114,8 +125,11 @@ | ||
| 114 | 125 | $this->operationStatusMethod = $options['operationStatusMethod']; |
| 115 | 126 | $this->operationStatusDoneValue = $options['operationStatusDoneValue']; |
| 116 | 127 | $this->operationErrorCodeMethod = $options['operationErrorCodeMethod']; |
| 117 | 128 | $this->operationErrorMessageMethod = $options['operationErrorMessageMethod']; |
| 129 | + $this->getOperationRequest = $options['getOperationRequest']; | |
| 130 | + $this->cancelOperationRequest = $options['cancelOperationRequest']; | |
| 131 | + $this->deleteOperationRequest = $options['deleteOperationRequest']; | |
| 118 | 132 | if (isset($options['initialPollDelayMillis'])) { |
| 119 | 133 | $this->defaultPollSettings['initialPollDelayMillis'] = $options['initialPollDelayMillis']; |
| 120 | 134 | } |
| 121 | 135 | if (isset($options['pollDelayMultiplier'])) { |
| @@ -137,10 +151,10 @@ | ||
| 137 | 151 | { |
| 138 | 152 | if (!$this->hasProtoResponse()) { |
| 139 | 153 | return \false; |
| 140 | 154 | } |
| 141 | - $status = call_user_func([$this->lastProtoResponse, $this->operationStatusMethod]); | |
| 142 | - if (is_null($status)) { | |
| 155 | + $status = \call_user_func([$this->lastProtoResponse, $this->operationStatusMethod]); | |
| 156 | + if (\is_null($status)) { | |
| 143 | 157 | return \false; |
| 144 | 158 | } |
| 145 | 159 | return $status === $this->operationStatusDoneValue; |
| 146 | 160 | } |
| @@ -159,9 +173,9 @@ | ||
| 159 | 173 | // For Operations which do not have a result, we consider a successful |
| 160 | 174 | // operation when the operation has completed without errors. |
| 161 | 175 | return $this->isDone() && !$this->hasErrors(); |
| 162 | 176 | } |
| 163 | - return !is_null($this->getResult()); | |
| 177 | + return !\is_null($this->getResult()); | |
| 164 | 178 | } |
| 165 | 179 | /** |
| 166 | 180 | * Check whether the operation failed. If the operation is not complete, or if the operation |
| 167 | 181 | * succeeded, return false. |
| @@ -205,9 +219,9 @@ | ||
| 205 | 219 | { |
| 206 | 220 | if ($this->isDone()) { |
| 207 | 221 | return \true; |
| 208 | 222 | } |
| 209 | - $pollSettings = array_merge($this->defaultPollSettings, $options); | |
| 223 | + $pollSettings = \array_merge($this->defaultPollSettings, $options); | |
| 210 | 224 | return $this->poll(function () { |
| 211 | 225 | $this->reload(); |
| 212 | 226 | return $this->isDone(); |
| 213 | 227 | }, $pollSettings); |
| @@ -220,16 +234,18 @@ | ||
| 220 | 234 | */ |
| 221 | 235 | public function reload() |
| 222 | 236 | { |
| 223 | 237 | if ($this->deleted) { |
| 224 | - throw new ValidationException("Cannot call reload() on a deleted operation"); | |
| 238 | + throw new ValidationException('Cannot call reload() on a deleted operation'); | |
| 225 | 239 | } |
| 226 | - $this->lastProtoResponse = $this->operationsCall($this->getOperationMethod, $this->getName(), $this->additionalArgs); | |
| 240 | + $requestClass = $this->isNewSurfaceOperationsClient() ? $this->getOperationRequest : null; | |
| 241 | + $this->lastProtoResponse = $this->operationsCall($this->getOperationMethod, $requestClass); | |
| 227 | 242 | } |
| 228 | 243 | /** |
| 229 | - * Return the result of the operation. If operationSucceeded() is false, return null. | |
| 244 | + * Return the result of the operation. If operationSucceeded() is false, | |
| 245 | + * return null. | |
| 230 | 246 | * |
| 231 | - * @return mixed|null The result of the operation, or null if operationSucceeded() is false | |
| 247 | + * @return T|null | |
| 232 | 248 | */ |
| 233 | 249 | public function getResult() |
| 234 | 250 | { |
| 235 | 251 | if (!$this->hasProtoResponse()) { |
| @@ -242,12 +258,12 @@ | ||
| 242 | 258 | return null; |
| 243 | 259 | } |
| 244 | 260 | /** @var Any|null $anyResponse */ |
| 245 | 261 | $anyResponse = $this->lastProtoResponse->getResponse(); |
| 246 | - if (is_null($anyResponse)) { | |
| 262 | + if (\is_null($anyResponse)) { | |
| 247 | 263 | return null; |
| 248 | 264 | } |
| 249 | - if (is_null($this->operationReturnType)) { | |
| 265 | + if (\is_null($this->operationReturnType)) { | |
| 250 | 266 | return $anyResponse; |
| 251 | 267 | } |
| 252 | 268 | $operationReturnType = $this->operationReturnType; |
| 253 | 269 | /** @var Message $response */ |
| @@ -266,13 +282,13 @@ | ||
| 266 | 282 | if (!$this->hasProtoResponse() || !$this->isDone()) { |
| 267 | 283 | return null; |
| 268 | 284 | } |
| 269 | 285 | if ($this->operationErrorCodeMethod || $this->operationErrorMessageMethod) { |
| 270 | - $errorCode = $this->operationErrorCodeMethod ? call_user_func([$this->lastProtoResponse, $this->operationErrorCodeMethod]) : null; | |
| 271 | - $errorMessage = $this->operationErrorMessageMethod ? call_user_func([$this->lastProtoResponse, $this->operationErrorMessageMethod]) : null; | |
| 286 | + $errorCode = $this->operationErrorCodeMethod ? \call_user_func([$this->lastProtoResponse, $this->operationErrorCodeMethod]) : null; | |
| 287 | + $errorMessage = $this->operationErrorMessageMethod ? \call_user_func([$this->lastProtoResponse, $this->operationErrorMessageMethod]) : null; | |
| 272 | 288 | return (new Status())->setCode(ApiStatus::rpcCodeFromHttpStatusCode($errorCode))->setMessage($errorMessage); |
| 273 | 289 | } |
| 274 | - if (method_exists($this->lastProtoResponse, 'getError')) { | |
| 290 | + if (\method_exists($this->lastProtoResponse, 'getError')) { | |
| 275 | 291 | return $this->lastProtoResponse->getError(); |
| 276 | 292 | } |
| 277 | 293 | return null; |
| 278 | 294 | } |
| @@ -321,12 +337,13 @@ | ||
| 321 | 337 | * @throws LogicException If the API call method has not been configured |
| 322 | 338 | */ |
| 323 | 339 | public function cancel() |
| 324 | 340 | { |
| 325 | - if (is_null($this->cancelOperationMethod)) { | |
| 341 | + if (\is_null($this->cancelOperationMethod)) { | |
| 326 | 342 | throw new LogicException('The cancel operation is not supported by this API'); |
| 327 | 343 | } |
| 328 | - $this->operationsCall($this->cancelOperationMethod, $this->getName(), $this->additionalArgs); | |
| 344 | + $requestClass = $this->isNewSurfaceOperationsClient() ? $this->cancelOperationRequest : null; | |
| 345 | + $this->operationsCall($this->cancelOperationMethod, $requestClass); | |
| 329 | 346 | } |
| 330 | 347 | /** |
| 331 | 348 | * Delete the long-running operation. |
| 332 | 349 | * |
| @@ -339,12 +356,13 @@ | ||
| 339 | 356 | * @throws LogicException If the API call method has not been configured |
| 340 | 357 | */ |
| 341 | 358 | public function delete() |
| 342 | 359 | { |
| 343 | - if (is_null($this->deleteOperationMethod)) { | |
| 360 | + if (\is_null($this->deleteOperationMethod)) { | |
| 344 | 361 | throw new LogicException('The delete operation is not supported by this API'); |
| 345 | 362 | } |
| 346 | - $this->operationsCall($this->deleteOperationMethod, $this->getName(), $this->additionalArgs); | |
| 363 | + $requestClass = $this->isNewSurfaceOperationsClient() ? $this->deleteOperationRequest : null; | |
| 364 | + $this->operationsCall($this->deleteOperationMethod, $requestClass); | |
| 347 | 365 | $this->deleted = \true; |
| 348 | 366 | } |
| 349 | 367 | /** |
| 350 | 368 | * Get the metadata returned with the last proto response. If a metadata type was provided, then |
| @@ -357,9 +375,9 @@ | ||
| 357 | 375 | { |
| 358 | 376 | if (!$this->hasProtoResponse()) { |
| 359 | 377 | return null; |
| 360 | 378 | } |
| 361 | - if (!method_exists($this->lastProtoResponse, 'getMetadata')) { | |
| 379 | + if (!\method_exists($this->lastProtoResponse, 'getMetadata')) { | |
| 362 | 380 | // The call to getMetadata is only for OnePlatform LROs, and is not |
| 363 | 381 | // supported by other LRO GAPIC clients (e.g. Compute) |
| 364 | 382 | return null; |
| 365 | 383 | } |
| @@ -364,16 +382,16 @@ | ||
| 364 | 382 | return null; |
| 365 | 383 | } |
| 366 | 384 | /** @var Any|null $any */ |
| 367 | 385 | $any = $this->lastProtoResponse->getMetadata(); |
| 368 | - if (is_null($this->metadataReturnType)) { | |
| 386 | + if (\is_null($this->metadataReturnType)) { | |
| 369 | 387 | return $any; |
| 370 | 388 | } |
| 371 | - if (is_null($any)) { | |
| 389 | + if (\is_null($any)) { | |
| 372 | 390 | return null; |
| 373 | 391 | } |
| 374 | 392 | // @TODO: This is probably not doing anything and can be removed in the next release. |
| 375 | - if (is_null($any->getValue())) { | |
| 393 | + if (\is_null($any->getValue())) { | |
| 376 | 394 | return null; |
| 377 | 395 | } |
| 378 | 396 | $metadataReturnType = $this->metadataReturnType; |
| 379 | 397 | /** @var Message $metadata */ |
| @@ -380,18 +398,38 @@ | ||
| 380 | 398 | $metadata = new $metadataReturnType(); |
| 381 | 399 | $metadata->mergeFromString($any->getValue()); |
| 382 | 400 | return $metadata; |
| 383 | 401 | } |
| 384 | - private function operationsCall($method, $name, array $additionalArgs) | |
| 402 | + /** | |
| 403 | + * Call the operations client to perform an operation. | |
| 404 | + * | |
| 405 | + * @param string $method The method to call on the operations client. | |
| 406 | + * @param string|null $requestClass The request class to use for the call. | |
| 407 | + * Will be null for legacy operations clients. | |
| 408 | + */ | |
| 409 | + private function operationsCall(string $method, ?string $requestClass) | |
| 385 | 410 | { |
| 386 | - $args = array_merge([$name], $additionalArgs); | |
| 387 | - return call_user_func_array([$this->operationsClient, $method], $args); | |
| 411 | + // V1 GAPIC clients have an empty $requestClass | |
| 412 | + if (empty($requestClass)) { | |
| 413 | + if ($this->additionalArgs) { | |
| 414 | + return $this->operationsClient->{$method}($this->getName(), ...\array_values($this->additionalArgs)); | |
| 415 | + } | |
| 416 | + return $this->operationsClient->{$method}($this->getName()); | |
| 417 | + } | |
| 418 | + if (!\method_exists($requestClass, 'build')) { | |
| 419 | + throw new LogicException('Request class must support the static build method'); | |
| 420 | + } | |
| 421 | + // In V2 of Compute, the Request "build" methods contain the operation ID last instead | |
| 422 | + // of first. Compute is the only API which uses $additionalArgs, so switching the order | |
| 423 | + // will not break anything. | |
| 424 | + $request = $requestClass::build(...\array_merge(\array_values($this->additionalArgs), [$this->getName()])); | |
| 425 | + return $this->operationsClient->{$method}($request); | |
| 388 | 426 | } |
| 389 | 427 | private function canHaveResult() |
| 390 | 428 | { |
| 391 | 429 | // The call to getResponse is only for OnePlatform LROs, and is not |
| 392 | 430 | // supported by other LRO GAPIC clients (e.g. Compute) |
| 393 | - return method_exists($this->lastProtoResponse, 'getResponse'); | |
| 431 | + return \method_exists($this->lastProtoResponse, 'getResponse'); | |
| 394 | 432 | } |
| 395 | 433 | private function hasErrors() |
| 396 | 434 | { |
| 397 | 435 | if (!$this->hasProtoResponse()) { |
| @@ -396,13 +434,13 @@ | ||
| 396 | 434 | { |
| 397 | 435 | if (!$this->hasProtoResponse()) { |
| 398 | 436 | return \false; |
| 399 | 437 | } |
| 400 | - if (method_exists($this->lastProtoResponse, 'getError')) { | |
| 438 | + if (\method_exists($this->lastProtoResponse, 'getError')) { | |
| 401 | 439 | return !empty($this->lastProtoResponse->getError()); |
| 402 | 440 | } |
| 403 | 441 | if ($this->operationErrorCodeMethod) { |
| 404 | - $errorCode = call_user_func([$this->lastProtoResponse, $this->operationErrorCodeMethod]); | |
| 442 | + $errorCode = \call_user_func([$this->lastProtoResponse, $this->operationErrorCodeMethod]); | |
| 405 | 443 | return !empty($errorCode); |
| 406 | 444 | } |
| 407 | 445 | // This should never happen unless an API is misconfigured |
| 408 | 446 | throw new LogicException('Unable to determine operation error status for this service'); |
| @@ -408,7 +446,11 @@ | ||
| 408 | 446 | throw new LogicException('Unable to determine operation error status for this service'); |
| 409 | 447 | } |
| 410 | 448 | private function hasProtoResponse() |
| 411 | 449 | { |
| 412 | - return !is_null($this->lastProtoResponse); | |
| 450 | + return !\is_null($this->lastProtoResponse); | |
| 451 | + } | |
| 452 | + private function isNewSurfaceOperationsClient() : bool | |
| 453 | + { | |
| 454 | + return !$this->operationsClient instanceof LegacyOperationsClient && \false !== \strpos(\get_class($this->operationsClient), self::NEW_CLIENT_NAMESPACE); | |
| 413 | 455 | } |
| 414 | 456 | } |