diff --git a/src/PubSub/Drivers/RedisClient.php b/src/PubSub/Drivers/RedisClient.php index 6b922bc..d159c1f 100644 --- a/src/PubSub/Drivers/RedisClient.php +++ b/src/PubSub/Drivers/RedisClient.php @@ -194,7 +194,7 @@ class RedisClient extends LocalClient { $this->subscribeClient->__call('subscribe', [$this->getTopicName($appId)]); - $this->redis->hincrby($this->getTopicName($appId), 'connections', 1); + $this->publishClient->__call('hincrby', [$this->getTopicName($appId), 'connections', 1]); return true; } @@ -209,7 +209,7 @@ class RedisClient extends LocalClient { $this->subscribeClient->__call('unsubscribe', [$this->getTopicName($appId)]); - $this->redis->hincrby($this->getTopicName($appId), 'connections', -1); + $this->publishClient->__call('hincrby', [$this->getTopicName($appId), 'connections', -1]); return true; } @@ -226,7 +226,7 @@ class RedisClient extends LocalClient */ public function joinChannel($appId, string $channel, string $socketId, string $data) { - $this->redis->hset($this->getTopicName($appId, $channel), $socketId, $data); + $this->publishClient->__call('hset', [$this->getTopicName($appId, $channel), $socketId, $data]); DashboardLogger::log($appId, DashboardLogger::TYPE_REPLICATOR_JOINED_CHANNEL, [ 'channel' => $channel, @@ -248,7 +248,7 @@ class RedisClient extends LocalClient */ public function leaveChannel($appId, string $channel, string $socketId) { - $this->redis->hdel($this->getTopicName($appId, $channel), $socketId); + $this->publishClient->__call('hdel', [$this->getTopicName($appId, $channel), $socketId]); DashboardLogger::log($appId, DashboardLogger::TYPE_REPLICATOR_LEFT_CHANNEL, [ 'channel' => $channel, @@ -307,7 +307,7 @@ class RedisClient extends LocalClient { // Use the in-built Redis manager to avoid async run. - return $this->redis->hget($this->getTopicName($appId), 'connections') ?: 0; + return $this->publishClient->hget($this->getTopicName($appId), 'connections') ?: 0; } /** diff --git a/tests/Channels/PresenceChannelReplicationTest.php b/tests/Channels/PresenceChannelReplicationTest.php index 8f3fa27..d416aef 100644 --- a/tests/Channels/PresenceChannelReplicationTest.php +++ b/tests/Channels/PresenceChannelReplicationTest.php @@ -4,17 +4,10 @@ namespace BeyondCode\LaravelWebSockets\Tests\Channels; use BeyondCode\LaravelWebSockets\Tests\Mocks\Message; use BeyondCode\LaravelWebSockets\Tests\TestCase; -use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Facades\Redis; class PresenceChannelReplicationTest extends TestCase { - /** - * The Redis manager instance. - * - * @var \Illuminate\Redis\RedisManager - */ - protected $redis; - /** * {@inheritdoc} */ @@ -23,8 +16,6 @@ class PresenceChannelReplicationTest extends TestCase parent::setUp(); $this->runOnlyOnRedisReplication(); - - $this->redis = Cache::getRedis(); } /** @test */ @@ -55,7 +46,7 @@ class PresenceChannelReplicationTest extends TestCase $this->pusherServer->onMessage($connection, $message); $this->getPublishClient() - ->assertNotCalledWithArgs('hset', [ + ->assertCalledWithArgs('hset', [ 'laravel_database_1234:presence-channel', $connection->socketId, json_encode($channelData), @@ -64,7 +55,7 @@ class PresenceChannelReplicationTest extends TestCase ->assertCalled('publish'); $this->assertNotNull( - $this->redis->hget('laravel_database_1234:presence-channel', $connection->socketId) + Redis::hget('laravel_database_1234:presence-channel', $connection->socketId) ); } @@ -96,7 +87,7 @@ class PresenceChannelReplicationTest extends TestCase ->assertEventDispatched('message'); $this->getPublishClient() - ->assertNotCalled('hset') + ->assertCalled('hset') ->assertCalledWithArgs('hgetall', ['laravel_database_1234:presence-channel']) ->assertCalled('publish'); @@ -114,7 +105,7 @@ class PresenceChannelReplicationTest extends TestCase $this->pusherServer->onMessage($connection, $message); $this->getPublishClient() - ->assertNotCalled('hdel') + ->assertCalled('hdel') ->assertCalled('publish'); } @@ -143,8 +134,8 @@ class PresenceChannelReplicationTest extends TestCase $this->pusherServer->onMessage($connection, $message); $this->getPublishClient() - ->assertNotCalled('hset') - ->assertcalledWithArgs('hgetall', ['laravel_database_1234:presence-channel']) + ->assertCalled('hset') + ->assertCalledWithArgs('hgetall', ['laravel_database_1234:presence-channel']) ->assertCalled('publish'); } } diff --git a/tests/ConnectionTest.php b/tests/ConnectionTest.php index 526bb07..818e0c4 100644 --- a/tests/ConnectionTest.php +++ b/tests/ConnectionTest.php @@ -7,7 +7,7 @@ use BeyondCode\LaravelWebSockets\Tests\Mocks\Message; use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\ConnectionsOverCapacity; use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\OriginNotAllowed; use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\UnknownAppKey; -use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Facades\Redis; class ConnectionTest extends TestCase { @@ -47,15 +47,18 @@ class ConnectionTest extends TestCase { $this->runOnlyOnRedisReplication(); - $redis = Cache::getRedis(); - - $redis->hdel('laravel_database_1234', 'connections'); + Redis::hdel('laravel_database_1234', 'connections'); $this->app['config']->set('websockets.apps.0.capacity', 2); $this->getConnectedWebSocketConnection(['test-channel']); $this->getConnectedWebSocketConnection(['test-channel']); + + $this->getPublishClient() + ->assertCalledWithArgsCount(2, 'hincrby', ['laravel_database_1234', 'connections', 1]); + $this->expectException(ConnectionsOverCapacity::class); + $this->getConnectedWebSocketConnection(['test-channel']); } diff --git a/tests/HttpApi/FetchChannelsReplicationTest.php b/tests/HttpApi/FetchChannelsReplicationTest.php index 805b123..8c691c3 100644 --- a/tests/HttpApi/FetchChannelsReplicationTest.php +++ b/tests/HttpApi/FetchChannelsReplicationTest.php @@ -48,7 +48,7 @@ class FetchChannelsReplicationTest extends TestCase ->assertEventDispatched('message'); $this->getPublishClient() - ->assertNotCalled('hset') + ->assertCalled('hset') ->assertCalledWithArgs('hgetall', ['laravel_database_1234:presence-channel']) ->assertCalled('publish') ->assertCalled('multi') @@ -88,7 +88,7 @@ class FetchChannelsReplicationTest extends TestCase ->assertEventDispatched('message'); $this->getPublishClient() - ->assertNotCalled('hset') + ->assertCalled('hset') ->assertCalledWithArgs('hgetall', ['laravel_database_1234:presence-global.1']) ->assertCalledWithArgs('hgetall', ['laravel_database_1234:presence-global.2']) ->assertCalledWithArgs('hgetall', ['laravel_database_1234:presence-notglobal.2']) @@ -133,7 +133,7 @@ class FetchChannelsReplicationTest extends TestCase ->assertEventDispatched('message'); $this->getPublishClient() - ->assertNotCalled('hset') + ->assertCalled('hset') ->assertCalledWithArgs('hgetall', ['laravel_database_1234:presence-global.1']) ->assertCalledWithArgs('hgetall', ['laravel_database_1234:presence-global.2']) ->assertCalledWithArgs('hgetall', ['laravel_database_1234:presence-notglobal.2']) diff --git a/tests/Mocks/LazyClient.php b/tests/Mocks/LazyClient.php index ab3e224..932d75c 100644 --- a/tests/Mocks/LazyClient.php +++ b/tests/Mocks/LazyClient.php @@ -3,7 +3,10 @@ namespace BeyondCode\LaravelWebSockets\Tests\Mocks; use Clue\React\Redis\LazyClient as BaseLazyClient; +use Clue\React\Redis\Factory; +use Illuminate\Support\Facades\Cache; use PHPUnit\Framework\Assert as PHPUnit; +use React\EventLoop\LoopInterface; class LazyClient extends BaseLazyClient { @@ -21,6 +24,23 @@ class LazyClient extends BaseLazyClient */ protected $events = []; + /** + * The Redis manager instance. + * + * @var \Illuminate\Redis\RedisManager + */ + protected $redis; + + /** + * {@inheritdoc} + */ + public function __construct($target, Factory $factory, LoopInterface $loop) + { + parent::__construct($target, $factory, $loop); + + $this->redis = Cache::getRedis(); + } + /** * {@inheritdoc} */ @@ -28,6 +48,10 @@ class LazyClient extends BaseLazyClient { $this->calls[] = [$name, $args]; + if (! in_array($name, ['subscribe', 'psubscribe', 'unsubscribe', 'punsubscribe', 'onMessage'])) { + $this->redis->__call($name, $args); + } + return parent::__call($name, $args); } @@ -88,6 +112,26 @@ class LazyClient extends BaseLazyClient return $this; } + /** + * Check if the method with args got called an amount of times. + * + * @param string $name + * @param array $args + * @return $this + */ + public function assertCalledWithArgsCount($times = 1, $name, array $args) + { + $total = collect($this->getCalledFunctions())->filter(function ($function) use ($name, $args) { + [$calledName, $calledArgs] = $function; + + return $calledName === $name && $calledArgs === $args; + }); + + PHPUnit::assertCount($times, $total); + + return $this; + } + /** * Check if the method didn't call. * @@ -135,6 +179,26 @@ class LazyClient extends BaseLazyClient return $this; } + /** + * Check if the method with args got called an amount of times. + * + * @param string $name + * @param array $args + * @return $this + */ + public function assertNotCalledWithArgsCount($times = 1, $name, array $args) + { + $total = collect($this->getCalledFunctions())->filter(function ($function) use ($name, $args) { + [$calledName, $calledArgs] = $function; + + return $calledName === $name && $calledArgs === $args; + }); + + PHPUnit::assertNotCount($times, $total); + + return $this; + } + /** * Check if no function got called. * diff --git a/tests/PubSub/RedisDriverTest.php b/tests/PubSub/RedisDriverTest.php index dae8f7c..b018fcc 100644 --- a/tests/PubSub/RedisDriverTest.php +++ b/tests/PubSub/RedisDriverTest.php @@ -5,18 +5,11 @@ namespace BeyondCode\LaravelWebSockets\Tests\PubSub; use BeyondCode\LaravelWebSockets\PubSub\Drivers\RedisClient; use BeyondCode\LaravelWebSockets\Tests\Mocks\RedisFactory; use BeyondCode\LaravelWebSockets\Tests\TestCase; -use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Facades\Redis; use React\EventLoop\Factory as LoopFactory; class RedisDriverTest extends TestCase { - /** - * The Redis manager instance. - * - * @var \Illuminate\Redis\RedisManager - */ - protected $redis; - /** * {@inheritdoc} */ @@ -26,9 +19,7 @@ class RedisDriverTest extends TestCase $this->runOnlyOnRedisReplication(); - $this->redis = Cache::getRedis(); - - $this->redis->hdel('laravel_database_1234', 'connections'); + Redis::hdel('laravel_database_1234', 'connections'); } /** @test */ @@ -104,9 +95,7 @@ class RedisDriverTest extends TestCase ->assertCalledWithArgs('subscribe', ['laravel_database_1234']); $this->getPublishClient() - ->assertNothingCalled(); - - $this->assertEquals(1, $this->redis->hget('laravel_database_1234', 'connections')); + ->assertCalledWithArgs('hincrby', ['laravel_database_1234', 'connections', 1]); } /** @test */ @@ -121,15 +110,13 @@ class RedisDriverTest extends TestCase ->assertNotCalledWithArgs('unsubscribe', ['laravel_database_1234']); $this->getPublishClient() - ->assertNothingCalled(); - - $this->assertEquals(1, $this->redis->hget('laravel_database_1234', 'connections')); + ->assertCalledWithArgs('hincrby', ['laravel_database_1234', 'connections', 1]); $this->pusherServer->onClose($connection); $this->getPublishClient() - ->assertNothingCalled(); + ->assertCalledWithArgs('hincrby', ['laravel_database_1234', 'connections', -1]); - $this->assertEquals(0, $this->redis->hget('laravel_database_1234', 'connections')); + $this->assertEquals(0, Redis::hget('laravel_database_1234', 'connections')); } } diff --git a/tests/Statistics/Logger/StatisticsLoggerTest.php b/tests/Statistics/Logger/StatisticsLoggerTest.php index 9c075b5..a2b1e7b 100644 --- a/tests/Statistics/Logger/StatisticsLoggerTest.php +++ b/tests/Statistics/Logger/StatisticsLoggerTest.php @@ -8,13 +8,15 @@ use BeyondCode\LaravelWebSockets\Statistics\Logger\NullStatisticsLogger; use BeyondCode\LaravelWebSockets\Statistics\Logger\RedisStatisticsLogger; use BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry; use BeyondCode\LaravelWebSockets\Tests\TestCase; -use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Facades\Redis; class StatisticsLoggerTest extends TestCase { /** @test */ public function it_counts_connections() { + $this->runOnlyOnLocalReplication(); + $connections = []; $connections[] = $this->getConnectedWebSocketConnection(['channel-1']); @@ -30,6 +32,26 @@ class StatisticsLoggerTest extends TestCase $this->assertEquals(2, StatisticsLogger::getForAppId(1234)['peak_connection_count']); } + /** @test */ + public function it_counts_connections_on_redis_replication() + { + $this->runOnlyOnRedisReplication(); + + $connections = []; + + $connections[] = $this->getConnectedWebSocketConnection(['channel-1']); + $connections[] = $this->getConnectedWebSocketConnection(['channel-1']); + $connections[] = $this->getConnectedWebSocketConnection(['channel-1']); + + $this->assertEquals(3, StatisticsLogger::getForAppId(1234)['peak_connection_count']); + + $this->pusherServer->onClose(array_pop($connections)); + + StatisticsLogger::save(); + + $this->assertEquals(3, StatisticsLogger::getForAppId(1234)['peak_connection_count']); + } + /** @test */ public function it_counts_unique_connections_no_channel_subscriptions() { @@ -56,9 +78,7 @@ class StatisticsLoggerTest extends TestCase { $this->runOnlyOnRedisReplication(); - $redis = Cache::getRedis(); - - $redis->hdel('laravel_database_1234', 'connections'); + Redis::hdel('laravel_database_1234', 'connections'); $connections = []; @@ -73,7 +93,7 @@ class StatisticsLoggerTest extends TestCase StatisticsLogger::save(); - $this->assertEquals(1, StatisticsLogger::getForAppId(1234)['peak_connection_count']); + $this->assertEquals(3, StatisticsLogger::getForAppId(1234)['peak_connection_count']); } /** @test */