ParallelClient::sendParallel()   C
last analyzed

Complexity

Conditions 12
Paths 120

Size

Total Lines 65
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 37
CRAP Score 12.5799

Importance

Changes 2
Bugs 1 Features 1
Metric Value
cc 12
eloc 39
c 2
b 1
f 1
nc 120
nop 3
dl 0
loc 65
ccs 37
cts 44
cp 0.8409
crap 12.5799
rs 6.8

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
require_once __DIR__ . "/_prepend.php";
3
4
use PhpXmlRpc\Encoder;
5
use PhpXmlRpc\Client;
6
use PhpXmlRpc\PhpXmlRpc;
7
use PhpXmlRpc\Request;
8
use PhpXmlRpc\Response;
9
10
/// @todo add an html header with links to view-source
11
12
/**
13
 * A class taking advantage of cURL to send many requests in parallel (to a single server), for when the given server
14
 * does not support the system.multicall method
15
 */
16
class ParallelClient extends Client
17 1
{
18
    public function sendParallel($requests, $timeout = 0, $method = '')
19 1
    {
20 1
        if ($method == '') {
21
            $method = $this->method;
22
        }
23
24
        if ($timeout == 0) {
25 1
            $timeout = $this->timeout;
26 1
        }
27
28 1
        $opts = $this->getOptions();
29 1
        $opts['timeout'] = $timeout;
30
31 1
        /// @todo validate that $method can be handled by the current curl install
32 1
33 1
        $handles = array();
34 1
        $curl = curl_multi_init();
35
36 1
        foreach($requests as $k => $req) {
37 1
            $req->setDebug($this->debug);
38 1
            $handle = $this->createCurlHandle($req, $method, $this->server, $this->port, $this->path, $opts);
39 1
            curl_multi_add_handle($curl, $handle);
0 ignored issues
show
Bug introduced by
It seems like $curl can also be of type true; however, parameter $multi_handle of curl_multi_add_handle() does only seem to accept CurlMultiHandle|resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

39
            curl_multi_add_handle(/** @scrutinizer ignore-type */ $curl, $handle);
Loading history...
Bug introduced by
It seems like $handle can also be of type false; however, parameter $handle of curl_multi_add_handle() does only seem to accept CurlHandle|resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

39
            curl_multi_add_handle($curl, /** @scrutinizer ignore-type */ $handle);
Loading history...
40 1
            $handles[$k] = $handle;
41 1
        }
42 1
43 1
        $running = 0;
44 1
        do {
45 1
            curl_multi_exec($curl, $running);
0 ignored issues
show
Bug introduced by
It seems like $curl can also be of type true; however, parameter $multi_handle of curl_multi_exec() does only seem to accept CurlMultiHandle|resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

45
            curl_multi_exec(/** @scrutinizer ignore-type */ $curl, $running);
Loading history...
46 1
        } while($running > 0);
47 1
48
        $responses = array();
49 1
        $errors = array();
50 1
        foreach($handles as $k => $h) {
51 1
            $responses[$k] = curl_multi_getcontent($handles[$k]);
52 1
53
            if ($this->debug > 1) {
54 1
                $message = "---CURL INFO---\n";
55 1
                foreach (curl_getinfo($h) as $name => $val) {
56
                    if (is_array($val)) {
57
                        $val = implode("\n", $val);
58 1
                    }
59
                    $message .= $name . ': ' . $val . "\n";
60 1
                }
61 1
                $message .= '---END---';
62
                $this->getLogger()->debugMessage($message);
63 1
            }
64 1
65 1
            if (!$responses[$k]) {
66
                $errors[$k] = curl_error($h);
67 1
            }
68
69
            //curl_close($h);
70
            curl_multi_remove_handle($curl, $h);
0 ignored issues
show
Bug introduced by
It seems like $curl can also be of type true; however, parameter $multi_handle of curl_multi_remove_handle() does only seem to accept CurlMultiHandle|resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

70
            curl_multi_remove_handle(/** @scrutinizer ignore-type */ $curl, $h);
Loading history...
71
        }
72
        curl_multi_close($curl);
0 ignored issues
show
Bug introduced by
It seems like $curl can also be of type true; however, parameter $multi_handle of curl_multi_close() does only seem to accept CurlMultiHandle|resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

72
        curl_multi_close(/** @scrutinizer ignore-type */ $curl);
Loading history...
73
74
        foreach($responses as $k => $resp) {
75
            if (!$resp) {
76
                $responses[$k] = new Response(0, PhpXmlRpc::$xmlrpcerr['curl_fail'], PhpXmlRpc::$xmlrpcstr['curl_fail'] . ': ' . $errors[$k]);
77
            } else {
78
                $responses[$k] = $requests[$k]->parseResponse($resp, true, $this->return_type);
79
            }
80 1
        }
81
82 1
        return $responses;
83
    }
84 1
}
85 1
86
// a minimal benchmark - use 3 strategies to execute the same 25 calls: sequentially, using parallel http requests, and
87
// using a single system.multiCall request
88 1
89
$num_tests = 25;
90
91
$data = array(1, 1.0, 'hello world', true, '20051021T23:43:00', -1, 11.0, '~!@#$%^&*()_+|', false, '20051021T23:43:00');
92 1
$encoder = new Encoder();
93
$value = $encoder->encode($data, array('auto_dates'));
94
$req = new Request('interopEchoTests.echoValue', array($value));
95
$reqs = array();
96 1
for ($i = 0; $i < $num_tests; $i++) {
97
    $reqs[] = $req;
98 1
}
99 1
100 1
$client = new ParallelClient(XMLRPCSERVER);
101 1
102 1
// avoid storing http info in the responses, to make the checksums comparable
103 1
$client->setDebug(-1);
104 1
105
echo "Making $num_tests calls to method interopEchoTests.echoValue on server " . XMLRPCSERVER . " ...\n";
106
flush();
107 1
108 1
$client->setOption(Client::OPT_NO_MULTICALL,  true);
109
$t = microtime(true);
110 1
$resp = $client->send($reqs);
111 1
$t = microtime(true) - $t;
112 1
echo "Sequential send: " . sprintf('%.3f', $t) . " secs.\n";
113 1
echo "Response checksum: " . md5(var_export($resp, true)) . "\n";
114
flush();
115 1
116 1
if (strpos(XMLRPCSERVER, 'http://') === 0) {
117 1
    $client->setOption(Client::OPT_USE_CURL,  Client::USE_CURL_ALWAYS);
118 1
    $t = microtime(true);
119
    $resp = $client->send($reqs);
120 1
    $t = microtime(true) - $t;
121 1
    echo "Sequential send, curl (w. keepalive): " . sprintf('%.3f', $t) . " secs.\n";
122 1
    echo "Response checksum: " . md5(var_export($resp, true)) . "\n";
123 1
    flush();
124 1
}
125
126 1
$t = microtime(true);
127
$resp = $client->sendParallel($reqs);
128
$t = microtime(true) - $t;
129
echo "Parallel send: " . sprintf('%.3f', $t) . " secs.\n";
130
echo "Response checksum: " . md5(var_export($resp, true)) . "\n";
131
flush();
132
133
$client->setOption(Client::OPT_NO_MULTICALL, false);
134
// make sure we don't reuse the keepalive handle
135
$client->setOption(Client::OPT_USE_CURL,  Client::USE_CURL_NEVER);
136
$t = microtime(true);
137
$resp = $client->send($reqs);
138
$t = microtime(true) - $t;
139
echo "Multicall send: " . sprintf('%.3f', $t) . " secs.\n";
140
echo "Response checksum: " . md5(var_export($resp, true)) . "\n";
141
flush();
142