Completed
Pull Request — master (#46)
by Ekin
03:35
created

Handler::onStop()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 1
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace ekinhbayar\GitAmp\Websocket;
4
5
use Amp\Delayed;
6
use Amp\Http\Server\HttpServer;
7
use Amp\Http\Server\Request;
8
use Amp\Http\Server\Response;
9
use Amp\Http\Status;
10
use Amp\Promise;
11
use Amp\Success;
12
use Amp\Websocket\Client;
13
use Amp\Websocket\Server\ClientHandler;
14
use Amp\Websocket\Server\Gateway;
15
use Amp\Websocket\Server\WebsocketServerObserver;
16
use ekinhbayar\GitAmp\Provider\Listener;
17
use ekinhbayar\GitAmp\Response\Results;
18
use Psr\Log\LoggerInterface;
19
use function Amp\asyncCall;
20
use function Amp\call;
21
22
class Handler implements ClientHandler, WebsocketServerObserver
23
{
24
    private Gateway $gateway;
25
26
    private string $origin;
27
28
    private Listener $provider;
29
30
    private ?Results $lastEvents = null;
31
32
    private LoggerInterface $logger;
33
34 7
    public function __construct(string $origin, Listener $provider, LoggerInterface $logger)
35
    {
36 7
        $this->origin   = $origin;
37 7
        $this->provider = $provider;
38 7
        $this->logger   = $logger;
39
    }
40
41 2
    public function handleHandshake(Gateway $gateway, Request $request, Response $response): Promise
42
    {
43 2
        if ($request->getHeader('origin') !== $this->origin) {
44 1
            return $gateway->getErrorHandler()->handleError(Status::FORBIDDEN, 'Forbidden Origin', $request);
45
        }
46
47 1
        return new Success($response);
48
    }
49
50 2
    public function handleClient(Gateway $gateway, Client $client, Request $request, Response $response): Promise
51
    {
52 2
        $client->onClose(function (Client $client, int $code, string $reason) use ($gateway) {
53
            $this->logger->info(
54
                \sprintf(
55
                    'Client %d disconnected. Code: %d Reason: %s. Total clients: %d',
56
                    $client->getId(),
57
                    $code,
58
                    $reason,
59
                    count($gateway->getClients()),
60
                )
61
            );
62
63
            $this->sendConnectedUsersCount(count($gateway->getClients()));
64 2
        });
65
66 2
        $this->logger->info(
67 2
            \sprintf('Client %d connected. Total clients: %d', $client->getId(), count($gateway->getClients())),
68
        );
69
70 2
        $this->sendConnectedUsersCount(\count($gateway->getClients()));
71
72 2
        if ($this->lastEvents) {
73 1
            $client->send($this->lastEvents->jsonEncode());
74
        }
75
76 2
        return call(function () use ($gateway, $client): \Generator {
0 ignored issues
show
Unused Code introduced by
The import $gateway is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
77 2
            while ($message = yield $client->receive()) {
0 ignored issues
show
Unused Code introduced by
The assignment to $message is dead and can be removed.
Loading history...
78
                // intentionally keep receiving, otherwise the connection closes instantly for some reason
79
            }
80 2
        });
81
    }
82
83 4
    private function emit(Results $events): void
84
    {
85 4
        if (!$events->hasEvents()) {
86 2
            return;
87
        }
88
89 2
        $this->lastEvents = $events;
90
91 2
        $this->gateway->broadcast($events->jsonEncode());
92
    }
93
94 2
    private function sendConnectedUsersCount(int $count): void
95
    {
96 2
        $this->gateway->broadcast(\json_encode(['connectedUsers' => $count]));
97
    }
98
99 4
    public function onStart(HttpServer $server, Gateway $gateway): Promise
100
    {
101 4
        $this->gateway = $gateway;
102
103 4
        asyncCall(function () {
104 4
            while (true) {
105 4
                $this->emit(yield $this->provider->listen());
106
107 4
                yield new Delayed(25000);
108
            }
109 4
        });
110
111 4
        return new Success();
112
    }
113
114 1
    public function onStop(HttpServer $server, Gateway $gateway): Promise
115
    {
116 1
        return new Success();
117
    }
118
}
119