Skip to content

Commit e41a068

Browse files
committed
Handle dropped connections georgeboot#9
1 parent e234ebe commit e41a068

File tree

4 files changed

+59
-14
lines changed

4 files changed

+59
-14
lines changed

src/ConnectionRepository.php

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@
33
namespace Georgeboot\LaravelEchoApiGateway;
44

55
use Aws\ApiGatewayManagementApi\ApiGatewayManagementApiClient;
6+
use Aws\ApiGatewayManagementApi\Exception\ApiGatewayManagementApiException;
67

78
class ConnectionRepository
89
{
910
protected ApiGatewayManagementApiClient $apiGatewayManagementApiClient;
1011

11-
public function __construct(array $config)
12-
{
12+
public function __construct(
13+
protected SubscriptionRepository $subscriptionRepository,
14+
array $config
15+
) {
1316
$this->apiGatewayManagementApiClient = new ApiGatewayManagementApiClient(array_merge($config['connection'], [
1417
'version' => '2018-11-29',
1518
'endpoint' => "https://{$config['api']['id']}.execute-api.{$config['connection']['region']}.amazonaws.com/{$config['api']['stage']}/",
@@ -18,9 +21,20 @@ public function __construct(array $config)
1821

1922
public function sendMessage(string $connectionId, string $data): void
2023
{
21-
$this->apiGatewayManagementApiClient->postToConnection([
22-
'ConnectionId' => $connectionId,
23-
'Data' => $data,
24-
]);
24+
try {
25+
$this->apiGatewayManagementApiClient->postToConnection([
26+
'ConnectionId' => $connectionId,
27+
'Data' => $data,
28+
]);
29+
} catch (ApiGatewayManagementApiException $e) {
30+
// handle gone connections
31+
if ($e->getAwsErrorCode() === 'GoneException') {
32+
$this->subscriptionRepository->clearConnection($connectionId);
33+
34+
return;
35+
}
36+
37+
throw $e;
38+
}
2539
}
2640
}

src/Handler.php

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@
1111

1212
class Handler extends WebsocketHandler
1313
{
14-
protected SubscriptionRepository $subscriptionRepository;
15-
protected ConnectionRepository $connectionRepository;
16-
17-
public function __construct(SubscriptionRepository $subscriptionRepository, ConnectionRepository $connectionRepository)
18-
{
14+
public function __construct(
15+
protected SubscriptionRepository $subscriptionRepository,
16+
protected ConnectionRepository $connectionRepository
17+
) {
1918
$this->subscriptionRepository = $subscriptionRepository;
2019
$this->connectionRepository = $connectionRepository;
2120
}

src/ServiceProvider.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ class ServiceProvider extends LaravelServiceProvider
1212
public function register()
1313
{
1414
$this->mergeConfigFrom(
15-
__DIR__ . '/../config/laravel-echo-api-gateway.php', 'laravel-echo-api-gateway'
15+
__DIR__ . '/../config/laravel-echo-api-gateway.php',
16+
'laravel-echo-api-gateway'
1617
);
1718

1819
Config::set('broadcasting.connections.laravel-echo-api-gateway', [
@@ -21,8 +22,10 @@ public function register()
2122

2223
$config = config('laravel-echo-api-gateway');
2324

24-
$this->app->bind(ConnectionRepository::class, fn () => new ConnectionRepository($config));
25-
$this->app->bind(SubscriptionRepository::class, fn () => new SubscriptionRepository($config));
25+
$subscriptionRepository = new SubscriptionRepository($config);
26+
27+
$this->app->bind(SubscriptionRepository::class, fn () => $subscriptionRepository);
28+
$this->app->bind(ConnectionRepository::class, fn () => new ConnectionRepository($subscriptionRepository, $config));
2629
}
2730

2831
public function boot(BroadcastManager $broadcastManager): void

tests/HandlerTest.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
<?php
22

3+
use Aws\ApiGatewayManagementApi\Exception\ApiGatewayManagementApiException;
4+
use Aws\CommandInterface;
5+
use Aws\Exception\AwsException;
6+
use Aws\MockHandler;
7+
use Aws\Result;
38
use Bref\Context\Context;
49
use Georgeboot\LaravelEchoApiGateway\ConnectionRepository;
510
use Georgeboot\LaravelEchoApiGateway\Handler;
611
use Georgeboot\LaravelEchoApiGateway\SubscriptionRepository;
712
use Mockery\Mock;
13+
use Psr\Http\Message\RequestInterface;
814

915
it('can subscribe to open channels', function () {
1016
app()->instance(SubscriptionRepository::class, Mockery::mock(SubscriptionRepository::class, function ($mock) {
@@ -71,3 +77,26 @@
7177
'body' => json_encode(['event' => 'unsubscribe', 'data' => ['channel' => 'test-channel']]),
7278
], $context);
7379
});
80+
81+
it('handles dropped connections', function () {
82+
$mock = new MockHandler();
83+
84+
$mock->append(function (CommandInterface $cmd, RequestInterface $req) {
85+
return new ApiGatewayManagementApiException('', $cmd, ['code' => 'GoneException']);
86+
});
87+
88+
/** @var SubscriptionRepository */
89+
$subscriptionRepository = Mockery::mock(SubscriptionRepository::class, function ($mock) {
90+
/** @var Mock $mock */
91+
$mock->shouldReceive('clearConnection')->withArgs(function (string $connectionId): bool {
92+
return $connectionId === 'dropped-connection-id-1234';
93+
})->once();
94+
});
95+
96+
$config = config('laravel-echo-api-gateway');
97+
98+
/** @var ConnectionRepository */
99+
$connectionRepository = new ConnectionRepository($subscriptionRepository, array_merge_recursive(['connection' => ['handler' => $mock]], $config));
100+
101+
$connectionRepository->sendMessage('dropped-connection-id-1234', 'test-message');
102+
});

0 commit comments

Comments
 (0)