Skip to content

Commit

Permalink
Support reverb as a broadcasting driver
Browse files Browse the repository at this point in the history
  • Loading branch information
spawnia committed Dec 9, 2024
1 parent a74f08c commit 05df6f2
Show file tree
Hide file tree
Showing 15 changed files with 92 additions and 86 deletions.
6 changes: 3 additions & 3 deletions benchmarks/QueryBench.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ public function setUp(): void
{
parent::setUp();

$configRepository = $this->app->make(ConfigRepository::class);
assert($configRepository instanceof ConfigRepository);
$config = $this->app->make(ConfigRepository::class);
assert($config instanceof ConfigRepository);

$routeName = $configRepository->get('lighthouse.route.name');
$routeName = $config->get('lighthouse.route.name');
$this->graphQLEndpoint = route($routeName);
}

Expand Down
3 changes: 1 addition & 2 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,8 @@ parameters:
message: '#Call to method version\(\) on an unknown class Laravel\\Lumen\\Application.#'
- path: src/Subscriptions/SubscriptionRouter.php
messages:
- '#Parameter \$router of method Nuwave\\Lighthouse\\Subscriptions\\SubscriptionRouter::pusher\(\) has invalid type Laravel\\Lumen\\Routing\\Router\.#'
- '#Parameter \$router of method Nuwave\\Lighthouse\\Subscriptions\\SubscriptionRouter::.+\(\) has invalid type Laravel\\Lumen\\Routing\\Router\.#'
- '#Call to method post\(\) on an unknown class Laravel\\Lumen\\Routing\\Router\.#'
- '#Parameter \$router of method Nuwave\\Lighthouse\\Subscriptions\\SubscriptionRouter::echoRoutes\(\) has invalid type Laravel\\Lumen\\Routing\\Router\.#'
- path: src/Http/routes.php
messages:
- '#PHPDoc tag @var for variable \$router contains unknown class Laravel\\Lumen\\Routing\\Router\.#'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* @method \Symfony\Component\HttpFoundation\Response authorized(\Illuminate\Http\Request $request)
* @method \Symfony\Component\HttpFoundation\Response unauthorized(\Illuminate\Http\Request $request)
*/
class BroadcastManager extends DriverManager
class BroadcastDriverManager extends DriverManager
{
protected function configKey(): string
{
Expand All @@ -38,11 +38,9 @@ protected function interface(): string
protected function createPusherDriver(array $config): PusherBroadcaster
{
$connection = $config['connection'] ?? 'pusher';
$driverConfig = config("broadcasting.connections.{$connection}");

if (empty($driverConfig) || $driverConfig['driver'] !== 'pusher') {
throw new \RuntimeException("Could not initialize Pusher broadcast driver for connection: {$connection}.");
}
$driverConfig = config("broadcasting.connections.{$connection}")
?? throw new \RuntimeException("Missing connection {$connection} from config/broadcasting.php.");

$pusher = new Pusher(
$driverConfig['key'],
Expand Down
8 changes: 4 additions & 4 deletions src/Subscriptions/SubscriptionBroadcaster.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public function __construct(
protected AuthorizesSubscriptions $subscriptionAuthorizer,
protected StoresSubscriptions $subscriptionStorage,
protected SubscriptionIterator $subscriptionIterator,
protected BroadcastManager $broadcastManager,
protected BroadcastDriverManager $broadcastDriverManager,
protected BusDispatcher $busDispatcher,
) {}

Expand Down Expand Up @@ -50,15 +50,15 @@ function (Subscriber $subscriber) use ($root): void {
$subscriber->variables,
$subscriber,
);
$this->broadcastManager->broadcast($subscriber, $result);
$this->broadcastDriverManager->broadcast($subscriber, $result);
},
);
}

public function authorize(Request $request): Response
{
return $this->subscriptionAuthorizer->authorize($request)
? $this->broadcastManager->authorized($request)
: $this->broadcastManager->unauthorized($request);
? $this->broadcastDriverManager->authorized($request)
: $this->broadcastDriverManager->unauthorized($request);
}
}
4 changes: 2 additions & 2 deletions src/Subscriptions/SubscriptionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ public function authorize(Request $request, BroadcastsSubscriptions $broadcaster
return $broadcaster->authorize($request);
}

public function webhook(Request $request, BroadcastManager $broadcastManager): Response
public function webhook(Request $request, BroadcastDriverManager $broadcastDriverManager): Response
{
return $broadcastManager->hook($request);
return $broadcastDriverManager->hook($request);
}
}
12 changes: 11 additions & 1 deletion src/Subscriptions/SubscriptionRouter.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

class SubscriptionRouter
{
/** Register the routes for pusher based subscriptions. */
/** Register the routes for Pusher based subscriptions. */
public function pusher(Registrar|Router $router): void
{
$router->post('graphql/subscriptions/auth', [
Expand All @@ -21,6 +21,16 @@ public function pusher(Registrar|Router $router): void
]);
}

/** Register the routes for Laravel Reverb based subscriptions. */
public function reverb(Registrar|Router $router): void
{
$router->post('graphql/subscriptions/auth', [
'as' => 'lighthouse.subscriptions.auth',
'uses' => SubscriptionController::class . '@authorize',
]);
}

/** Register the routes for Laravel Echo based subscriptions. */
public function echoRoutes(Registrar|Router $router): void
{
$router->post('graphql/subscriptions/auth', [
Expand Down
2 changes: 1 addition & 1 deletion src/Subscriptions/SubscriptionServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class SubscriptionServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->singleton(BroadcastManager::class);
$this->app->singleton(BroadcastDriverManager::class);
$this->app->singleton(SubscriptionRegistry::class);
$this->app->singleton(StoresSubscriptions::class, static function (Container $app): StoresSubscriptions {
$configRepository = $app->make(ConfigRepository::class);
Expand Down
8 changes: 4 additions & 4 deletions src/Testing/MakesGraphQLRequests.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
use Illuminate\Support\Arr;
use Illuminate\Testing\TestResponse;
use Nuwave\Lighthouse\Http\Responses\MemoryStream;
use Nuwave\Lighthouse\Subscriptions\BroadcastDriverManager;
use Nuwave\Lighthouse\Subscriptions\Broadcasters\LogBroadcaster;
use Nuwave\Lighthouse\Subscriptions\BroadcastManager;
use Nuwave\Lighthouse\Subscriptions\Contracts\Broadcaster;
use Nuwave\Lighthouse\Support\Contracts\CanStreamResponse;
use PHPUnit\Framework\Assert;
Expand Down Expand Up @@ -246,11 +246,11 @@ protected function setUpSubscriptionEnvironment(): void
$config->get('lighthouse.subscriptions.broadcasters.log'),
));

$broadcastManager = $app->make(BroadcastManager::class);
assert($broadcastManager instanceof BroadcastManager);
$broadcastDriverManager = $app->make(BroadcastDriverManager::class);
assert($broadcastDriverManager instanceof BroadcastDriverManager);

// adding a custom driver which is a spied version of log driver
$broadcastManager->extend('mock', fn () => $this->spy(LogBroadcaster::class)->makePartial());
$broadcastDriverManager->extend('mock', fn () => $this->spy(LogBroadcaster::class)->makePartial());

// set the custom driver as the default driver
$config->set('lighthouse.subscriptions.broadcaster', 'mock');
Expand Down
8 changes: 4 additions & 4 deletions src/Testing/MakesGraphQLRequestsLumen.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
use Illuminate\Support\Arr;
use Illuminate\Testing\TestResponse;
use Nuwave\Lighthouse\Http\Responses\MemoryStream;
use Nuwave\Lighthouse\Subscriptions\BroadcastDriverManager;
use Nuwave\Lighthouse\Subscriptions\Broadcasters\LogBroadcaster;
use Nuwave\Lighthouse\Subscriptions\BroadcastManager;
use Nuwave\Lighthouse\Subscriptions\Contracts\Broadcaster;
use Nuwave\Lighthouse\Support\Contracts\CanStreamResponse;
use PHPUnit\Framework\Assert;
Expand Down Expand Up @@ -265,11 +265,11 @@ protected function setUpSubscriptionEnvironment(): void
$config->get('lighthouse.subscriptions.broadcasters.log'),
));

$broadcastManager = $app->make(BroadcastManager::class);
assert($broadcastManager instanceof BroadcastManager);
$broadcastDriverManager = $app->make(BroadcastDriverManager::class);
assert($broadcastDriverManager instanceof BroadcastDriverManager);

// adding a custom driver which is a spied version of log driver
$broadcastManager->extend('mock', fn () => $this->spy(LogBroadcaster::class)->makePartial());
$broadcastDriverManager->extend('mock', fn () => $this->spy(LogBroadcaster::class)->makePartial());

// set the custom driver as the default driver
$config->set('lighthouse.subscriptions.broadcaster', 'mock');
Expand Down
17 changes: 8 additions & 9 deletions src/Testing/TestResponseMixin.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@
use Illuminate\Testing\TestResponse;
use Mockery\LegacyMockInterface;
use Mockery\MockInterface;
use Nuwave\Lighthouse\Subscriptions\BroadcastManager;
use Nuwave\Lighthouse\Subscriptions\BroadcastDriverManager;
use Nuwave\Lighthouse\Subscriptions\Contracts\Broadcaster;
use Nuwave\Lighthouse\Subscriptions\Subscriber;
use PHPUnit\Framework\Assert;
use PHPUnit\Framework\TestCase;

/**
* @mixin \Illuminate\Testing\TestResponse
*/
/** @mixin \Illuminate\Testing\TestResponse */
class TestResponseMixin
{
public function assertGraphQLValidationError(): \Closure
Expand Down Expand Up @@ -155,12 +153,13 @@ public function assertGraphQLSubscriptionNotAuthorized(): \Closure
public function graphQLSubscriptionMock(): \Closure
{
return function (): MockInterface {
$broadcastManager = Container::getInstance()->make(BroadcastManager::class);
assert($broadcastManager instanceof BroadcastManager);
$mock = $broadcastManager->driver();
assert($mock instanceof Broadcaster && $mock instanceof MockInterface);
$broadcastDriverManager = Container::getInstance()->make(BroadcastDriverManager::class);
assert($broadcastDriverManager instanceof BroadcastDriverManager);

return $mock;
$broadcastDriver = $broadcastDriverManager->driver();
assert($broadcastDriver instanceof Broadcaster && $broadcastDriver instanceof MockInterface);

return $broadcastDriver;
};
}

Expand Down
12 changes: 5 additions & 7 deletions src/Testing/TestsSubscriptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@

use Illuminate\Container\Container;
use Illuminate\Contracts\Config\Repository as ConfigRepository;
use Nuwave\Lighthouse\Subscriptions\BroadcastDriverManager;
use Nuwave\Lighthouse\Subscriptions\Broadcasters\LogBroadcaster;
use Nuwave\Lighthouse\Subscriptions\BroadcastManager;
use Nuwave\Lighthouse\Subscriptions\Contracts\Broadcaster;

/**
* Sets up the environment for testing subscriptions.
*/
/** Sets up the environment for testing subscriptions. */
trait TestsSubscriptions
{
protected function setUpTestsSubscriptions(): void
Expand All @@ -27,11 +25,11 @@ protected function setUpTestsSubscriptions(): void
$config->get('lighthouse.subscriptions.broadcasters.log'),
));

$broadcastManager = $app->make(BroadcastManager::class);
assert($broadcastManager instanceof BroadcastManager);
$broadcastDriverManager = $app->make(BroadcastDriverManager::class);
assert($broadcastDriverManager instanceof BroadcastDriverManager);

// adding a custom driver which is a spied version of log driver
$broadcastManager->extend('mock', fn () => $this->spy(LogBroadcaster::class)->makePartial());
$broadcastDriverManager->extend('mock', fn () => $this->spy(LogBroadcaster::class)->makePartial());

// set the custom driver as the default driver
$config->set('lighthouse.subscriptions.broadcaster', 'mock');
Expand Down
15 changes: 10 additions & 5 deletions src/lighthouse.php
Original file line number Diff line number Diff line change
Expand Up @@ -435,16 +435,21 @@
'log' => [
'driver' => 'log',
],
'pusher' => [
'driver' => 'pusher',
'routes' => Nuwave\Lighthouse\Subscriptions\SubscriptionRouter::class . '@pusher',
'connection' => 'pusher',
],
'echo' => [
'driver' => 'echo',
'connection' => env('LIGHTHOUSE_SUBSCRIPTION_REDIS_CONNECTION', 'default'),
'routes' => Nuwave\Lighthouse\Subscriptions\SubscriptionRouter::class . '@echoRoutes',
],
'pusher' => [
'driver' => 'pusher',
'connection' => 'pusher',
'routes' => Nuwave\Lighthouse\Subscriptions\SubscriptionRouter::class . '@pusher',
],
'reverb' => [
'driver' => 'pusher',
'connection' => 'reverb',
'routes' => Nuwave\Lighthouse\Subscriptions\SubscriptionRouter::class . '@reverb',
],
],

/*
Expand Down
48 changes: 22 additions & 26 deletions tests/Integration/Subscriptions/SubscriptionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
use Illuminate\Support\Arr;
use Illuminate\Testing\TestResponse;
use Mockery\MockInterface;
use Nuwave\Lighthouse\Subscriptions\BroadcastDriverManager;
use Nuwave\Lighthouse\Subscriptions\Broadcasters\LogBroadcaster;
use Nuwave\Lighthouse\Subscriptions\BroadcastManager;
use Nuwave\Lighthouse\Subscriptions\Storage\CacheStorageManager;
use Nuwave\Lighthouse\Subscriptions\Subscriber;
use Nuwave\Lighthouse\Testing\TestsSubscriptions;
Expand Down Expand Up @@ -118,14 +118,14 @@ public function testBroadcastSubscriptions(): void
title
}
}
');
')->assertGraphQLErrorFree();

$broadcastManager = $this->app->make(BroadcastManager::class);
$broadcastDriverManager = $this->app->make(BroadcastDriverManager::class);

$log = $broadcastManager->driver();
assert($log instanceof LogBroadcaster);
$logDriver = $broadcastDriverManager->driver();
assert($logDriver instanceof LogBroadcaster);

$broadcasts = $log->broadcasts();
$broadcasts = $logDriver->broadcasts();

$this->assertNotNull($broadcasts);
/** @var array<mixed> $broadcasts */
Expand All @@ -144,10 +144,10 @@ public function testWithFieldAlias(): void
title
}
}
');
')->assertGraphQLErrorFree();

/** @var CacheStorageManager $cache */
$cache = $this->app->make(CacheStorageManager::class);
assert($cache instanceof CacheStorageManager);

$subscriber = $cache
->subscribersByTopic('ON_POST_CREATED')
Expand All @@ -169,18 +169,15 @@ public function testWithFieldAlias(): void
public function testWithoutExcludeEmpty(): void
{
$config = $this->app->make(ConfigRepository::class);

$config->set('lighthouse.subscriptions.exclude_empty', false);

$this->subscribe();

$response = $this->graphQL(/** @lang GraphQL */ '
query foo {
$this->graphQL(/** @lang GraphQL */ '
{
foo
}
');

$response->assertExactJson([
')->assertExactJson([
'data' => [
'foo' => '42',
],
Expand All @@ -199,13 +196,11 @@ public function testWithExcludeEmpty(): void

$this->subscribe();

$response = $this->graphQL(/** @lang GraphQL */ '
query foo {
$this->graphQL(/** @lang GraphQL */ '
{
foo
}
');

$response->assertExactJson([
')->assertExactJson([
'data' => [
'foo' => '42',
],
Expand All @@ -221,7 +216,7 @@ public function testWithGuard(): void
body
}
}
');
')->assertGraphQLErrorFree();

$authFactory = $this->app->make(AuthFactory::class);
$sessionGuard = $authFactory->guard();
Expand All @@ -234,10 +229,11 @@ public function testWithGuard(): void
title
}
}
');
')->assertGraphQLErrorFree();

$broadcastDriverManager = $this->app->make(BroadcastDriverManager::class);

$broadcastManager = $this->app->make(BroadcastManager::class);
$log = $broadcastManager->driver();
$log = $broadcastDriverManager->driver();
assert($log instanceof LogBroadcaster);

$broadcasts = $log->broadcasts();
Expand Down Expand Up @@ -281,7 +277,7 @@ public function testGraphQLBroadcastedEvents(): void
title
}
}
');
')->assertGraphQLErrorFree();

$response->assertGraphQLBroadcasted([
['title' => 'foo'],
Expand All @@ -298,15 +294,15 @@ public function testGraphQLBroadcastedEventsTwice(): void
title
}
}
');
')->assertGraphQLErrorFree();

$this->graphQL(/** @lang GraphQL */ '
mutation {
createPost(title: "baz", body: "boom") {
title
}
}
');
')->assertGraphQLErrorFree();

$response->assertGraphQLBroadcasted([
['title' => 'foo'],
Expand Down
Loading

0 comments on commit 05df6f2

Please sign in to comment.