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

feat(Core): add RequestHandler and supporting classes #6871

Merged
merged 25 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
ef252d7
feat: Add request handler and a GapicRequestWrapper (#6807)
saranshdhingra Dec 13, 2023
f1cec73
Added tests for ApiHelpersTrait
saranshdhingra Dec 13, 2023
7a09351
Marked the classes as internal
saranshdhingra Dec 13, 2023
510b562
Added missed use statements
saranshdhingra Dec 13, 2023
739ac5c
Update RequestHandler to accept only GAPIC classes and not objects
saranshdhingra Dec 18, 2023
4e2fcb7
Fix lint issues
saranshdhingra Dec 19, 2023
3597b40
Addressed PR comments
saranshdhingra Jan 2, 2024
7b639be
Fixed Unit tests for the latest changes
saranshdhingra Jan 2, 2024
ec21e82
Fixed return type for constructGapic
saranshdhingra Jan 2, 2024
be3a5b0
Removed setSerialzer from RequestHandler
saranshdhingra Jan 2, 2024
8eef4dd
Removed mixed type declerations
saranshdhingra Jan 2, 2024
33fd1ec
Removed mixed types from argument declerations
saranshdhingra Jan 2, 2024
7e32839
Merged RequestHandler and RequestCallerTrait
saranshdhingra Jan 3, 2024
4a9c090
Removed incompatible changes in ApiHelpersTrait
saranshdhingra Jan 8, 2024
4a9d03c
Removed getSerializer from RequestHandler
saranshdhingra Jan 8, 2024
d7a1c85
Removed trailing comas
saranshdhingra Jan 8, 2024
04ed254
Merged RequestHandler and GapicRequestWrapper
saranshdhingra Jan 16, 2024
a046bb6
Fixed tests
saranshdhingra Jan 16, 2024
85a088a
Fixed segmentation faults in tests with protobuf enabled
saranshdhingra Jan 22, 2024
c72ae30
Removed calls to reveal() in RequestHandler
saranshdhingra Jan 22, 2024
c394634
Merge branch 'main' into add-request-handler
saranshdhingra Jan 22, 2024
4147a9d
Added client related changes
saranshdhingra Jan 24, 2024
265fbc0
Updated version for gax in Core
saranshdhingra Jan 24, 2024
4806e22
Addressed PR comments
saranshdhingra Jan 26, 2024
8aaa1da
Marked the RequestProcessorTrait as internal
saranshdhingra Jan 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 1 addition & 122 deletions Core/src/GrpcRequestWrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,16 @@
use Google\Auth\HttpHandler\HttpHandlerFactory;
use Google\Cloud\Core\Exception;
use Google\ApiCore\ApiException;
use Google\ApiCore\OperationResponse;
use Google\ApiCore\PagedListResponse;
use Google\ApiCore\Serializer;
use Google\ApiCore\ServerStream;
use Google\Protobuf\Internal\Message;
use Google\Rpc\BadRequest;
use Google\Rpc\Code;
use Google\Rpc\RetryInfo;

/**
* The GrpcRequestWrapper is responsible for delivering gRPC requests.
*/
class GrpcRequestWrapper
{
use RequestWrapperTrait;
use RequestProcessorTrait;

/**
* @var callable A handler used to deliver Psr7 requests specifically for
Expand Down Expand Up @@ -63,14 +58,6 @@ class GrpcRequestWrapper
Code::DATA_LOSS
];

/**
* @var array Map of error metadata types to RPC wrappers.
*/
private $metadataTypes = [
'google.rpc.retryinfo-bin' => RetryInfo::class,
'google.rpc.badrequest-bin' => BadRequest::class
];

/**
* @param array $config [optional] {
* Configuration options. Please see
Expand Down Expand Up @@ -154,112 +141,4 @@ public function send(callable $request, array $args, array $options = [])
throw $ex;
}
}

/**
* Serializes a gRPC response.
*
* @param mixed $response
* @return \Generator|OperationResponse|array|null
*/
private function handleResponse($response)
{
if ($response instanceof PagedListResponse) {
$response = $response->getPage()->getResponseObject();
}

if ($response instanceof Message) {
return $this->serializer->encodeMessage($response);
}

if ($response instanceof OperationResponse) {
return $response;
}

if ($response instanceof ServerStream) {
return $this->handleStream($response);
}

return null;
}

/**
* Handles a streaming response.
*
* @param ServerStream $response
* @return \Generator|array|null
* @throws Exception\ServiceException
*/
private function handleStream($response)
{
try {
foreach ($response->readAll() as $count => $result) {
$res = $this->serializer->encodeMessage($result);
yield $res;
}
} catch (\Exception $ex) {
throw $this->convertToGoogleException($ex);
}
}

/**
* Convert a ApiCore exception to a Google Exception.
*
* @param \Exception $ex
* @return Exception\ServiceException
*/
private function convertToGoogleException($ex)
{
switch ($ex->getCode()) {
case Code::INVALID_ARGUMENT:
$exception = Exception\BadRequestException::class;
break;

case Code::NOT_FOUND:
case Code::UNIMPLEMENTED:
$exception = Exception\NotFoundException::class;
break;

case Code::ALREADY_EXISTS:
$exception = Exception\ConflictException::class;
break;

case Code::FAILED_PRECONDITION:
$exception = Exception\FailedPreconditionException::class;
break;

case Code::UNKNOWN:
$exception = Exception\ServerException::class;
break;

case Code::INTERNAL:
$exception = Exception\ServerException::class;
break;

case Code::ABORTED:
$exception = Exception\AbortedException::class;
break;

case Code::DEADLINE_EXCEEDED:
$exception = Exception\DeadlineExceededException::class;
break;

default:
$exception = Exception\ServiceException::class;
break;
}

$metadata = [];
if ($ex->getMetadata()) {
foreach ($ex->getMetadata() as $type => $binaryValue) {
if (!isset($this->metadataTypes[$type])) {
continue;
}
$metadataElement = new $this->metadataTypes[$type];
$metadataElement->mergeFromString($binaryValue[0]);
$metadata[] = $this->serializer->encodeMessage($metadataElement);
}
}

return new $exception($ex->getMessage(), $ex->getCode(), $ex, $metadata);
}
}
135 changes: 1 addition & 134 deletions Core/src/RequestHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,8 @@
use Google\Cloud\Core\TimeTrait;
use Google\Cloud\Core\WhitelistTrait;
use \Google\Protobuf\Internal\Message;
use Google\ApiCore\ServerStream;
use Google\Rpc\BadRequest;
use Google\Rpc\Code;
use Google\Rpc\RetryInfo;
use Google\ApiCore\ApiException;
use Google\ApiCore\OperationResponse;
use Google\ApiCore\PagedListResponse;

/**
* @internal
Expand All @@ -43,20 +38,13 @@ class RequestHandler
use ArrayTrait;
use TimeTrait;
use WhitelistTrait;
use RequestProcessorTrait;

/**
* @var Serializer
*/
private Serializer $serializer;

/**
* @var array Map of error metadata types to RPC wrappers.
*/
private array $metadataTypes = [
'google.rpc.retryinfo-bin' => RetryInfo::class,
'google.rpc.badrequest-bin' => BadRequest::class
];

private array $clients;

/**
Expand All @@ -77,7 +65,6 @@ public function __construct(
// gccl needs to be present for handwritten clients
$clientConfig += [
'libName' => 'gccl',
'transport' => $this->getDefaultTransport(),
'emulatorHost' => null
];

Expand Down Expand Up @@ -142,114 +129,6 @@ public function sendRequest(
}
}

/**
* Serializes a gRPC response.
*
* @param mixed $response
* @return \Generator|OperationResponse|array|null
*/
private function handleResponse($response)
{
if ($response instanceof PagedListResponse) {
$response = $response->getPage()->getResponseObject();
}

if ($response instanceof Message) {
return $this->serializer->encodeMessage($response);
}

if ($response instanceof OperationResponse) {
return $response;
}

if ($response instanceof ServerStream) {
return $this->handleStream($response);
}

return null;
}

/**
* Handles a streaming response.
*
* @param ServerStream $response
* @return \Generator|array|null
* @throws Exception\ServiceException
*/
private function handleStream(ServerStream $response)
{
try {
foreach ($response->readAll() as $count => $result) {
$res = $this->serializer->encodeMessage($result);
yield $res;
}
} catch (\Exception $ex) {
throw $this->convertToGoogleException($ex);
}
}

/**
* Convert a ApiCore exception to a Google Exception.
*
* @param \Exception $ex
* @return ServiceException
*/
private function convertToGoogleException(\Exception $ex): ServiceException
{
switch ($ex->getCode()) {
case Code::INVALID_ARGUMENT:
$exception = Exception\BadRequestException::class;
break;

case Code::NOT_FOUND:
case Code::UNIMPLEMENTED:
$exception = Exception\NotFoundException::class;
break;

case Code::ALREADY_EXISTS:
$exception = Exception\ConflictException::class;
break;

case Code::FAILED_PRECONDITION:
$exception = Exception\FailedPreconditionException::class;
break;

case Code::UNKNOWN:
$exception = Exception\ServerException::class;
break;

case Code::INTERNAL:
$exception = Exception\ServerException::class;
break;

case Code::ABORTED:
$exception = Exception\AbortedException::class;
break;

case Code::DEADLINE_EXCEEDED:
$exception = Exception\DeadlineExceededException::class;
break;

default:
$exception = Exception\ServiceException::class;
break;
}

$metadata = [];
if (method_exists($ex, 'getMetadata') && $ex->getMetadata()) {
foreach ($ex->getMetadata() as $type => $binaryValue) {
if (!isset($this->metadataTypes[$type])) {
continue;
}
$metadataElement = new $this->metadataTypes[$type];
$metadataElement->mergeFromString($binaryValue[0]);
$metadata[] = $this->serializer->encodeMessage($metadataElement);
}
}

return new $exception($ex->getMessage(), $ex->getCode(), $ex, $metadata);
}

/**
* Helper function that returns a client object stored in memory
* using the client class as key.
Expand All @@ -260,16 +139,4 @@ private function getClientObject(string $clientClass)
{
return $this->clients[$clientClass] ?? null;
}

private function getDefaultTransport() : string
{
$isGrpcExtensionLoaded = $this->isGrpcLoaded();
$defaultTransport = $isGrpcExtensionLoaded ? 'grpc' : 'rest';
return $defaultTransport;
}

private function isGrpcLoaded() : bool
{
return extension_loaded('grpc');
}
}
Loading
Loading