Skip to content
This repository was archived by the owner on Feb 7, 2024. It is now read-only.

Commit 25694c7

Browse files
committed
wip
1 parent 4c64493 commit 25694c7

16 files changed

+473
-28
lines changed

src/Console/StartWebSocketServer.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
use BeyondCode\LaravelWebSockets\Facades\StatisticsLogger;
66
use BeyondCode\LaravelWebSockets\Facades\WebSocketsRouter;
7+
use BeyondCode\LaravelWebSockets\PubSub\Drivers\LocalClient;
8+
use BeyondCode\LaravelWebSockets\PubSub\Drivers\RedisClient;
79
use BeyondCode\LaravelWebSockets\PubSub\ReplicationInterface;
810
use BeyondCode\LaravelWebSockets\Server\Logger\ConnectionLogger;
911
use BeyondCode\LaravelWebSockets\Server\Logger\HttpLogger;
@@ -53,6 +55,7 @@ public function handle()
5355
->configureMessageLogger()
5456
->configureConnectionLogger()
5557
->configureRestartTimer()
58+
->configurePubSub()
5659
->registerEchoRoutes()
5760
->registerCustomRoutes()
5861
->configurePubSubReplication()
@@ -130,6 +133,28 @@ public function configureRestartTimer()
130133
return $this;
131134
}
132135

136+
/**
137+
* Configure the replicators.
138+
*
139+
* @return void
140+
*/
141+
public function configurePubSub()
142+
{
143+
if (config('websockets.replication.driver', 'local') === 'local') {
144+
$this->laravel->singleton(ReplicationInterface::class, function () {
145+
return new LocalClient;
146+
});
147+
}
148+
149+
if (config('websockets.replication.driver', 'local') === 'redis') {
150+
$this->laravel->singleton(ReplicationInterface::class, function () {
151+
return (new RedisClient)->boot($this->loop);
152+
});
153+
}
154+
155+
return $this;
156+
}
157+
133158
protected function registerEchoRoutes()
134159
{
135160
WebSocketsRouter::echo();

src/PubSub/Drivers/LocalClient.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ class LocalClient implements ReplicationInterface
2121
* Boot the pub/sub provider (open connections, initial subscriptions, etc).
2222
*
2323
* @param LoopInterface $loop
24+
* @param string|null $factoryClass
2425
* @return self
2526
*/
26-
public function boot(LoopInterface $loop): ReplicationInterface
27+
public function boot(LoopInterface $loop, $factoryClass = null): ReplicationInterface
2728
{
2829
return $this;
2930
}

src/PubSub/Drivers/RedisClient.php

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,17 @@ public function __construct()
6666
* Boot the RedisClient, initializing the connections.
6767
*
6868
* @param LoopInterface $loop
69+
* @param string|null $factoryClass
6970
* @return ReplicationInterface
7071
*/
71-
public function boot(LoopInterface $loop): ReplicationInterface
72+
public function boot(LoopInterface $loop, $factoryClass = null): ReplicationInterface
7273
{
74+
$factoryClass = $factoryClass ?: Factory::class;
75+
7376
$this->loop = $loop;
7477

7578
$connectionUri = $this->getConnectionUri();
76-
$factory = new Factory($this->loop);
79+
$factory = new $factoryClass($this->loop);
7780

7881
$this->publishClient = $factory->createLazyClient($connectionUri);
7982
$this->subscribeClient = $factory->createLazyClient($connectionUri);
@@ -108,7 +111,7 @@ protected function onMessage(string $redisChannel, string $payload)
108111
// We need to put the channel name in the payload.
109112
// We strip the app ID from the channel name, websocket clients
110113
// expect the channel name to not include the app ID.
111-
$payload->channel = Str::after($redisChannel, "$appId:");
114+
$payload->channel = Str::after($redisChannel, "{$appId}:");
112115

113116
$channelManager = app(ChannelManager::class);
114117

@@ -296,4 +299,34 @@ protected function getConnectionUri()
296299

297300
return "redis://{$host}:{$port}".($query ? "?{$query}" : '');
298301
}
302+
303+
/**
304+
* Get the Subscribe client instance.
305+
*
306+
* @return Client
307+
*/
308+
public function getSubscribeClient()
309+
{
310+
return $this->subscribeClient;
311+
}
312+
313+
/**
314+
* Get the Publish client instance.
315+
*
316+
* @return Client
317+
*/
318+
public function getPublishClient()
319+
{
320+
return $this->publishClient;
321+
}
322+
323+
/**
324+
* Get the unique identifier for the server.
325+
*
326+
* @return string
327+
*/
328+
public function getServerId()
329+
{
330+
return $this->serverId;
331+
}
299332
}

src/PubSub/ReplicationInterface.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ interface ReplicationInterface
1212
* Boot the pub/sub provider (open connections, initial subscriptions, etc).
1313
*
1414
* @param LoopInterface $loop
15+
* @param string|null $factoryClass
1516
* @return self
1617
*/
17-
public function boot(LoopInterface $loop): self;
18+
public function boot(LoopInterface $loop, $factoryClass = null): self;
1819

1920
/**
2021
* Publish a payload on a specific channel, for a specific app.

src/WebSocketsServiceProvider.php

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@
99
use BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers\ShowDashboard;
1010
use BeyondCode\LaravelWebSockets\Dashboard\Http\Middleware\Authorize as AuthorizeDashboard;
1111
use BeyondCode\LaravelWebSockets\PubSub\Broadcasters\RedisPusherBroadcaster;
12-
use BeyondCode\LaravelWebSockets\PubSub\Drivers\LocalClient;
13-
use BeyondCode\LaravelWebSockets\PubSub\Drivers\RedisClient;
14-
use BeyondCode\LaravelWebSockets\PubSub\ReplicationInterface;
1512
use BeyondCode\LaravelWebSockets\Server\Router;
1613
use BeyondCode\LaravelWebSockets\Statistics\Http\Controllers\WebSocketStatisticsEntriesController;
1714
use BeyondCode\LaravelWebSockets\Statistics\Http\Middleware\Authorize as AuthorizeStatistics;
@@ -54,18 +51,6 @@ public function boot()
5451

5552
protected function configurePubSub()
5653
{
57-
if (config('websockets.replication.driver', 'local') === 'local') {
58-
$this->app->singleton(ReplicationInterface::class, function () {
59-
return new LocalClient;
60-
});
61-
}
62-
63-
if (config('websockets.replication.driver', 'local') === 'redis') {
64-
$this->app->singleton(ReplicationInterface::class, function () {
65-
return (new RedisClient)->boot($this->loop ?? LoopFactory::create());
66-
});
67-
}
68-
6954
$this->app->make(BroadcastManager::class)->extend('websockets', function ($app, array $config) {
7055
$pusher = new Pusher(
7156
$config['key'], $config['secret'],

tests/Channels/ChannelReplicationTest.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,13 @@
66

77
class ChannelReplicationTest extends TestCase
88
{
9-
//
9+
/**
10+
* {@inheritdoc}
11+
*/
12+
public function setUp(): void
13+
{
14+
parent::setUp();
15+
16+
$this->runOnlyOnRedisReplication();
17+
}
1018
}

tests/Channels/PresenceChannelReplicationTest.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,13 @@
66

77
class PresenceChannelReplicationTest extends TestCase
88
{
9-
//
9+
/**
10+
* {@inheritdoc}
11+
*/
12+
public function setUp(): void
13+
{
14+
parent::setUp();
15+
16+
$this->runOnlyOnRedisReplication();
17+
}
1018
}

tests/Channels/PresenceChannelTest.php

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace BeyondCode\LaravelWebSockets\Tests\Channels;
44

5+
use BeyondCode\LaravelWebSockets\PubSub\ReplicationInterface;
56
use BeyondCode\LaravelWebSockets\Tests\Mocks\Message;
67
use BeyondCode\LaravelWebSockets\Tests\TestCase;
78
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\InvalidSignature;
@@ -55,9 +56,27 @@ public function clients_with_valid_auth_signatures_can_join_presence_channels()
5556

5657
$this->pusherServer->onMessage($connection, $message);
5758

58-
$connection->assertSentEvent('pusher_internal:subscription_succeeded', [
59-
'channel' => 'presence-channel',
60-
]);
59+
$this->getPublishClient()
60+
->assertCalledWithArgs('hset', [
61+
'1234:presence-channel',
62+
$connection->socketId,
63+
json_encode($channelData),
64+
])
65+
->assertCalledWithArgs('hgetall', [
66+
'1234:presence-channel'
67+
]);
68+
// TODO: This fails somehow
69+
// Debugging shows the exact same pattern as good.
70+
/* ->assertCalledWithArgs('publish', [
71+
'1234:presence-channel',
72+
json_encode([
73+
'event' => 'pusher_internal:member_added',
74+
'channel' => 'presence-channel',
75+
'data' => $channelData,
76+
'appId' => '1234',
77+
'serverId' => $this->app->make(ReplicationInterface::class)->getServerId(),
78+
]),
79+
]) */
6180
}
6281

6382
/** @test */
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace BeyondCode\LaravelWebSockets\Tests\Channels;
4+
5+
use BeyondCode\LaravelWebSockets\Tests\TestCase;
6+
7+
class PrivateChannelReplicationTest extends TestCase
8+
{
9+
/**
10+
* {@inheritdoc}
11+
*/
12+
public function setUp(): void
13+
{
14+
parent::setUp();
15+
16+
$this->runOnlyOnRedisReplication();
17+
}
18+
}

0 commit comments

Comments
 (0)