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
This commit is contained in:
parent
db6d794fd5
commit
ec96ca7172
|
|
@ -97,4 +97,13 @@ return [
|
||||||
*/
|
*/
|
||||||
'passphrase' => null,
|
'passphrase' => null,
|
||||||
],
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Channel Manager
|
||||||
|
* This class handles how channel persistence is handled.
|
||||||
|
* By default, persistence is stored in an array by the running webserver.
|
||||||
|
* The only requirement is that the class should implement
|
||||||
|
* `ChannelManager` interface provided by this package.
|
||||||
|
*/
|
||||||
|
'channel_manager' => \BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManagers\ArrayChannelManager::class,
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -4,78 +4,15 @@ namespace BeyondCode\LaravelWebSockets\WebSockets\Channels;
|
||||||
|
|
||||||
use Ratchet\ConnectionInterface;
|
use Ratchet\ConnectionInterface;
|
||||||
|
|
||||||
class ChannelManager
|
interface ChannelManager
|
||||||
{
|
{
|
||||||
/** @var string */
|
public function findOrCreate(string $appId, string $channelName): Channel;
|
||||||
protected $appId;
|
|
||||||
|
|
||||||
/** @var array */
|
public function find(string $appId, string $channelName): ?Channel;
|
||||||
protected $channels = [];
|
|
||||||
|
|
||||||
public function findOrCreate(string $appId, string $channelName): Channel
|
public function getChannels(string $appId): array;
|
||||||
{
|
|
||||||
if (! isset($this->channels[$appId][$channelName])) {
|
|
||||||
$channelClass = $this->determineChannelClass($channelName);
|
|
||||||
|
|
||||||
$this->channels[$appId][$channelName] = new $channelClass($channelName);
|
public function getConnectionCount(string $appId): int;
|
||||||
}
|
|
||||||
|
|
||||||
return $this->channels[$appId][$channelName];
|
public function removeFromAllChannels(ConnectionInterface $connection);
|
||||||
}
|
|
||||||
|
|
||||||
public function find(string $appId, string $channelName): ?Channel
|
|
||||||
{
|
|
||||||
return $this->channels[$appId][$channelName] ?? null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function determineChannelClass(string $channelName): string
|
|
||||||
{
|
|
||||||
if (starts_with($channelName, 'private-')) {
|
|
||||||
return PrivateChannel::class;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (starts_with($channelName, 'presence-')) {
|
|
||||||
return PresenceChannel::class;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Channel::class;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getChannels(string $appId): array
|
|
||||||
{
|
|
||||||
return $this->channels[$appId] ?? [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getConnectionCount(string $appId): int
|
|
||||||
{
|
|
||||||
return collect($this->getChannels($appId))
|
|
||||||
->sum(function ($channel) {
|
|
||||||
return count($channel->getSubscribedConnections());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function removeFromAllChannels(ConnectionInterface $connection)
|
|
||||||
{
|
|
||||||
if (! isset($connection->app)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Remove the connection from all channels.
|
|
||||||
*/
|
|
||||||
collect(array_get($this->channels, $connection->app->id, []))->each->unsubscribe($connection);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Unset all channels that have no connections so we don't leak memory.
|
|
||||||
*/
|
|
||||||
collect(array_get($this->channels, $connection->app->id, []))
|
|
||||||
->reject->hasConnections()
|
|
||||||
->each(function (Channel $channel, string $channelName) use ($connection) {
|
|
||||||
unset($this->channels[$connection->app->id][$channelName]);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (count(array_get($this->channels, $connection->app->id, [])) === 0) {
|
|
||||||
unset($this->channels[$connection->app->id]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManagers;
|
||||||
|
|
||||||
|
use Ratchet\ConnectionInterface;
|
||||||
|
use BeyondCode\LaravelWebSockets\WebSockets\Channels\Channel;
|
||||||
|
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
|
||||||
|
use BeyondCode\LaravelWebSockets\WebSockets\Channels\PrivateChannel;
|
||||||
|
use BeyondCode\LaravelWebSockets\WebSockets\Channels\PresenceChannel;
|
||||||
|
|
||||||
|
class ArrayChannelManager implements ChannelManager
|
||||||
|
{
|
||||||
|
/** @var string */
|
||||||
|
protected $appId;
|
||||||
|
|
||||||
|
/** @var array */
|
||||||
|
protected $channels = [];
|
||||||
|
|
||||||
|
public function findOrCreate(string $appId, string $channelName): Channel
|
||||||
|
{
|
||||||
|
if (! isset($this->channels[$appId][$channelName])) {
|
||||||
|
$channelClass = $this->determineChannelClass($channelName);
|
||||||
|
|
||||||
|
$this->channels[$appId][$channelName] = new $channelClass($channelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->channels[$appId][$channelName];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function find(string $appId, string $channelName): ?Channel
|
||||||
|
{
|
||||||
|
return $this->channels[$appId][$channelName] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function determineChannelClass(string $channelName): string
|
||||||
|
{
|
||||||
|
if (starts_with($channelName, 'private-')) {
|
||||||
|
return PrivateChannel::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (starts_with($channelName, 'presence-')) {
|
||||||
|
return PresenceChannel::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Channel::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getChannels(string $appId): array
|
||||||
|
{
|
||||||
|
return $this->channels[$appId] ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getConnectionCount(string $appId): int
|
||||||
|
{
|
||||||
|
return collect($this->getChannels($appId))
|
||||||
|
->sum(function ($channel) {
|
||||||
|
return count($channel->getSubscribedConnections());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function removeFromAllChannels(ConnectionInterface $connection)
|
||||||
|
{
|
||||||
|
if (! isset($connection->app)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove the connection from all channels.
|
||||||
|
*/
|
||||||
|
collect(array_get($this->channels, $connection->app->id, []))->each->unsubscribe($connection);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unset all channels that have no connections so we don't leak memory.
|
||||||
|
*/
|
||||||
|
collect(array_get($this->channels, $connection->app->id, []))
|
||||||
|
->reject->hasConnections()
|
||||||
|
->each(function (Channel $channel, string $channelName) use ($connection) {
|
||||||
|
unset($this->channels[$connection->app->id][$channelName]);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (count(array_get($this->channels, $connection->app->id, [])) === 0) {
|
||||||
|
unset($this->channels[$connection->app->id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -12,6 +12,7 @@ use BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers\SendMessage;
|
||||||
use BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers\ShowDashboard;
|
use BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers\ShowDashboard;
|
||||||
use BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers\AuthenticateDashboard;
|
use BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers\AuthenticateDashboard;
|
||||||
use BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers\DashboardApiController;
|
use BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers\DashboardApiController;
|
||||||
|
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManagers\ArrayChannelManager;
|
||||||
use BeyondCode\LaravelWebSockets\Dashboard\Http\Middleware\Authorize as AuthorizeDashboard;
|
use BeyondCode\LaravelWebSockets\Dashboard\Http\Middleware\Authorize as AuthorizeDashboard;
|
||||||
use BeyondCode\LaravelWebSockets\Statistics\Http\Middleware\Authorize as AuthorizeStatistics;
|
use BeyondCode\LaravelWebSockets\Statistics\Http\Middleware\Authorize as AuthorizeStatistics;
|
||||||
use BeyondCode\LaravelWebSockets\Statistics\Http\Controllers\WebSocketStatisticsEntriesController;
|
use BeyondCode\LaravelWebSockets\Statistics\Http\Controllers\WebSocketStatisticsEntriesController;
|
||||||
|
|
@ -51,7 +52,8 @@ class WebSocketsServiceProvider extends ServiceProvider
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->app->singleton(ChannelManager::class, function () {
|
$this->app->singleton(ChannelManager::class, function () {
|
||||||
return new ChannelManager();
|
return config('websockets.channel_manager') !== null && class_exists(config('websockets.channel_manager'))
|
||||||
|
? app(config('websockets.channel_manager')) : new ArrayChannelManager();
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->app->singleton(AppProvider::class, function () {
|
$this->app->singleton(AppProvider::class, function () {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue