Skip to content

Commit

Permalink
Merge pull request #13 from msmakouz/exceptions
Browse files Browse the repository at this point in the history
Returning errors via Google\Rpc\Status
  • Loading branch information
butschster authored Nov 10, 2022
2 parents 415bd1a + 8c8a9ef commit 41ddf6f
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 30 deletions.
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
"require": {
"php": ">=7.4",
"ext-json": "*",
"symfony/polyfill-php80": "^1.22",
"google/common-protos": "^3.1",
"google/protobuf": "^3.7",
"spiral/roadrunner": "^2.0"
"spiral/roadrunner": "^2.0",
"symfony/polyfill-php80": "^1.22"
},
"require-dev": {
"jetbrains/phpstorm-attributes": "^1.0",
Expand Down
46 changes: 21 additions & 25 deletions src/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace Spiral\RoadRunner\GRPC;

use Google\Protobuf\Any;
use Google\Rpc\Status;
use Spiral\RoadRunner\GRPC\Exception\GRPCException;
use Spiral\RoadRunner\GRPC\Exception\GRPCExceptionInterface;
use Spiral\RoadRunner\GRPC\Exception\NotFoundException;
Expand Down Expand Up @@ -148,7 +149,7 @@ public function serve(Worker $worker = null, callable $finalize = null): void

$this->workerSend($worker, $answerBody, $answerHeaders);
} catch (GRPCExceptionInterface $e) {
$this->workerError($worker, $this->packError($e));
$this->workerGrpcError($worker, $e);
} catch (\Throwable $e) {
$this->workerError($worker, $this->isDebugMode() ? (string)$e : $e->getMessage());
} finally {
Expand All @@ -171,37 +172,32 @@ public function serve(Worker $worker = null, callable $finalize = null): void
*/
protected function invoke(string $service, string $method, ContextInterface $context, string $body): string
{
if (! isset($this->services[$service])) {
if (!isset($this->services[$service])) {
throw NotFoundException::create("Service `{$service}` not found.", StatusCode::NOT_FOUND);
}

return $this->services[$service]->invoke($method, $context, $body);
}

/**
* Packs exception message and code into one string.
*
* Internal agreement:
*
* Details will be sent as serialized google.protobuf.Any messages after
* code and exception message separated with |:| delimiter.
*
* @param GRPCExceptionInterface $e
* @return string
*/
private function packError(GRPCExceptionInterface $e): string
private function workerGrpcError(Worker $worker, GRPCExceptionInterface $e): void
{
$data = [$e->getCode(), $e->getMessage()];

foreach ($e->getDetails() as $detail) {
$anyMessage = new Any();

$anyMessage->pack($detail);

$data[] = $anyMessage->serializeToString();
}

return \implode('|:|', $data);
$status = new Status([
'code' => $e->getCode(),
'message' => $e->getMessage(),
'details' => \array_map(
static function ($detail) {
$message = new Any();
$message->pack($detail);

return $message;
},
$e->getDetails()
),
]);

$this->workerSend($worker, '', Json::encode([
'error' => \base64_encode($status->serializeToString()),
]));
}

/**
Expand Down
10 changes: 7 additions & 3 deletions tests/ServerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use Service\TestInterface;
use Spiral\Goridge\Frame;
use Spiral\Goridge\RelayInterface;
use Spiral\GRPC\Server;
use Spiral\RoadRunner\GRPC\Server;
use Spiral\RoadRunner\GRPC\Tests\Stub\TestService;
use Spiral\RoadRunner\Worker;

Expand Down Expand Up @@ -67,7 +67,9 @@ public function testNotFound(): void
);

$relay->shouldReceive('send')->once()->withArgs(function (Frame $frame) {
return $frame->payload === '5|:|Service `service.Test2` not found.';
$error = base64_decode(json_decode($frame->payload, true)['error']);

return str_contains($error, 'Service `service.Test2` not found.');
});

$this->server->serve(
Expand All @@ -87,7 +89,9 @@ public function testNotFound2(): void
);

$relay->shouldReceive('send')->once()->withArgs(function (Frame $frame) {
return $frame->payload === '5|:|Method `Echo2` not found in service `service.Test`.';
$error = base64_decode(json_decode($frame->payload, true)['error']);

return str_contains($error, 'Method `Echo2` not found in service `service.Test`.');
});

$this->server->serve(
Expand Down

0 comments on commit 41ddf6f

Please sign in to comment.