Completed
Branch concurrent-server (73e3a0)
by Marcel
02:45
created

ConcurrentServer::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2.0185

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 5
cts 6
cp 0.8333
rs 9.9332
c 0
b 0
f 0
cc 2
nc 2
nop 2
crap 2.0185
1
<?php
2
3
declare (strict_types=1);
4
5
namespace UMA\JsonRpc;
6
7
use Psr\Container\ContainerInterface;
8
use UMA\JsonRpc\Internal\Input;
9
10
/**
11
 * Experimental concurrent Server. Needs the pcntl extension,
12
 * therefore it can only work in the CLI SAPI.
13
 */
14
class ConcurrentServer extends Server
15
{
16 16
    public function __construct(ContainerInterface $container, int $batchLimit = null)
17
    {
18 16
        if (!\extension_loaded('pcntl')) {
19
            throw new \RuntimeException('ConcurrentServer relies on the pcntl extension');
20
        }
21
22 16
        \pcntl_async_signals(true);
23
24 16
        parent::__construct($container, $batchLimit);
25 16
    }
26
27 6
    protected function batch(Input $input): ?string
28
    {
29 6
        \assert($input->isArray());
30
31 6
        if ($this->tooManyBatchRequests($input)) {
32 1
            return self::end(Error::tooManyBatchRequests($this->batchLimit));
33
        }
34
35 5
        $children = [];
36 5
        $responses = [];
37 5
        foreach ($input->decoded() as $request) {
38 5
            $pair = \stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
39
40 5
            $pid = \pcntl_fork();
41
42 5
            if (0 === $pid) {
43
                \fclose($pair[0]);
44
45
                \fwrite($pair[1], $this->single(Input::fromSafeData($request)) . "\n");
46
47
                \fclose($pair[1]);
48
49
                exit(0);
50
            }
51
52 5
            \fclose($pair[1]);
53
54 5
            $children[$pid] = $pair[0];
55
        }
56
57 5
        foreach ($children as $pid => $socket) {
58 5
            if ('' !== $response = \trim(\fgets($socket))) {
59 4
                $responses[] = $response;
60
            }
61
62 5
            \fclose($socket);
63 5
            \pcntl_waitpid($pid, $status);
64
        }
65
66 5
        return empty($responses) ?
67 5
            null : \sprintf('[%s]', \implode(',', $responses));
68
    }
69
}
70