Passed
Push — master ( 0432e4...76f962 )
by Marcel
33s
created

ConcurrentServer::batch()   B

Complexity

Conditions 7
Paths 14

Size

Total Lines 42

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 7.2576

Importance

Changes 0
Metric Value
dl 0
loc 42
ccs 19
cts 23
cp 0.8261
rs 8.3146
c 0
b 0
f 0
cc 7
nc 14
nop 1
crap 7.2576
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
 * /!\ Probably NOT fit for production usage.
15
 */
16
class ConcurrentServer extends Server
17
{
18 16
    public function __construct(ContainerInterface $container, int $batchLimit = null)
19
    {
20 16
        if (!\extension_loaded('pcntl')) {
21
            throw new \RuntimeException('ConcurrentServer relies on the pcntl extension');
22
        }
23
24 16
        \pcntl_async_signals(true);
25
26 16
        parent::__construct($container, $batchLimit);
27 16
    }
28
29 6
    protected function batch(Input $input): ?string
30
    {
31 6
        \assert($input->isArray());
32
33 6
        if ($this->tooManyBatchRequests($input)) {
34 1
            return self::end(Error::tooManyBatchRequests($this->batchLimit));
35
        }
36
37 5
        $children = [];
38 5
        $responses = [];
39 5
        foreach ($input->decoded() as $request) {
40 5
            $pair = \stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
41
42 5
            $pid = \pcntl_fork();
43
44 5
            if (0 === $pid) {
45
                \fclose($pair[0]);
46
47
                \fwrite($pair[1], $this->single(Input::fromSafeData($request)) . "\n");
48
49
                \fclose($pair[1]);
50
51
                exit(0);
52
            }
53
54 5
            \fclose($pair[1]);
55
56 5
            $children[$pid] = $pair[0];
57
        }
58
59 5
        foreach ($children as $pid => $socket) {
60 5
            if ('' !== $response = \trim(\fgets($socket))) {
61 4
                $responses[] = $response;
62
            }
63
64 5
            \fclose($socket);
65 5
            \pcntl_waitpid($pid, $status);
66
        }
67
68 5
        return empty($responses) ?
69 5
            null : \sprintf('[%s]', \implode(',', $responses));
70
    }
71
}
72