Completed
Push — master ( e5c732...8e3e30 )
by Ekin
03:31
created

Handler::onStart()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 2
eloc 6
nc 1
nop 2
dl 0
loc 13
ccs 8
cts 8
cp 1
crap 2
rs 10
c 4
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 6
    public function __construct(string $origin, Listener $provider, LoggerInterface $logger)
35
    {
36 6
        $this->origin   = $origin;
37 6
        $this->provider = $provider;
38 6
        $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 1
    public function handleClient(Gateway $gateway, Client $client, Request $request, Response $response): Promise
51
    {
52 1
        return call(function () use ($gateway, $client, $request, $response) {
0 ignored issues
show
Unused Code introduced by
The import $response 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...
Unused Code introduced by
The import $request 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...
53 1
            $client->onClose(function (Client $client, int $code, string $reason) use ($gateway) {
54
                yield $this->processDisconnectingClient($gateway, $client, $code, $reason);
55 1
            });
56
57 1
            $this->logger->info(
58 1
                \sprintf('Client %d connected. Total clients: %d', $client->getId(), count($gateway->getClients())),
59
            );
60
61 1
            yield $this->sendConnectedUsersCount(\count($gateway->getClients()));
62
63
            if ($this->lastEvents) {
64
                $client->send($this->lastEvents->jsonEncode());
65
            }
66
67
            yield $client->receive();
68 1
        });
69
    }
70
71
    private function processDisconnectingClient(Gateway $gateway, Client  $client, int $code, string $reason): Promise
72
    {
73
        return call(function () use ($gateway, $client, $code, $reason) {
74
            $this->logger->info(
75
                \sprintf(
76
                    'Client %d disconnected. Code: %d Reason: %s. Total clients: %d',
77
                    $client->getId(),
78
                    $code,
79
                    $reason,
80
                    count($gateway->getClients()),
81
                )
82
            );
83
84
            yield $this->sendConnectedUsersCount(count($gateway->getClients()));
85
        });
86
    }
87
88 3
    private function emit(Results $events): Promise
89
    {
90 3
        if (!$events->hasEvents()) {
91 2
            return new Success();
92
        }
93
94 1
        $this->lastEvents = $events;
95
96 1
        return $this->gateway->broadcast($events->jsonEncode());
97
    }
98
99 1
    private function sendConnectedUsersCount(int $count): Promise
100
    {
101 1
        return $this->gateway->broadcast(\json_encode(['connectedUsers' => $count]));
102
    }
103
104 3
    public function onStart(HttpServer $server, Gateway $gateway): Promise
105
    {
106 3
        $this->gateway = $gateway;
107
108 3
        asyncCall(function () {
109 3
            while (true) {
110 3
                $this->emit(yield $this->provider->listen());
111
112 3
                yield new Delayed(25000);
113
            }
114 3
        });
115
116 3
        return new Success();
117
    }
118
119 1
    public function onStop(HttpServer $server, Gateway $gateway): Promise
120
    {
121 1
        return new Success();
122
    }
123
}
124