1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace BenTools\MercurePHP\Hub; |
4
|
|
|
|
5
|
|
|
use BenTools\MercurePHP\Configuration\Configuration; |
6
|
|
|
use BenTools\MercurePHP\Helpers\LoggerAwareTrait; |
7
|
|
|
use BenTools\MercurePHP\Metrics\MetricsHandlerInterface; |
8
|
|
|
use BenTools\MercurePHP\Security\CORS; |
9
|
|
|
use Psr\Http\Message\ResponseInterface; |
10
|
|
|
use Psr\Http\Message\ServerRequestInterface; |
11
|
|
|
use Psr\Http\Server\RequestHandlerInterface; |
12
|
|
|
use Psr\Log\LoggerInterface; |
13
|
|
|
use Psr\Log\NullLogger; |
14
|
|
|
use React\EventLoop\LoopInterface; |
15
|
|
|
use React\Http; |
16
|
|
|
use React\Promise\PromiseInterface; |
17
|
|
|
use React\Socket; |
18
|
|
|
|
19
|
|
|
use function React\Promise\resolve; |
20
|
|
|
|
21
|
|
|
final class Hub implements RequestHandlerInterface |
22
|
|
|
{ |
23
|
|
|
use LoggerAwareTrait; |
24
|
|
|
|
25
|
|
|
private array $config; |
26
|
|
|
private RequestHandlerInterface $requestHandler; |
27
|
|
|
private CORS $cors; |
28
|
|
|
private MetricsHandlerInterface $metricsHandler; |
29
|
|
|
private ?int $shutdownSignal; |
30
|
|
|
|
31
|
1 |
|
public function __construct( |
32
|
|
|
array $config, |
33
|
|
|
RequestHandlerInterface $requestHandler, |
34
|
|
|
MetricsHandlerInterface $metricsHandler, |
35
|
|
|
?LoggerInterface $logger = null |
36
|
|
|
) { |
37
|
1 |
|
$this->config = $config; |
38
|
1 |
|
$this->requestHandler = $requestHandler; |
39
|
1 |
|
$this->metricsHandler = $metricsHandler; |
40
|
1 |
|
$this->logger = $logger ?? new NullLogger(); |
|
|
|
|
41
|
1 |
|
$this->cors = new CORS($config); |
42
|
1 |
|
} |
43
|
|
|
|
44
|
|
|
public function run(LoopInterface $loop): void |
45
|
|
|
{ |
46
|
|
|
$localAddress = $this->config[Configuration::ADDR]; |
47
|
|
|
$this->shutdownSignal = null; |
48
|
|
|
$this->metricsHandler->resetUsers($localAddress); |
49
|
|
|
$loop->addSignal(SIGINT, function ($signal) use ($loop) { |
50
|
|
|
$this->stop($signal, $loop); |
51
|
|
|
}); |
52
|
|
|
$loop->addPeriodicTimer( |
53
|
|
|
15, |
54
|
|
|
fn() => $this->metricsHandler->getNbUsers()->then( |
55
|
|
|
function (int $nbUsers) { |
56
|
|
|
$memory = \memory_get_usage(true) / 1024 / 1024; |
57
|
|
|
$this->logger()->debug("Users: {$nbUsers} - Memory: {$memory}MB"); |
58
|
|
|
} |
59
|
|
|
) |
60
|
|
|
); |
61
|
|
|
|
62
|
|
|
$socket = $this->createSocketConnection($localAddress, $loop); |
63
|
|
|
$this->createServer($socket, $loop); |
64
|
|
|
|
65
|
|
|
$this->logger()->info("Server running at http://" . $localAddress); |
66
|
|
|
$loop->run(); |
67
|
|
|
} |
68
|
|
|
|
69
|
4 |
|
public function handle(ServerRequestInterface $request): ResponseInterface |
70
|
|
|
{ |
71
|
4 |
|
return $this->cors->decorateResponse( |
72
|
4 |
|
$request, |
73
|
4 |
|
$this->requestHandler->handle($request) |
74
|
|
|
); |
75
|
|
|
} |
76
|
|
|
|
77
|
4 |
|
public function __invoke(ServerRequestInterface $request): PromiseInterface |
78
|
|
|
{ |
79
|
4 |
|
return resolve($this->handle($request)); |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
public function getShutdownSignal(): ?int |
83
|
|
|
{ |
84
|
|
|
return $this->shutdownSignal; |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
private function stop(int $signal, LoopInterface $loop): void |
88
|
|
|
{ |
89
|
|
|
$this->shutdownSignal = $signal; |
90
|
|
|
$loop->futureTick(function () use ($loop) { |
91
|
|
|
$loop->stop(); |
92
|
|
|
}); |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
private function createSocketConnection(string $localAddress, LoopInterface $loop): Socket\Server |
96
|
|
|
{ |
97
|
|
|
$socket = new Socket\Server($localAddress, $loop); |
98
|
|
|
$socket->on( |
99
|
|
|
'connection', |
100
|
|
|
function (Socket\ConnectionInterface $connection) use ($localAddress) { |
101
|
|
|
$this->metricsHandler->incrementUsers($localAddress); |
102
|
|
|
$connection->on('close', fn() => $this->metricsHandler->decrementUsers($localAddress)); |
103
|
|
|
} |
104
|
|
|
); |
105
|
|
|
|
106
|
|
|
return $socket; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
private function createServer(Socket\Server $socket, LoopInterface $loop): Http\Server |
|
|
|
|
110
|
|
|
{ |
111
|
|
|
$server = new Http\Server($this); |
112
|
|
|
$server->listen($socket); |
113
|
|
|
|
114
|
|
|
return $server; |
115
|
|
|
} |
116
|
|
|
} |
117
|
|
|
|
This property has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.