From 0d81d406655ceb14eff8acbd3494e54083be18cd Mon Sep 17 00:00:00 2001 From: Joe Dixon Date: Tue, 21 Nov 2023 13:36:46 +0000 Subject: [PATCH] Removes connection manager (#20) * remove connection manager * formatting * remove channel manager * formatting * handle connection pings * wip --- src/Channels/Channel.php | 20 ++- src/ClientEvent.php | 2 +- src/Contracts/ChannelConnectionManager.php | 7 +- src/Contracts/ChannelManager.php | 7 +- src/Contracts/Connection.php | 10 +- src/Contracts/ConnectionManager.php | 61 --------- src/Contracts/ServerProvider.php | 5 - src/Jobs/PingInactiveConnections.php | 8 +- src/Jobs/PruneStaleConnections.php | 11 +- .../ArrayChannelConnectionManager.php | 16 ++- src/Managers/ArrayChannelManager.php | 12 ++ src/Managers/ArrayConnectionManager.php | 120 ------------------ src/Pusher/Http/Controllers/Controller.php | 10 -- .../Controllers/EventsBatchController.php | 2 +- .../Http/Controllers/EventsController.php | 2 +- .../Controllers/UsersTerminateController.php | 4 +- src/Servers/ApiGateway/ApiGatewayProvider.php | 10 -- src/Servers/ApiGateway/Server.php | 37 ++---- src/Servers/Reverb/Connection.php | 2 +- src/Servers/Reverb/Controller.php | 15 +-- src/Servers/Reverb/ReverbProvider.php | 10 -- src/ServiceProvider.php | 6 - .../Reverb/ChannelUsersControllerTest.php | 6 +- tests/Feature/Reverb/EventsControllerTest.php | 2 +- tests/Feature/Reverb/ServerTest.php | 42 +----- .../Reverb/UsersTerminateControllerTest.php | 12 +- tests/Pest.php | 15 +-- tests/ReverbTestCase.php | 23 ++-- tests/Unit/Channels/PresenceChannelTest.php | 8 +- tests/Unit/Channels/PrivateChannelTest.php | 2 +- .../Unit/Jobs/PingInactiveConnectionsTest.php | 16 +-- tests/Unit/Jobs/PruneStaleConnectionsTest.php | 17 +-- tests/Unit/Managers/ChannelManagerTest.php | 5 +- tests/Unit/Managers/ConnectionMangerTest.php | 59 --------- 34 files changed, 129 insertions(+), 455 deletions(-) delete mode 100644 src/Contracts/ConnectionManager.php delete mode 100644 src/Managers/ArrayConnectionManager.php delete mode 100644 tests/Unit/Managers/ConnectionMangerTest.php diff --git a/src/Channels/Channel.php b/src/Channels/Channel.php index a68883ce..962c2f3f 100644 --- a/src/Channels/Channel.php +++ b/src/Channels/Channel.php @@ -39,6 +39,22 @@ public function connections(): array return $this->connections->all(); } + /** + * Find a connection. + */ + public function find(Connection $connection): ?Connection + { + return $this->connections->find($connection); + } + + /** + * Find a connection by its ID. + */ + public function findById(string $id): ?Connection + { + return $this->connections->findById($id); + } + /** * Subscribe to the given channel. */ @@ -70,11 +86,11 @@ public function broadcast(Application $app, array $payload, Connection $except = { collect($this->connections()) ->each(function ($connection) use ($payload, $except) { - if ($except && $except->identifier() === $connection->connection()->identifier()) { + if ($except && $except->id() === $connection->connection()->id()) { return; } - if (isset($payload['except']) && $payload['except'] === $connection->connection()->identifier()) { + if (isset($payload['except']) && $payload['except'] === $connection->connection()->id()) { return; } diff --git a/src/ClientEvent.php b/src/ClientEvent.php index 52caebf5..f00f733d 100644 --- a/src/ClientEvent.php +++ b/src/ClientEvent.php @@ -33,7 +33,7 @@ public static function whisper(Connection $connection, array $payload): void { Event::dispatch( $connection->app(), - $payload + ['except' => $connection->identifier()], + $payload + ['except' => $connection->id()], $connection ); } diff --git a/src/Contracts/ChannelConnectionManager.php b/src/Contracts/ChannelConnectionManager.php index 8ea7baa5..70bbee7d 100644 --- a/src/Contracts/ChannelConnectionManager.php +++ b/src/Contracts/ChannelConnectionManager.php @@ -17,10 +17,15 @@ public function add(Connection $connection, array $data): void; public function remove(Connection $connection): void; /** - * Find a connection by its identifier. + * Find a connection in the set. */ public function find(Connection $connection): ?ChannelConnection; + /** + * Find a connection in the set by its ID. + */ + public function findById(string $id): ?ChannelConnection; + /** * Get all the connections. * diff --git a/src/Contracts/ChannelManager.php b/src/Contracts/ChannelManager.php index a3878593..32af8da2 100644 --- a/src/Contracts/ChannelManager.php +++ b/src/Contracts/ChannelManager.php @@ -24,10 +24,15 @@ public function for(Application $application): ChannelManager; public function all(): Collection; /** - * Find the given channel + * Find the given channel. */ public function find(string $channel): Channel; + /** + * Get all the connections for the given channels. + */ + public function connections(string $channel = null): Collection; + /** * Unsubscribe from all channels. */ diff --git a/src/Contracts/Connection.php b/src/Contracts/Connection.php index 97d38ce5..54a20648 100644 --- a/src/Contracts/Connection.php +++ b/src/Contracts/Connection.php @@ -13,7 +13,7 @@ abstract class Connection /** * The last time the connection was seen. */ - protected string $lastSeenAt; + protected ?string $lastSeenAt = null; /** * Stores the ping state of the connection. @@ -95,19 +95,15 @@ public function disconnect(): void ->for($this->app()) ->unsubscribeFromAll($this); - App::make(ConnectionManager::class) - ->for($this->app()) - ->disconnect($this->identifier()); - $this->terminate(); } /** * Get the last time the connection was seen. */ - public function lastSeenAt(): Carbon + public function lastSeenAt(): ?Carbon { - return Carbon::parse($this->lastSeenAt); + return $this->lastSeenAt ? Carbon::parse($this->lastSeenAt) : null; } /** diff --git a/src/Contracts/ConnectionManager.php b/src/Contracts/ConnectionManager.php deleted file mode 100644 index da7da619..00000000 --- a/src/Contracts/ConnectionManager.php +++ /dev/null @@ -1,61 +0,0 @@ - - */ - public function all(): array; - - /** - * Synchronize a connection with the manager. - */ - public function save(Connection $connection): void; - - /** - * Flush the channel manager repository. - */ - public function flush(): void; -} diff --git a/src/Contracts/ServerProvider.php b/src/Contracts/ServerProvider.php index dfa76666..233133a7 100644 --- a/src/Contracts/ServerProvider.php +++ b/src/Contracts/ServerProvider.php @@ -52,11 +52,6 @@ public function doesNotSubscribeToEvents(): bool return $this->shouldNotPublishEvents(); } - /** - * Build the connection manager for the server. - */ - abstract public function buildConnectionManager(): ConnectionManager; - /** * Build the channel manager for the server. */ diff --git a/src/Jobs/PingInactiveConnections.php b/src/Jobs/PingInactiveConnections.php index a2ec881c..c019e46c 100644 --- a/src/Jobs/PingInactiveConnections.php +++ b/src/Jobs/PingInactiveConnections.php @@ -4,7 +4,7 @@ use Illuminate\Foundation\Bus\Dispatchable; use Laravel\Reverb\Contracts\ApplicationProvider; -use Laravel\Reverb\Contracts\ConnectionManager; +use Laravel\Reverb\Contracts\ChannelManager; class PingInactiveConnections { @@ -13,12 +13,12 @@ class PingInactiveConnections /** * Execute the job. */ - public function handle(ConnectionManager $connections): void + public function handle(ChannelManager $channels): void { app(ApplicationProvider::class) ->all() - ->each(function ($application) use ($connections) { - collect($connections->for($application)->all()) + ->each(function ($application) use ($channels) { + $channels->for($application)->connections() ->each(function ($connection) { if ($connection->isActive()) { return; diff --git a/src/Jobs/PruneStaleConnections.php b/src/Jobs/PruneStaleConnections.php index 6bb0efe1..364dd89c 100644 --- a/src/Jobs/PruneStaleConnections.php +++ b/src/Jobs/PruneStaleConnections.php @@ -4,7 +4,7 @@ use Illuminate\Foundation\Bus\Dispatchable; use Laravel\Reverb\Contracts\ApplicationProvider; -use Laravel\Reverb\Contracts\ConnectionManager; +use Laravel\Reverb\Contracts\ChannelManager; use Laravel\Reverb\Output; class PruneStaleConnections @@ -14,16 +14,15 @@ class PruneStaleConnections /** * Execute the job. */ - public function handle(ConnectionManager $connections): void + public function handle(ChannelManager $channels): void { app(ApplicationProvider::class) ->all() - ->each(function ($application) use ($connections) { - collect($connections->for($application)->all()) + ->each(function ($application) use ($channels) { + + $channels->for($application)->connections() ->each(function ($connection) { if (! $connection->isStale()) { - dump('Connection is not stale', $connection->id()); - return; } diff --git a/src/Managers/ArrayChannelConnectionManager.php b/src/Managers/ArrayChannelConnectionManager.php index 35d568f1..70f209bb 100644 --- a/src/Managers/ArrayChannelConnectionManager.php +++ b/src/Managers/ArrayChannelConnectionManager.php @@ -20,7 +20,7 @@ class ArrayChannelConnectionManager implements ChannelConnectionManager */ public function add(Connection $connection, array $data): void { - $this->connections[$connection->identifier()] = new ChannelConnection($connection, $data); + $this->connections[$connection->id()] = new ChannelConnection($connection, $data); } /** @@ -28,15 +28,23 @@ public function add(Connection $connection, array $data): void */ public function remove(Connection $connection): void { - unset($this->connections[$connection->identifier()]); + unset($this->connections[$connection->id()]); } /** - * Find a connection by its identifier. + * Find a connection in the set. */ public function find(Connection $connection): ?ChannelConnection { - return $this->connections[$connection->identifier()] ?? null; + return $this->findById($connection->id()); + } + + /** + * Find a connection in the set by its ID. + */ + public function findById(string $id): ?ChannelConnection + { + return $this->connections[$id] ?? null; } /** diff --git a/src/Managers/ArrayChannelManager.php b/src/Managers/ArrayChannelManager.php index 003e6fb9..eed0ffc5 100644 --- a/src/Managers/ArrayChannelManager.php +++ b/src/Managers/ArrayChannelManager.php @@ -54,6 +54,18 @@ public function find(string $channel): Channel return $this->channels($channel); } + /** + * Get all the connections for the given channels. + */ + public function connections(string $channel = null): Collection + { + $channels = Collection::wrap($this->channels($channel)); + + return $channels->reduce(function ($carry, $channel) { + return $carry = $carry->merge($channel->connections()); + }, collect()); + } + /** * Unsubscribe from all channels. */ diff --git a/src/Managers/ArrayConnectionManager.php b/src/Managers/ArrayConnectionManager.php deleted file mode 100644 index ce3f3936..00000000 --- a/src/Managers/ArrayConnectionManager.php +++ /dev/null @@ -1,120 +0,0 @@ -> - */ - protected $connections = []; - - /** - * The appliation instance. - * - * @var \Laravel\Reverb\Application - */ - protected $application; - - /** - * Get the application instance. - */ - public function app(): ?Application - { - return $this->application; - } - - /** - * Add a new connection to the manager. - */ - public function connect(Connection $connection): Connection - { - $connection->touch(); - - $this->save($connection); - - return $connection; - } - - /** - * Attempt to find a connection from the manager. - */ - public function reconnect(string $identifier): ?Connection - { - if ($connection = $this->find($identifier)) { - return $connection->touch(); - } - - return null; - } - - /** - * Remove a connection from the manager. - */ - public function disconnect(string $identifier): void - { - unset($this->connections[$this->application->id()][$identifier]); - } - - /** - * Resolve a connection by its identifier. - */ - public function resolve(string $identifier, Closure $newConnection): Connection - { - if (! $connection = $this->find($identifier)) { - $connection = $newConnection(); - } - - return $this->connect($connection); - } - - /** - * Find a connection by its identifier. - */ - public function find(string $identifier): ?Connection - { - return $this->connections[$this->application->id()][$identifier] ?? null; - } - - /** - * Get all of the connections from the cache. - * - * @return array - */ - public function all(): array - { - return $this->connections[$this->application->id()] ?? []; - } - - /** - * Synchronize a connection with the manager. - */ - public function save(Connection $connection): void - { - $this->connections[$this->application->id()][$connection->identifier()] = $connection; - } - - /** - * Flush the channel manager repository. - */ - public function flush(): void - { - App::make(ApplicationProvider::class) - ->all() - ->each(function (Application $application) { - $this->connections[$application->id()] = []; - }); - } -} diff --git a/src/Pusher/Http/Controllers/Controller.php b/src/Pusher/Http/Controllers/Controller.php index a2b5b62a..7fb6f3fe 100644 --- a/src/Pusher/Http/Controllers/Controller.php +++ b/src/Pusher/Http/Controllers/Controller.php @@ -7,7 +7,6 @@ use Laravel\Reverb\Concerns\ClosesConnections; use Laravel\Reverb\Contracts\ApplicationProvider; use Laravel\Reverb\Contracts\ChannelManager; -use Laravel\Reverb\Contracts\ConnectionManager; use Laravel\Reverb\Exceptions\InvalidApplication; use Laravel\Reverb\Http\Connection; use Psr\Http\Message\RequestInterface; @@ -36,7 +35,6 @@ public function __invoke(RequestInterface $request, Connection $connection, ...$ try { $this->setApplication($args['appId'] ?? null); - $this->setConnections(); $this->setChannels(); } catch (HttpException $e) { return $this->close($connection, $e->getStatusCode(), $e->getMessage()); @@ -72,14 +70,6 @@ protected function setApplication(?string $appId): Application } } - /** - * Set the Reverb connection manager instance. - */ - protected function setConnections() - { - $this->connections = app(ConnectionManager::class)->for($this->application); - } - /** * Set the Reverb channel manager instance. */ diff --git a/src/Pusher/Http/Controllers/EventsBatchController.php b/src/Pusher/Http/Controllers/EventsBatchController.php index 7fe357c8..db3d3d09 100644 --- a/src/Pusher/Http/Controllers/EventsBatchController.php +++ b/src/Pusher/Http/Controllers/EventsBatchController.php @@ -27,7 +27,7 @@ public function handle(RequestInterface $request, Connection $connection, ...$ar 'channel' => $item['channel'], 'data' => $item['data'], ], - isset($item['socket_id']) ? $this->connections->find($item['socket_id']) : null + isset($item['socket_id']) ? $this->channels->find($item['channel'])->connections()->findById($item['socket_id']) : null ); return isset($item['info']) ? $this->getInfo($item['channel'], $item['info']) : []; diff --git a/src/Pusher/Http/Controllers/EventsController.php b/src/Pusher/Http/Controllers/EventsController.php index 36057731..a46f9821 100644 --- a/src/Pusher/Http/Controllers/EventsController.php +++ b/src/Pusher/Http/Controllers/EventsController.php @@ -28,7 +28,7 @@ public function handle(RequestInterface $request, Connection $connection, ...$ar 'channels' => $channels, 'data' => $payload['data'], ], - isset($payload['socket_id']) ? $this->connections->find($payload['socket_id']) : null + isset($payload['socket_id']) ? $this->channels->connections()[$payload['socket_id']]->connection() : null ); if (isset($payload['info'])) { diff --git a/src/Pusher/Http/Controllers/UsersTerminateController.php b/src/Pusher/Http/Controllers/UsersTerminateController.php index aa797403..ad21aeb1 100644 --- a/src/Pusher/Http/Controllers/UsersTerminateController.php +++ b/src/Pusher/Http/Controllers/UsersTerminateController.php @@ -14,11 +14,11 @@ class UsersTerminateController extends Controller */ public function handle(RequestInterface $request, Connection $connection, ...$args): Response { - if (! $connection = $this->connections->find($args['user'])) { + if (! $connection = $this->channels->connections()[$args['user']]) { return new JsonResponse((object) [], 400); } - $connection->disconnect(); + $connection->connection()->disconnect(); return new JsonResponse((object) []); } diff --git a/src/Servers/ApiGateway/ApiGatewayProvider.php b/src/Servers/ApiGateway/ApiGatewayProvider.php index 3ca3ca04..acd90ca3 100644 --- a/src/Servers/ApiGateway/ApiGatewayProvider.php +++ b/src/Servers/ApiGateway/ApiGatewayProvider.php @@ -10,14 +10,12 @@ use Laravel\Reverb\Contracts\ApplicationProvider; use Laravel\Reverb\Contracts\ChannelConnectionManager; use Laravel\Reverb\Contracts\ChannelManager; -use Laravel\Reverb\Contracts\ConnectionManager; use Laravel\Reverb\Contracts\ServerProvider; use Laravel\Reverb\Event; use Laravel\Reverb\Jobs\PingInactiveConnections; use Laravel\Reverb\Jobs\PruneStaleConnections; use Laravel\Reverb\Managers\ArrayChannelConnectionManager; use Laravel\Reverb\Managers\ArrayChannelManager; -use Laravel\Reverb\Managers\ArrayConnectionManager; class ApiGatewayProvider extends ServerProvider { @@ -54,14 +52,6 @@ public function register(): void }); } - /** - * Build the connection manager for the server. - */ - public function buildConnectionManager(): ConnectionManager - { - return new ArrayConnectionManager; - } - /** * Build the channel manager for the server. */ diff --git a/src/Servers/ApiGateway/Server.php b/src/Servers/ApiGateway/Server.php index 4e0e0d19..92b5d38b 100644 --- a/src/Servers/ApiGateway/Server.php +++ b/src/Servers/ApiGateway/Server.php @@ -4,7 +4,6 @@ use Laravel\Reverb\Application; use Laravel\Reverb\Contracts\ApplicationProvider; -use Laravel\Reverb\Contracts\ConnectionManager; use Laravel\Reverb\Exceptions\InvalidApplication; use Laravel\Reverb\Server as ReverbServer; use Laravel\Reverb\Servers\ApiGateway\Jobs\SendToConnection; @@ -13,7 +12,6 @@ class Server { public function __construct( protected ReverbServer $server, - protected ConnectionManager $connections, protected ApplicationProvider $applications, ) { } @@ -29,10 +27,10 @@ public function handle(Request $request): void $this->connect($request) ), 'DISCONNECT' => $this->server->close( - $this->getConnection($request) + $this->connect($request) ), 'MESSAGE' => $this->server->message( - $this->getConnection($request), + $this->connect($request), $request->message() ) }; @@ -43,7 +41,7 @@ public function handle(Request $request): void ); } catch (\Exception $e) { $this->server->error( - $this->getConnection($request), + $this->connect($request), $e ); } @@ -54,30 +52,11 @@ public function handle(Request $request): void */ protected function connect(Request $request): Connection { - return $this->connections - ->for($application = $this->application($request)) - ->resolve( - $request->connectionId(), - fn () => new Connection( - $request->connectionId(), - $application, - $request->headers['origin'] ?? null - ) - ); - } - - /** - * Get a Reverb connection from the API Gateway request. - */ - protected function getConnection(Request $request): Connection - { - foreach ($this->applications->all() as $application) { - if ($connection = $this->connections->for($application)->find($request->connectionId())) { - return $this->connections->connect($connection); - } - } - - throw new InvalidApplication; + return new Connection( + $request->connectionId(), + $this->application($request), + $request->headers['origin'] ?? null + ); } /** diff --git a/src/Servers/Reverb/Connection.php b/src/Servers/Reverb/Connection.php index 37b387c2..e1b0e53f 100644 --- a/src/Servers/Reverb/Connection.php +++ b/src/Servers/Reverb/Connection.php @@ -19,7 +19,7 @@ class Connection extends ConnectionContract /** * The last time the connection was seen. */ - protected string $lastSeenAt; + protected ?string $lastSeenAt = null; /** * Stores the ping state of the connection. diff --git a/src/Servers/Reverb/Controller.php b/src/Servers/Reverb/Controller.php index 1131def7..350bbfaf 100644 --- a/src/Servers/Reverb/Controller.php +++ b/src/Servers/Reverb/Controller.php @@ -3,7 +3,6 @@ namespace Laravel\Reverb\Servers\Reverb; use Laravel\Reverb\Contracts\ApplicationProvider; -use Laravel\Reverb\Contracts\ConnectionManager; use Laravel\Reverb\Exceptions\InvalidApplication; use Laravel\Reverb\Server; use Laravel\Reverb\Servers\Reverb\Connection as ReverbConnection; @@ -41,14 +40,10 @@ protected function connection(RequestInterface $request, WsConnection $connectio return $connection->close(); } - return app(ConnectionManager::class) - ->for($application) - ->connect( - new ReverbConnection( - $connection, - $application, - $request->getHeader('Origin')[0] ?? null - ) - ); + return new ReverbConnection( + $connection, + $application, + $request->getHeader('Origin')[0] ?? null + ); } } diff --git a/src/Servers/Reverb/ReverbProvider.php b/src/Servers/Reverb/ReverbProvider.php index 99b1b845..1b4f5b0e 100644 --- a/src/Servers/Reverb/ReverbProvider.php +++ b/src/Servers/Reverb/ReverbProvider.php @@ -9,12 +9,10 @@ use Laravel\Reverb\Concerns\InteractsWithAsyncRedis; use Laravel\Reverb\Contracts\ChannelConnectionManager; use Laravel\Reverb\Contracts\ChannelManager; -use Laravel\Reverb\Contracts\ConnectionManager; use Laravel\Reverb\Contracts\ServerProvider; use Laravel\Reverb\Event; use Laravel\Reverb\Managers\ArrayChannelConnectionManager; use Laravel\Reverb\Managers\ArrayChannelManager; -use Laravel\Reverb\Managers\ArrayConnectionManager; use Laravel\Reverb\Servers\Reverb\Console\Commands\StartServer; use React\EventLoop\LoopInterface; @@ -96,14 +94,6 @@ public function withPublishing(): void $this->publishesEvents = true; } - /** - * Build the connection manager for the server. - */ - public function buildConnectionManager(): ConnectionManager - { - return new ArrayConnectionManager; - } - /** * Build the channel manager for the server. */ diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php index 22b9f8f1..5850046c 100644 --- a/src/ServiceProvider.php +++ b/src/ServiceProvider.php @@ -5,7 +5,6 @@ use Illuminate\Support\ServiceProvider as BaseServiceProvider; use Laravel\Reverb\Contracts\ChannelConnectionManager; use Laravel\Reverb\Contracts\ChannelManager; -use Laravel\Reverb\Contracts\ConnectionManager; use Laravel\Reverb\Contracts\Logger; use Laravel\Reverb\Contracts\ServerProvider; use Laravel\Reverb\Loggers\NullLogger; @@ -48,11 +47,6 @@ public function registerServer() $server->register(); - $this->app->singleton( - ConnectionManager::class, - fn () => $server->buildConnectionManager() - ); - $this->app->singleton( ChannelManager::class, fn () => $server->buildChannelManager() diff --git a/tests/Feature/Reverb/ChannelUsersControllerTest.php b/tests/Feature/Reverb/ChannelUsersControllerTest.php index d63d634e..af53642b 100644 --- a/tests/Feature/Reverb/ChannelUsersControllerTest.php +++ b/tests/Feature/Reverb/ChannelUsersControllerTest.php @@ -18,9 +18,9 @@ $channel = app(ChannelManager::class) ->for(app()->make(ApplicationProvider::class)->findByKey('pusher-key')) ->find('presence-test-channel'); - $channel->subscribe($connection = new Connection('test-connection-one'), validAuth($connection, 'presence-test-channel', $data = json_encode(['user_id' => 1, 'user_info' => ['name' => 'Taylor']])), $data); - $channel->subscribe($connection = new Connection('test-connection-two'), validAuth($connection, 'presence-test-channel', $data = json_encode(['user_id' => 2, 'user_info' => ['name' => 'Joe']])), $data); - $channel->subscribe($connection = new Connection('test-connection-three'), validAuth($connection, 'presence-test-channel', $data = json_encode(['user_id' => 3, 'user_info' => ['name' => 'Jess']])), $data); + $channel->subscribe($connection = new Connection('test-connection-one'), validAuth($connection->id(), 'presence-test-channel', $data = json_encode(['user_id' => 1, 'user_info' => ['name' => 'Taylor']])), $data); + $channel->subscribe($connection = new Connection('test-connection-two'), validAuth($connection->id(), 'presence-test-channel', $data = json_encode(['user_id' => 2, 'user_info' => ['name' => 'Joe']])), $data); + $channel->subscribe($connection = new Connection('test-connection-three'), validAuth($connection->id(), 'presence-test-channel', $data = json_encode(['user_id' => 3, 'user_info' => ['name' => 'Jess']])), $data); $response = await($this->signedRequest('channels/presence-test-channel/users')); diff --git a/tests/Feature/Reverb/EventsControllerTest.php b/tests/Feature/Reverb/EventsControllerTest.php index 7b07aaf5..5d12db4c 100644 --- a/tests/Feature/Reverb/EventsControllerTest.php +++ b/tests/Feature/Reverb/EventsControllerTest.php @@ -86,7 +86,7 @@ 'name' => 'NewEvent', 'channels' => ['test-channel-one', 'test-channel-two'], 'data' => ['some' => 'data'], - 'socket_id' => $this->managedConnection()->identifier(), + 'socket_id' => $this->connectionId, ])); $this->assertSame(200, $response->getStatusCode()); diff --git a/tests/Feature/Reverb/ServerTest.php b/tests/Feature/Reverb/ServerTest.php index e2760a04..156e9e98 100644 --- a/tests/Feature/Reverb/ServerTest.php +++ b/tests/Feature/Reverb/ServerTest.php @@ -1,12 +1,8 @@ connect(); - - $this->assertCount(1, connectionManager()->all()); -}); - -it('can handle multiple new connections', function () { - $this->connect(); - $this->connect(); - - $this->assertCount(2, connectionManager()->all()); -}); - it('can handle connections to different applications', function () { $this->connect(); $this->connect(key: 'pusher-key-2'); $this->connect(key: 'pusher-key-3', headers: ['Origin' => 'http://laravel.com']); - - foreach (App::make(ApplicationProvider::class)->all() as $app) { - $this->assertCount(1, connectionManager()->for($app)->all()); - } }); it('can subscribe to a channel', function () { $response = $this->subscribe('test-channel'); - $this->assertCount(1, connectionManager()->all()); - $this->assertCount(1, channelManager()->find('test-channel')->connections()); expect($response)->toBe('{"event":"pusher_internal:subscription_succeeded","channel":"test-channel"}'); @@ -160,13 +137,12 @@ it('it can ping inactive subscribers', function () { $connection = $this->connect(); + $this->subscribe('test-channel', connection: $connection); $promise = $this->messagePromise($connection); Carbon::setTestNow(now()->addMinutes(10)); - (new PingInactiveConnections)->handle( - connectionManager() - ); + (new PingInactiveConnections)->handle(channelManager()); expect(await($promise))->toBe('{"event":"pusher:ping"}'); }); @@ -176,23 +152,21 @@ $this->subscribe('test-channel', connection: $connection); $promise = $this->disconnectPromise($connection); - expect(connectionManager()->all())->toHaveCount(1); expect(channelManager()->find('test-channel')->connections())->toHaveCount(1); Carbon::setTestNow(now()->addMinutes(10)); $promiseTwo = $this->messagePromise($connection); (new PingInactiveConnections)->handle( - connectionManager() + channelManager() ); expect(await($promiseTwo))->toBe('{"event":"pusher:ping"}'); $promiseThree = $this->messagePromise($connection); (new PruneStaleConnections)->handle( - connectionManager() + channelManager() ); - expect(connectionManager()->all())->toHaveCount(0); expect(channelManager()->find('test-channel')->connections())->toHaveCount(0); expect(await($promiseThree))->toBe('{"event":"pusher:error","data":"{\"code\":4201,\"message\":\"Pong reply not received in time\"}"}'); @@ -228,14 +202,10 @@ $this->subscribe('private-test-channel-3', connection: $connection, data: ['foo' => 'bar']); $this->subscribe('presence-test-channel-4', connection: $connection, data: ['user_id' => 1, 'user_info' => ['name' => 'Test User 1']]); - expect(connectionManager()->all())->toHaveCount(1); expect(channelManager()->all())->toHaveCount(4); - - $connection = Arr::first(connectionManager()->all()); - channelManager()->all()->each(function ($channel) use ($connection) { expect($channel->connections())->toHaveCount(1); - expect(collect($channel->connections())->map(fn ($conn, $index) => (string) $index))->toContain($connection->identifier()); + expect(collect($channel->connections())->map(fn ($connection) => $connection->id()))->toContain($this->connectionId); }); }); @@ -250,7 +220,6 @@ $this->subscribe('test-channel', connection: $connection); $this->subscribe('private-test-channel-3', connection: $connection, data: ['foo' => 'bar']); - expect(connectionManager()->all())->toHaveCount(2); expect(channelManager()->all())->toHaveCount(4); expect(channelManager()->find('test-channel')->connections())->toHaveCount(2); @@ -348,6 +317,5 @@ it('clears application state between requests', function () { $this->subscribe('test-channel'); - expect($this->app->make(ConnectionManager::class)->app())->toBeNull(); expect($this->app->make(ChannelManager::class)->app())->toBeNull(); })->todo(); diff --git a/tests/Feature/Reverb/UsersTerminateControllerTest.php b/tests/Feature/Reverb/UsersTerminateControllerTest.php index 2853a555..639f8e72 100644 --- a/tests/Feature/Reverb/UsersTerminateControllerTest.php +++ b/tests/Feature/Reverb/UsersTerminateControllerTest.php @@ -1,6 +1,5 @@ subscribe('test-channel-one', connection: $connection); $this->subscribe('test-channel-two', connection: $connection); - $this->subscribe('test-channel-one'); - $this->subscribe('test-channel-two'); + $connection = $this->connect(); + $this->subscribe('test-channel-one', connection: $connection); + $this->subscribe('test-channel-two', connection: $connection); - expect($connections = connectionManager()->all())->toHaveCount(3); expect(channelManager()->all()->get('test-channel-one')->connections())->toHaveCount(2); expect(channelManager()->all()->get('test-channel-two')->connections())->toHaveCount(2); - $connection = Arr::first($connections); - - $response = await($this->signedPostRequest("users/{$connection->identifier()}/terminate_connections")); + $response = await($this->signedPostRequest("users/{$this->connectionId}/terminate_connections")); $this->assertSame(200, $response->getStatusCode()); $this->assertSame('{}', $response->getBody()->getContents()); - expect($connections = connectionManager()->all())->toHaveCount(2); expect(channelManager()->all()->get('test-channel-one')->connections())->toHaveCount(1); expect(channelManager()->all()->get('test-channel-two')->connections())->toHaveCount(1); }); diff --git a/tests/Pest.php b/tests/Pest.php index 247afb23..0f3b627d 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -5,8 +5,6 @@ use Laravel\Reverb\Application; use Laravel\Reverb\Contracts\ApplicationProvider; use Laravel\Reverb\Contracts\ChannelManager; -use Laravel\Reverb\Contracts\Connection as ReverbConnection; -use Laravel\Reverb\Contracts\ConnectionManager; use Laravel\Reverb\Managers\Connections; use Laravel\Reverb\Servers\Reverb\ChannelConnection; use Laravel\Reverb\Tests\Connection; @@ -37,9 +35,9 @@ function connections(int $count = 1, array $data = [], $serializable = false): a /** * Generate a valid Pusher authentication signature. */ -function validAuth(ReverbConnection $connection, string $channel, string $data = null): string +function validAuth(string $connectionId, string $channel, string $data = null): string { - $signature = "{$connection->id()}:{$channel}"; + $signature = "{$connectionId}:{$channel}"; if ($data) { $signature .= ":{$data}"; @@ -48,15 +46,6 @@ function validAuth(ReverbConnection $connection, string $channel, string $data = return 'app-key:'.hash_hmac('sha256', $signature, 'pusher-secret'); } -/** - * Return the connection manager. - */ -function connectionManager(Application $app = null): ConnectionManager -{ - return App::make(ConnectionManager::class) - ->for($app ?: App::make(ApplicationProvider::class)->all()->first()); -} - /** * Return the connection manager. */ diff --git a/tests/ReverbTestCase.php b/tests/ReverbTestCase.php index 03b748eb..15f38207 100644 --- a/tests/ReverbTestCase.php +++ b/tests/ReverbTestCase.php @@ -3,7 +3,6 @@ namespace Laravel\Reverb\Tests; use Clue\React\Redis\Client; -use Illuminate\Support\Arr; use Illuminate\Support\Str; use Laravel\Reverb\Concerns\InteractsWithAsyncRedis; use Laravel\Reverb\Contracts\Connection; @@ -33,6 +32,8 @@ class ReverbTestCase extends TestCase protected $loop; + protected $connectionId; + protected function setUp(): void { parent::setUp(); @@ -146,13 +147,20 @@ public function connect($host = '0.0.0.0', $port = '8080', $key = 'pusher-key', $promise->resolve((string) $message); }); + $message = await($promise->promise()); + $this->assertTrue( Str::contains( - await($promise->promise()), + $message, 'connection_established' ) ); + $message = json_decode($message, true); + $data = json_decode($message['data'], true); + + $this->connectionId = $data['socket_id'] ?? null; + return $connection; } @@ -199,8 +207,7 @@ public function subscribe(string $channel, ?array $data = [], string $auth = nul if (! $auth && Str::startsWith($channel, ['private-', 'presence-'])) { $connection = $connection ?: $this->connect(); - $managed = $this->managedConnection($connection); - $auth = validAuth($managed, $channel, $data); + $auth = validAuth($this->connectionId, $channel, $data); } return $this->send([ @@ -213,14 +220,6 @@ public function subscribe(string $channel, ?array $data = [], string $auth = nul ], $connection); } - /** - * Return the latest connection set on the manager. - */ - public function managedConnection(): ?Connection - { - return Arr::last(connectionManager()->all()); - } - /** * Return a promise for the next message received to the given connection. * diff --git a/tests/Unit/Channels/PresenceChannelTest.php b/tests/Unit/Channels/PresenceChannelTest.php index c481908b..88196b84 100644 --- a/tests/Unit/Channels/PresenceChannelTest.php +++ b/tests/Unit/Channels/PresenceChannelTest.php @@ -22,7 +22,7 @@ $this->channelConnectionManager->shouldReceive('connections') ->andReturn([]); - $channel->subscribe($this->connection, validAuth($this->connection, 'presence-test-channel')); + $channel->subscribe($this->connection, validAuth($this->connection->id(), 'presence-test-channel')); }); it('can unsubscribe a connection from a channel', function () { @@ -91,7 +91,7 @@ $this->channelConnectionManager->shouldReceive('all') ->andReturn($connections = connections(3)); - $channel->subscribe($this->connection, validAuth($this->connection, 'presence-test-channel')); + $channel->subscribe($this->connection, validAuth($this->connection->id(), 'presence-test-channel')); collect($connections)->each(fn ($connection) => $connection->assertSent([ 'event' => 'pusher_internal:member_added', @@ -114,7 +114,7 @@ $channel->subscribe( $this->connection, validAuth( - $this->connection, + $this->connection->id(), 'presence-test-channel', $data ), @@ -135,7 +135,7 @@ $channel->subscribe( $this->connection, validAuth( - $this->connection, + $this->connection->id(), 'presence-test-channel', $data ), diff --git a/tests/Unit/Channels/PrivateChannelTest.php b/tests/Unit/Channels/PrivateChannelTest.php index 3dfc957b..c9951d0c 100644 --- a/tests/Unit/Channels/PrivateChannelTest.php +++ b/tests/Unit/Channels/PrivateChannelTest.php @@ -19,7 +19,7 @@ ->once() ->with($this->connection, []); - $channel->subscribe($this->connection, validAuth($this->connection, 'private-test-channel')); + $channel->subscribe($this->connection, validAuth($this->connection->id(), 'private-test-channel')); }); it('can unsubscribe a connection from a channel', function () { diff --git a/tests/Unit/Jobs/PingInactiveConnectionsTest.php b/tests/Unit/Jobs/PingInactiveConnectionsTest.php index c934b7e0..a9dc23a9 100644 --- a/tests/Unit/Jobs/PingInactiveConnectionsTest.php +++ b/tests/Unit/Jobs/PingInactiveConnectionsTest.php @@ -1,30 +1,30 @@ connectionManager = Mockery::spy(ConnectionManager::class); - $this->connectionManager->shouldReceive('for') - ->andReturn($this->connectionManager); - $this->app->singleton(ConnectionManager::class, fn () => $this->connectionManager); + $this->channelManager = Mockery::spy(ChannelManager::class); + $this->channelManager->shouldReceive('for') + ->andReturn($this->channelManager); + $this->app->singleton(ChannelManager::class, fn () => $this->channelManager); }); it('pings inactive connections', function () { $connections = connections(5); $channel = ChannelBroker::create('test-channel'); - $this->connectionManager->shouldReceive('all') + $this->channelManager->shouldReceive('connections') ->once() - ->andReturn($connections); + ->andReturn(collect($connections)); $connections = collect($connections)->each(function ($connection) use ($channel) { $channel->subscribe($connection->connection()); $connection->setLastSeenAt(now()->subMinutes(10)); }); - (new PingInactiveConnections)->handle($this->connectionManager); + (new PingInactiveConnections)->handle($this->channelManager); $connections->each(function ($connection) { $connection->assertSent([ diff --git a/tests/Unit/Jobs/PruneStaleConnectionsTest.php b/tests/Unit/Jobs/PruneStaleConnectionsTest.php index 2c7bfc9c..ea956bf1 100644 --- a/tests/Unit/Jobs/PruneStaleConnectionsTest.php +++ b/tests/Unit/Jobs/PruneStaleConnectionsTest.php @@ -2,28 +2,22 @@ use Laravel\Reverb\Channels\ChannelBroker; use Laravel\Reverb\Contracts\ChannelManager; -use Laravel\Reverb\Contracts\ConnectionManager; use Laravel\Reverb\Jobs\PruneStaleConnections; beforeEach(function () { - $this->connectionManager = Mockery::spy(ConnectionManager::class); - $this->connectionManager->shouldReceive('for') - ->andReturn($this->connectionManager); - $this->app->singleton(ChannelManager::class, fn () => $this->channelManager); - $this->channelManager = Mockery::spy(ChannelManager::class); $this->channelManager->shouldReceive('for') ->andReturn($this->channelManager); - $this->app->singleton(ConnectionManager::class, fn () => $this->connectionManager); + $this->app->singleton(ChannelManager::class, fn () => $this->channelManager); }); it('cleans up stale connections', function () { $connections = connections(5); $channel = ChannelBroker::create('test-channel'); - $this->connectionManager->shouldReceive('all') + $this->channelManager->shouldReceive('connections') ->once() - ->andReturn($connections); + ->andReturn(collect($connections)); collect($connections)->each(function ($connection) use ($channel) { $channel->subscribe($connection->connection()); @@ -35,8 +29,5 @@ ->with($connection->connection()); }); - (new PruneStaleConnections)->handle( - $this->connectionManager, - $this->channelManager - ); + (new PruneStaleConnections)->handle($this->channelManager); }); diff --git a/tests/Unit/Managers/ChannelManagerTest.php b/tests/Unit/Managers/ChannelManagerTest.php index fa6e5b64..44bad1de 100644 --- a/tests/Unit/Managers/ChannelManagerTest.php +++ b/tests/Unit/Managers/ChannelManagerTest.php @@ -1,7 +1,6 @@ channelManager = $this->app->make(ChannelManager::class) ->for($this->connection->app()); $this->channel = $this->channelManager->find('test-channel-0'); - $this->connectionManager = $this->app->make(ConnectionManagerInterface::class) - ->for($this->connection->app()); }); it('can subscribe to a channel', function () { @@ -44,7 +41,7 @@ $connections = collect(connections(5)) ->each(fn ($connection) => $this->channel->subscribe($connection->connection())); - $connections->each(fn ($connection) => expect($connection->identifier()) + $connections->each(fn ($connection) => expect($connection->id()) ->toBeIn(array_keys($this->channel->connections()))); }); diff --git a/tests/Unit/Managers/ConnectionMangerTest.php b/tests/Unit/Managers/ConnectionMangerTest.php deleted file mode 100644 index 4b3ba839..00000000 --- a/tests/Unit/Managers/ConnectionMangerTest.php +++ /dev/null @@ -1,59 +0,0 @@ -connection = new Connection; - $this->connectionManager = $this->app->make(ConnectionManager::class) - ->for($this->connection->app()); -}); - -it('can resolve an existing connection', function () { - $connection = new Connection('my-connection'); - $this->connectionManager->save($connection); - - $connection = $this->connectionManager->resolve( - 'my-connection', - function () { - throw new Exception('This should not be called.'); - } - ); - - expect($connection->identifier()) - ->toBe('my-connection'); -}); - -it('can resolve and store a new connection', function () { - $this->connectionManager->save($this->connection); - - $connection = $this->connectionManager->resolve( - 'my-connection', - function () { - throw new Exception('Creating new connection.'); - } - ); - - expect($connection->identifier()) - ->toBe('my-connection'); -})->throws(Exception::class, 'Creating new connection.'); - -it('can disconnect a connection', function () { - $this->connectionManager->save($this->connection); - - expect($this->connectionManager->all()) - ->toHaveCount(1); - - $this->connectionManager->disconnect($this->connection->identifier()); - - expect($this->connectionManager->all()) - ->toHaveCount(0); -}); - -it('can get all connections', function () { - $connections = collect(connections(10)); - $connections->each(fn ($connection) => $this->connectionManager->save($connection->connection())); - - expect($this->connectionManager->all()) - ->toHaveCount(10); -});