Completed
Pull Request — master (#447)
by Alexandru
01:33
created

WebSocketHandler::onError()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
cc 2
nc 2
nop 2
1
<?php
2
3
namespace BeyondCode\LaravelWebSockets\WebSockets;
4
5
use BeyondCode\LaravelWebSockets\Apps\App;
6
use BeyondCode\LaravelWebSockets\Dashboard\DashboardLogger;
7
use BeyondCode\LaravelWebSockets\Facades\StatisticsLogger;
8
use BeyondCode\LaravelWebSockets\PubSub\ReplicationInterface;
9
use BeyondCode\LaravelWebSockets\QueryParameters;
10
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
11
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\ConnectionsOverCapacity;
12
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\OriginNotAllowed;
13
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\UnknownAppKey;
14
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\WebSocketException;
15
use BeyondCode\LaravelWebSockets\WebSockets\Messages\PusherMessageFactory;
16
use Exception;
17
use Ratchet\ConnectionInterface;
18
use Ratchet\RFC6455\Messaging\MessageInterface;
19
use Ratchet\WebSocket\MessageComponentInterface;
20
use React\Promise\PromiseInterface;
21
22
class WebSocketHandler implements MessageComponentInterface
23
{
24
    /**
25
     * The channel manager.
26
     *
27
     * @var \BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager
28
     */
29
    protected $channelManager;
30
31
    /**
32
     * The replicator client.
33
     *
34
     * @var ReplicationInterface
35
     */
36
    protected $replicator;
37
38
    /**
39
     * Initialize a new handler.
40
     *
41
     * @param  \BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager  $channelManager
42
     * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
43
     */
44
    public function __construct(ChannelManager $channelManager)
45
    {
46
        $this->channelManager = $channelManager;
47
        $this->replicator = app(ReplicationInterface::class);
48
    }
49
50
    /**
51
     * Handle the socket opening.
52
     *
53
     * @param  \Ratchet\ConnectionInterface  $connection
54
     * @return void
55
     */
56
    public function onOpen(ConnectionInterface $connection)
57
    {
58
        $this->verifyAppKey($connection)
59
            ->verifyOrigin($connection)
60
            ->limitConcurrentConnections($connection)
61
            ->generateSocketId($connection)
62
            ->establishConnection($connection);
63
    }
64
65
    /**
66
     * Handle the incoming message.
67
     *
68
     * @param  \Ratchet\ConnectionInterface  $connection
69
     * @param  \Ratchet\RFC6455\Messaging\MessageInterface  $message
70
     * @return void
71
     */
72
    public function onMessage(ConnectionInterface $connection, MessageInterface $message)
73
    {
74
        $message = PusherMessageFactory::createForMessage($message, $connection, $this->channelManager);
75
76
        $message->respond();
77
78
        StatisticsLogger::webSocketMessage($connection->app->id);
0 ignored issues
show
Bug introduced by
Accessing app on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
79
    }
80
81
    /**
82
     * Handle the websocket close.
83
     *
84
     * @param  \Ratchet\ConnectionInterface  $connection
85
     * @return void
86
     */
87
    public function onClose(ConnectionInterface $connection)
88
    {
89
        $this->channelManager->removeFromAllChannels($connection);
90
91
        DashboardLogger::log($connection->app->id, DashboardLogger::TYPE_DISCONNECTED, [
0 ignored issues
show
Bug introduced by
Accessing app on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
92
            'socketId' => $connection->socketId,
0 ignored issues
show
Bug introduced by
Accessing socketId on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
93
        ]);
94
95
        StatisticsLogger::disconnection($connection->app->id);
0 ignored issues
show
Bug introduced by
Accessing app on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
96
97
        $this->replicator->unsubscribeFromApp($connection->app->id);
0 ignored issues
show
Bug introduced by
Accessing app on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
98
    }
99
100
    /**
101
     * Handle the websocket errors.
102
     *
103
     * @param  \Ratchet\ConnectionInterface  $connection
104
     * @param  WebSocketException  $exception
105
     * @return void
106
     */
107
    public function onError(ConnectionInterface $connection, Exception $exception)
108
    {
109
        if ($exception instanceof WebSocketException) {
110
            $connection->send(json_encode(
111
                $exception->getPayload()
112
            ));
113
        }
114
115
        $this->replicator->unsubscribeFromApp($connection->app->id);
0 ignored issues
show
Bug introduced by
Accessing app on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
116
    }
117
118
    /**
119
     * Verify the app key validity.
120
     *
121
     * @param  \Ratchet\ConnectionInterface  $connection
122
     * @return $this
123
     */
124
    protected function verifyAppKey(ConnectionInterface $connection)
125
    {
126
        $appKey = QueryParameters::create($connection->httpRequest)->get('appKey');
0 ignored issues
show
Bug introduced by
Accessing httpRequest on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
127
128
        if (! $app = App::findByKey($appKey)) {
129
            throw new UnknownAppKey($appKey);
130
        }
131
132
        $connection->app = $app;
0 ignored issues
show
Bug introduced by
Accessing app on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
133
134
        return $this;
135
    }
136
137
    /**
138
     * Verify the origin.
139
     *
140
     * @param  \Ratchet\ConnectionInterface  $connection
141
     * @return $this
142
     */
143
    protected function verifyOrigin(ConnectionInterface $connection)
144
    {
145
        if (! $connection->app->allowedOrigins) {
0 ignored issues
show
Bug introduced by
Accessing app on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
146
            return $this;
147
        }
148
149
        $header = (string) ($connection->httpRequest->getHeader('Origin')[0] ?? null);
0 ignored issues
show
Bug introduced by
Accessing httpRequest on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
150
151
        $origin = parse_url($header, PHP_URL_HOST) ?: $header;
152
153
        if (! $header || ! in_array($origin, $connection->app->allowedOrigins)) {
0 ignored issues
show
Bug introduced by
Accessing app on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
154
            throw new OriginNotAllowed($connection->app->key);
0 ignored issues
show
Bug introduced by
Accessing app on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
155
        }
156
157
        return $this;
158
    }
159
160
    /**
161
     * Limit the connections count by the app.
162
     *
163
     * @param  \Ratchet\ConnectionInterface  $connection
164
     * @return $this
165
     */
166
    protected function limitConcurrentConnections(ConnectionInterface $connection)
167
    {
168
        if (! is_null($capacity = $connection->app->capacity)) {
0 ignored issues
show
Bug introduced by
Accessing app on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
169
            $connectionsCount = $this->channelManager->getGlobalConnectionsCount($connection->app->id);
0 ignored issues
show
Bug introduced by
Accessing app on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
170
171
            if ($connectionsCount instanceof PromiseInterface) {
172
                $connectionsCount->then(function ($connectionsCount) use ($capacity, $connection) {
173
                    $connectionsCount = $connectionsCount ?: 0;
174
175
                    $this->sendExceptionIfOverCapacity($connectionsCount, $capacity, $connection);
176
                });
177
            } else {
178
                $this->throwExceptionIfOverCapacity($connectionsCount, $capacity);
179
            }
180
        }
181
182
        return $this;
183
    }
184
185
    /**
186
     * Create a socket id.
187
     *
188
     * @param  \Ratchet\ConnectionInterface  $connection
189
     * @return $this
190
     */
191
    protected function generateSocketId(ConnectionInterface $connection)
192
    {
193
        $socketId = sprintf('%d.%d', random_int(1, 1000000000), random_int(1, 1000000000));
194
195
        $connection->socketId = $socketId;
0 ignored issues
show
Bug introduced by
Accessing socketId on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
196
197
        return $this;
198
    }
199
200
    /**
201
     * Establish connection with the client.
202
     *
203
     * @param  \Ratchet\ConnectionInterface  $connection
204
     * @return $this
205
     */
206
    protected function establishConnection(ConnectionInterface $connection)
207
    {
208
        $connection->send(json_encode([
209
            'event' => 'pusher:connection_established',
210
            'data' => json_encode([
211
                'socket_id' => $connection->socketId,
0 ignored issues
show
Bug introduced by
Accessing socketId on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
212
                'activity_timeout' => 30,
213
            ]),
214
        ]));
215
216
        /** @var \GuzzleHttp\Psr7\Request $request */
217
        $request = $connection->httpRequest;
0 ignored issues
show
Bug introduced by
Accessing httpRequest on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
218
219
        DashboardLogger::log($connection->app->id, DashboardLogger::TYPE_CONNECTED, [
0 ignored issues
show
Bug introduced by
Accessing app on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
220
            'origin' => "{$request->getUri()->getScheme()}://{$request->getUri()->getHost()}",
221
            'socketId' => $connection->socketId,
0 ignored issues
show
Bug introduced by
Accessing socketId on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
222
        ]);
223
224
        StatisticsLogger::connection($connection->app->id);
0 ignored issues
show
Bug introduced by
Accessing app on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
225
226
        $this->replicator->subscribeToApp($connection->app->id);
0 ignored issues
show
Bug introduced by
Accessing app on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
227
228
        return $this;
229
    }
230
231
    /**
232
     * Throw a ConnectionsOverCapacity exception.
233
     *
234
     * @param  int  $connectionsCount
235
     * @param  int  $capacity
236
     * @return void
237
     * @throws ConnectionsOverCapacity
238
     */
239
    protected function throwExceptionIfOverCapacity(int $connectionsCount, int $capacity)
240
    {
241
        if ($connectionsCount >= $capacity) {
242
            throw new ConnectionsOverCapacity;
243
        }
244
    }
245
246
    /**
247
     * Send the ConnectionsOverCapacity exception through
248
     * the connection and close the channel.
249
     *
250
     * @param  int  $connectionsCount
251
     * @param  int  $capacity
252
     * @param  ConnectionInterface  $connection
253
     * @return void
254
     */
255
    protected function sendExceptionIfOverCapacity(int $connectionsCount, int $capacity, ConnectionInterface $connection)
256
    {
257
        if ($connectionsCount >= $capacity) {
258
            $payload = json_encode((new ConnectionsOverCapacity)->getPayload());
259
260
            tap($connection)->send($payload)->close();
261
        }
262
    }
263
}
264