|
5 | 5 | use BeyondCode\LaravelWebSockets\Apps\App;
|
6 | 6 | use BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver;
|
7 | 7 | use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
|
| 8 | +use Illuminate\Cache\RedisLock; |
8 | 9 | use Illuminate\Support\Facades\Cache;
|
9 | 10 |
|
10 | 11 | class RedisStatisticsLogger implements StatisticsLogger
|
@@ -115,24 +116,26 @@ public function disconnection($appId)
|
115 | 116 | */
|
116 | 117 | public function save()
|
117 | 118 | {
|
118 |
| - foreach ($this->redis->smembers('laravel-websockets:apps') as $appId) { |
119 |
| - if (! $statistic = $this->redis->hgetall($this->getHash($appId))) { |
120 |
| - continue; |
| 119 | + $this->lock()->get(function () { |
| 120 | + foreach ($this->redis->smembers('laravel-websockets:apps') as $appId) { |
| 121 | + if (! $statistic = $this->redis->hgetall($this->getHash($appId))) { |
| 122 | + continue; |
| 123 | + } |
| 124 | + |
| 125 | + $this->driver::create([ |
| 126 | + 'app_id' => $appId, |
| 127 | + 'peak_connection_count' => $statistic['peak_connection_count'] ?? 0, |
| 128 | + 'websocket_message_count' => $statistic['websocket_message_count'] ?? 0, |
| 129 | + 'api_message_count' => $statistic['api_message_count'] ?? 0, |
| 130 | + ]); |
| 131 | + |
| 132 | + $currentConnectionCount = $this->channelManager->getConnectionCount($appId); |
| 133 | + |
| 134 | + $currentConnectionCount === 0 |
| 135 | + ? $this->resetAppTraces($appId) |
| 136 | + : $this->resetStatistics($appId, $currentConnectionCount); |
121 | 137 | }
|
122 |
| - |
123 |
| - $this->driver::create([ |
124 |
| - 'app_id' => $appId, |
125 |
| - 'peak_connection_count' => $statistic['peak_connection_count'] ?? 0, |
126 |
| - 'websocket_message_count' => $statistic['websocket_message_count'] ?? 0, |
127 |
| - 'api_message_count' => $statistic['api_message_count'] ?? 0, |
128 |
| - ]); |
129 |
| - |
130 |
| - $currentConnectionCount = $this->channelManager->getConnectionCount($appId); |
131 |
| - |
132 |
| - $currentConnectionCount === 0 |
133 |
| - ? $this->resetAppTraces($appId) |
134 |
| - : $this->resetStatistics($appId, $currentConnectionCount); |
135 |
| - } |
| 138 | + }); |
136 | 139 | }
|
137 | 140 |
|
138 | 141 | /**
|
@@ -190,4 +193,14 @@ protected function getHash($appId): string
|
190 | 193 | {
|
191 | 194 | return "laravel-websockets:app:{$appId}";
|
192 | 195 | }
|
| 196 | + |
| 197 | + /** |
| 198 | + * Get a new RedisLock instance to avoid race conditions. |
| 199 | + * |
| 200 | + * @return \Illuminate\Cache\CacheLock |
| 201 | + */ |
| 202 | + protected function lock() |
| 203 | + { |
| 204 | + return new RedisLock($this->redis, 'laravel-websockets:lock', 0); |
| 205 | + } |
193 | 206 | }
|
0 commit comments