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

Commit aecbfee

Browse files
Ahmed Al-ShahawiAlShahawi
authored andcommitted
Add the ability to limit the maximum concurrent connections per appli… (#143)
* Add the ability to limit the maximum concurrent connections per application Co-Authored-By: AlShahawi <[email protected]>
1 parent 556f433 commit aecbfee

File tree

7 files changed

+59
-1
lines changed

7 files changed

+59
-1
lines changed

config/websockets.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
* This package comes with multi tenancy out of the box. Here you can
99
* configure the different apps that can use the webSockets server.
1010
*
11+
* Optionally you specify capacity so you can limit the maximum
12+
* concurrent connections for a specific app.
13+
*
1114
* Optionally you can disable client events so clients cannot send
1215
* messages to each other via the webSockets.
1316
*/
@@ -17,6 +20,7 @@
1720
'name' => env('APP_NAME'),
1821
'key' => env('PUSHER_APP_KEY'),
1922
'secret' => env('PUSHER_APP_SECRET'),
23+
'capacity' => null,
2024
'enable_client_messages' => false,
2125
'enable_statistics' => true,
2226
],

src/Apps/App.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ class App
2121
/** @var string|null */
2222
public $host;
2323

24+
/** @var int|null */
25+
public $capacity = null;
26+
2427
/** @var bool */
2528
public $clientMessagesEnabled = false;
2629

@@ -80,6 +83,13 @@ public function enableClientMessages(bool $enabled = true)
8083
return $this;
8184
}
8285

86+
public function setCapacity(?int $capacity)
87+
{
88+
$this->capacity = $capacity;
89+
90+
return $this;
91+
}
92+
8393
public function enableStatistics(bool $enabled = true)
8494
{
8595
$this->statisticsEnabled = $enabled;

src/Apps/ConfigAppProvider.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ protected function instanciate(?array $appAttributes): ?App
7373

7474
$app
7575
->enableClientMessages($appAttributes['enable_client_messages'])
76-
->enableStatistics($appAttributes['enable_statistics']);
76+
->enableStatistics($appAttributes['enable_statistics'])
77+
->setCapacity($appAttributes['capacity'] ?? null);
7778

7879
return $app;
7980
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace BeyondCode\LaravelWebSockets\WebSockets\Exceptions;
4+
5+
class ConnectionsOverCapacity extends WebSocketException
6+
{
7+
public function __construct()
8+
{
9+
$this->message = 'Over capacity';
10+
11+
// @See https://pusher.com/docs/pusher_protocol#error-codes
12+
// Indicates an error resulting in the connection
13+
// being closed by Pusher, and that the client may reconnect after 1s or more.
14+
$this->code = 4100;
15+
}
16+
}

src/WebSockets/WebSocketHandler.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\UnknownAppKey;
1515
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\WebSocketException;
1616
use BeyondCode\LaravelWebSockets\WebSockets\Messages\PusherMessageFactory;
17+
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\ConnectionsOverCapacity;
1718

1819
class WebSocketHandler implements MessageComponentInterface
1920
{
@@ -29,6 +30,7 @@ public function onOpen(ConnectionInterface $connection)
2930
{
3031
$this
3132
->verifyAppKey($connection)
33+
->limitConcurrentConnections($connection)
3234
->generateSocketId($connection)
3335
->establishConnection($connection);
3436
}
@@ -73,6 +75,18 @@ protected function verifyAppKey(ConnectionInterface $connection)
7375
return $this;
7476
}
7577

78+
protected function limitConcurrentConnections(ConnectionInterface $connection)
79+
{
80+
if (! is_null($capacity = $connection->app->capacity)) {
81+
$connectionsCount = $this->channelManager->getConnectionCount($connection->app->id);
82+
if ($connectionsCount >= $capacity) {
83+
throw new ConnectionsOverCapacity();
84+
}
85+
}
86+
87+
return $this;
88+
}
89+
7690
protected function generateSocketId(ConnectionInterface $connection)
7791
{
7892
$socketId = sprintf('%d.%d', random_int(1, 1000000000), random_int(1, 1000000000));

tests/ConnectionTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use BeyondCode\LaravelWebSockets\Apps\App;
66
use BeyondCode\LaravelWebSockets\Tests\Mocks\Message;
77
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\UnknownAppKey;
8+
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\ConnectionsOverCapacity;
89

910
class ConnectionTest extends TestCase
1011
{
@@ -26,6 +27,17 @@ public function known_app_keys_can_connect()
2627
$connection->assertSentEvent('pusher:connection_established');
2728
}
2829

30+
/** @test */
31+
public function app_can_not_exceed_maximum_capacity()
32+
{
33+
$this->app['config']->set('websockets.apps.0.capacity', 2);
34+
35+
$this->getConnectedWebSocketConnection(['test-channel']);
36+
$this->getConnectedWebSocketConnection(['test-channel']);
37+
$this->expectException(ConnectionsOverCapacity::class);
38+
$this->getConnectedWebSocketConnection(['test-channel']);
39+
}
40+
2941
/** @test */
3042
public function successful_connections_have_the_app_attached()
3143
{

tests/TestCase.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ protected function getEnvironmentSetUp($app)
4949
'id' => 1234,
5050
'key' => 'TestKey',
5151
'secret' => 'TestSecret',
52+
'capacity' => null,
5253
'enable_client_messages' => false,
5354
'enable_statistics' => true,
5455
],

0 commit comments

Comments
 (0)