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

Commit ec96ca7

Browse files
snellingiompociot
authored andcommitted
Update ChannelManager (#41)
* Update Channel Manager Switch ChannelManager to an interface. Extend with an ArrayChannelManager (and copy the code). Update the config to allow for swapping. Bind it to the ServiceProvider * Add a fallback if the config variable isn’t set * Fix StyleCI * Fix StyleCI line break * Add description for the ChannelManager option
1 parent db6d794 commit ec96ca7

File tree

4 files changed

+103
-70
lines changed

4 files changed

+103
-70
lines changed

config/websockets.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,13 @@
9797
*/
9898
'passphrase' => null,
9999
],
100+
101+
/*
102+
* Channel Manager
103+
* This class handles how channel persistence is handled.
104+
* By default, persistence is stored in an array by the running webserver.
105+
* The only requirement is that the class should implement
106+
* `ChannelManager` interface provided by this package.
107+
*/
108+
'channel_manager' => \BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManagers\ArrayChannelManager::class,
100109
];

src/WebSockets/Channels/ChannelManager.php

Lines changed: 6 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -4,78 +4,15 @@
44

55
use Ratchet\ConnectionInterface;
66

7-
class ChannelManager
7+
interface ChannelManager
88
{
9-
/** @var string */
10-
protected $appId;
9+
public function findOrCreate(string $appId, string $channelName): Channel;
1110

12-
/** @var array */
13-
protected $channels = [];
11+
public function find(string $appId, string $channelName): ?Channel;
1412

15-
public function findOrCreate(string $appId, string $channelName): Channel
16-
{
17-
if (! isset($this->channels[$appId][$channelName])) {
18-
$channelClass = $this->determineChannelClass($channelName);
13+
public function getChannels(string $appId): array;
1914

20-
$this->channels[$appId][$channelName] = new $channelClass($channelName);
21-
}
15+
public function getConnectionCount(string $appId): int;
2216

23-
return $this->channels[$appId][$channelName];
24-
}
25-
26-
public function find(string $appId, string $channelName): ?Channel
27-
{
28-
return $this->channels[$appId][$channelName] ?? null;
29-
}
30-
31-
protected function determineChannelClass(string $channelName): string
32-
{
33-
if (starts_with($channelName, 'private-')) {
34-
return PrivateChannel::class;
35-
}
36-
37-
if (starts_with($channelName, 'presence-')) {
38-
return PresenceChannel::class;
39-
}
40-
41-
return Channel::class;
42-
}
43-
44-
public function getChannels(string $appId): array
45-
{
46-
return $this->channels[$appId] ?? [];
47-
}
48-
49-
public function getConnectionCount(string $appId): int
50-
{
51-
return collect($this->getChannels($appId))
52-
->sum(function ($channel) {
53-
return count($channel->getSubscribedConnections());
54-
});
55-
}
56-
57-
public function removeFromAllChannels(ConnectionInterface $connection)
58-
{
59-
if (! isset($connection->app)) {
60-
return;
61-
}
62-
63-
/*
64-
* Remove the connection from all channels.
65-
*/
66-
collect(array_get($this->channels, $connection->app->id, []))->each->unsubscribe($connection);
67-
68-
/*
69-
* Unset all channels that have no connections so we don't leak memory.
70-
*/
71-
collect(array_get($this->channels, $connection->app->id, []))
72-
->reject->hasConnections()
73-
->each(function (Channel $channel, string $channelName) use ($connection) {
74-
unset($this->channels[$connection->app->id][$channelName]);
75-
});
76-
77-
if (count(array_get($this->channels, $connection->app->id, [])) === 0) {
78-
unset($this->channels[$connection->app->id]);
79-
}
80-
}
17+
public function removeFromAllChannels(ConnectionInterface $connection);
8118
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
3+
namespace BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManagers;
4+
5+
use Ratchet\ConnectionInterface;
6+
use BeyondCode\LaravelWebSockets\WebSockets\Channels\Channel;
7+
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
8+
use BeyondCode\LaravelWebSockets\WebSockets\Channels\PrivateChannel;
9+
use BeyondCode\LaravelWebSockets\WebSockets\Channels\PresenceChannel;
10+
11+
class ArrayChannelManager implements ChannelManager
12+
{
13+
/** @var string */
14+
protected $appId;
15+
16+
/** @var array */
17+
protected $channels = [];
18+
19+
public function findOrCreate(string $appId, string $channelName): Channel
20+
{
21+
if (! isset($this->channels[$appId][$channelName])) {
22+
$channelClass = $this->determineChannelClass($channelName);
23+
24+
$this->channels[$appId][$channelName] = new $channelClass($channelName);
25+
}
26+
27+
return $this->channels[$appId][$channelName];
28+
}
29+
30+
public function find(string $appId, string $channelName): ?Channel
31+
{
32+
return $this->channels[$appId][$channelName] ?? null;
33+
}
34+
35+
protected function determineChannelClass(string $channelName): string
36+
{
37+
if (starts_with($channelName, 'private-')) {
38+
return PrivateChannel::class;
39+
}
40+
41+
if (starts_with($channelName, 'presence-')) {
42+
return PresenceChannel::class;
43+
}
44+
45+
return Channel::class;
46+
}
47+
48+
public function getChannels(string $appId): array
49+
{
50+
return $this->channels[$appId] ?? [];
51+
}
52+
53+
public function getConnectionCount(string $appId): int
54+
{
55+
return collect($this->getChannels($appId))
56+
->sum(function ($channel) {
57+
return count($channel->getSubscribedConnections());
58+
});
59+
}
60+
61+
public function removeFromAllChannels(ConnectionInterface $connection)
62+
{
63+
if (! isset($connection->app)) {
64+
return;
65+
}
66+
67+
/*
68+
* Remove the connection from all channels.
69+
*/
70+
collect(array_get($this->channels, $connection->app->id, []))->each->unsubscribe($connection);
71+
72+
/*
73+
* Unset all channels that have no connections so we don't leak memory.
74+
*/
75+
collect(array_get($this->channels, $connection->app->id, []))
76+
->reject->hasConnections()
77+
->each(function (Channel $channel, string $channelName) use ($connection) {
78+
unset($this->channels[$connection->app->id][$channelName]);
79+
});
80+
81+
if (count(array_get($this->channels, $connection->app->id, [])) === 0) {
82+
unset($this->channels[$connection->app->id]);
83+
}
84+
}
85+
}

src/WebSocketsServiceProvider.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers\ShowDashboard;
1313
use BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers\AuthenticateDashboard;
1414
use BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers\DashboardApiController;
15+
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManagers\ArrayChannelManager;
1516
use BeyondCode\LaravelWebSockets\Dashboard\Http\Middleware\Authorize as AuthorizeDashboard;
1617
use BeyondCode\LaravelWebSockets\Statistics\Http\Middleware\Authorize as AuthorizeStatistics;
1718
use BeyondCode\LaravelWebSockets\Statistics\Http\Controllers\WebSocketStatisticsEntriesController;
@@ -51,7 +52,8 @@ public function register()
5152
});
5253

5354
$this->app->singleton(ChannelManager::class, function () {
54-
return new ChannelManager();
55+
return config('websockets.channel_manager') !== null && class_exists(config('websockets.channel_manager'))
56+
? app(config('websockets.channel_manager')) : new ArrayChannelManager();
5557
});
5658

5759
$this->app->singleton(AppProvider::class, function () {

0 commit comments

Comments
 (0)