Skip to content

Commit

Permalink
Fix gRPC scopes, add unit test
Browse files Browse the repository at this point in the history
  • Loading branch information
msmakouz committed Mar 4, 2024
1 parent dcc20e8 commit 51fe8d5
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 13 deletions.
7 changes: 3 additions & 4 deletions src/Bootloader/GRPCBootloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
use Spiral\Boot\KernelInterface;
use Spiral\Config\ConfiguratorInterface;
use Spiral\Config\Patch\Append;
use Spiral\Core\Attribute\Proxy;
use Spiral\Core\Container\Autowire;
use Spiral\Core\CoreInterceptorInterface;
use Spiral\Core\FactoryInterface;
use Spiral\Core\InterceptableCore;
use Spiral\Core\ScopeInterface;
use Spiral\RoadRunner\GRPC\Invoker as BaseInvoker;
use Spiral\RoadRunner\GRPC\InvokerInterface;
use Spiral\RoadRunner\GRPC\Server;
Expand Down Expand Up @@ -112,10 +112,9 @@ public function addGenerator(string|GeneratorInterface|Autowire $generator): voi

private function initInvoker(
GRPCConfig $config,
ContainerInterface $container,
#[Proxy] ContainerInterface $container,
FactoryInterface $factory,
BaseInvoker $invoker,
ScopeInterface $scope,
): InvokerInterface {
$core = new InterceptableCore(
new InvokerCore($invoker),
Expand All @@ -129,7 +128,7 @@ private function initInvoker(
$core->addInterceptor($interceptor);
}

return new Invoker($core, $scope);
return new Invoker($core, $container);
}

private function initProtoFilesRepository(GRPCConfig $config): ProtoFilesRepositoryInterface
Expand Down
6 changes: 4 additions & 2 deletions src/GRPC/Interceptor/Invoker.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Spiral\RoadRunnerBridge\GRPC\Interceptor;

use Google\Protobuf\Internal\Message;
use Psr\Container\ContainerInterface;
use Spiral\Core\CoreInterface;
use Spiral\Core\Scope;
use Spiral\Core\ScopeInterface;
Expand All @@ -24,16 +25,17 @@ final class Invoker implements InvokerInterface
{
public function __construct(
private readonly CoreInterface $core,
private readonly ScopeInterface $scope,
private readonly ContainerInterface $container,
) {
}

public function invoke(ServiceInterface $service, Method $method, ContextInterface $ctx, ?string $input): string
{
$message = $this->makeInput($method, $input);
$scope = $this->container->get(ScopeInterface::class);

/** @psalm-suppress InvalidArgument */
return $this->scope->runScope(
return $scope->runScope(
new Scope('grpc.request', [UnaryCallInterface::class => new UnaryCall($ctx, $method, $message)]),
fn (): string => $this->core->callAction($service::class, $method->name, [
'service' => $service,
Expand Down
23 changes: 16 additions & 7 deletions src/GRPC/ServiceLocator.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
namespace Spiral\RoadRunnerBridge\GRPC;

use Psr\Container\ContainerInterface;
use Spiral\Core\BinderInterface;
use Spiral\Core\Attribute\Proxy as ProxyAttribute;
use Spiral\Core\Config\Proxy;
use Spiral\Core\Exception\Container\ContainerException;
use Spiral\RoadRunner\GRPC\ServiceInterface;
use Spiral\Tokenizer\ClassesInterface;
Expand All @@ -13,7 +16,8 @@ final class ServiceLocator implements LocatorInterface
{
public function __construct(
private readonly ClassesInterface $classes,
private readonly ContainerInterface $container
#[ProxyAttribute] private readonly ContainerInterface $container,
private readonly BinderInterface $binder,
) {
}

Expand All @@ -26,14 +30,19 @@ public function getServices(): array
continue;
}

try {
$instance = $this->container->get($service->getName());
} catch (ContainerException) {
continue;
}

foreach ($service->getInterfaces() as $interface) {
if ($interface->isSubclassOf(ServiceInterface::class)) {
$grpcRequest = $this->binder->getBinder('grpc.request');
$grpcRequest->bind($interface->getName(), $service->getName());
$grpcRequest->bind($service->getName(), $service->getName());
$this->binder->bind($interface->getName(), new Proxy($interface->getName()));

try {
$instance = $this->container->get($interface->getName());
} catch (ContainerException) {
continue;
}

$result[$interface->getName()] = $instance;
}
}
Expand Down
10 changes: 10 additions & 0 deletions tests/app/config/tokenizer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

return [
'directories' => [
\dirname(__DIR__, 2) . '/app',
\dirname(__DIR__, 2) . '/generated',
]
];
13 changes: 13 additions & 0 deletions tests/generated/Service/PingService.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,25 @@

namespace Service;

use Psr\Container\ContainerInterface;
use Spiral\Core\Attribute\Scope;
use Spiral\Core\Internal\Introspector;
use Spiral\RoadRunner\GRPC\ContextInterface;

#[Scope('grpc.request')]
class PingService implements PingInterface
{
public static array $scopes = [];

public function __construct(
private readonly ContainerInterface $container,
) {
}

public function Ping(ContextInterface $ctx, Message $in): Message
{
self::$scopes = Introspector::scopeNames($this->container);

$out = new Message();

return $out->setMsg('PONG');
Expand Down
30 changes: 30 additions & 0 deletions tests/src/GRPC/DispatcherTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Spiral\Tests\GRPC;

use Service\PingService;
use Spiral\App\GRPC\EchoService\Message;
use Spiral\Boot\FinalizerInterface;
use Spiral\RoadRunner\Payload;
Expand Down Expand Up @@ -57,6 +58,35 @@ public function testServe(): void
$this->serveDispatcher(Dispatcher::class);
}

public function testGrpcScope(): void
{
$this->assertEquals([], PingService::$scopes);

$worker = $this->mockContainer(WorkerInterface::class, Worker::class);
$this->getContainer()->bind(RoadRunnerMode::class, RoadRunnerMode::Grpc);

$finalizer = $this->mockContainer(FinalizerInterface::class);
$finalizer->shouldReceive('finalize')->once()->with(false);

$worker->shouldReceive('waitPayload')->once()->andReturn(
new Payload(
(new \Service\Message())->setMsg('PING')->serializeToString(),
json_encode(['service' => 'service.Ping', 'method' => 'Ping', 'context' => []])
)
);

$worker->shouldReceive('respond')->once()->withArgs(function (Payload $payload) {
$this->assertSame($payload->body, (new \Service\Message())->setMsg('PONG')->serializeToString());
return true;
});

$worker->shouldReceive('waitPayload')->once()->with()->andReturnNull();

$this->getApp()->serve();

$this->assertEquals(['grpc.request', 'grpc', 'root'], PingService::$scopes);
}

protected function tearDown(): void
{
parent::tearDown();
Expand Down

0 comments on commit 51fe8d5

Please sign in to comment.