Last active
December 18, 2015 15:38
-
-
Save polyfractal/5805379 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Naive curl multi-handle implementation. Was only supposed to be a temp function | |
* hence the ugliness | |
*/ | |
public function performRequest($method, $uri, $params = null, $body = null) | |
{ | |
$uri = $this->host . $uri; | |
if (isset($params) === true) { | |
$uri .= '?' . http_build_query($params); | |
} | |
$curlHandle = curl_init(); | |
$opts = array( | |
CURLOPT_RETURNTRANSFER => true, | |
CURLOPT_TIMEOUT => 3, | |
CURLOPT_CONNECTTIMEOUT => 3, | |
CURLOPT_URL => $uri, | |
CURLOPT_CUSTOMREQUEST => $method, | |
); | |
if (isset($body) === true) { | |
$opts[CURLOPT_POST] = true; | |
$opts[CURLOPT_POSTFIELDS] = $body; | |
} | |
// Custom Curl options? Merge them. | |
if (isset($this->connectionParams['curlOpts']) === true) { | |
$opts = array_merge($opts, $this->connectionParams['curlOpts']); | |
} | |
$this->log->addDebug("Curl Options:", $opts); | |
curl_setopt_array($curlHandle, $opts); | |
curl_multi_add_handle($this->multiHandle, $curlHandle); | |
$response = array(); | |
do { | |
do { | |
$execrun = curl_multi_exec($this->multiHandle, $running); | |
} while ($execrun == CURLM_CALL_MULTI_PERFORM && $running === 1); | |
if ($execrun !== CURLM_OK) { | |
$this->log->addCritical('Unexpected Curl error: ' . $execrun); | |
throw new TransportException('Unexpected Curl error: ' . $execrun); | |
} | |
/* | |
Curl_multi_select not strictly nescessary, since we are only | |
performing one request total. May be useful if we ever | |
implement batching | |
From Guzzle: https://github.com/guzzle/guzzle/blob/master/src/Guzzle/Http/Curl/CurlMulti.php#L314 | |
Select the curl handles until there is any | |
activity on any of the open file descriptors. See: | |
https://github.com/php/php-src/blob/master/ext/curl/multi.c#L170 | |
*/ | |
if ($running === 1 && $execrun === CURLM_OK && curl_multi_select($this->multiHandle, 0.001) === -1) { | |
/* | |
Perform a usleep if a previously executed select returned -1 | |
@see https://bugs.php.net/bug.php?id=61141 | |
*/ | |
usleep(100); | |
} | |
// A request was just completed. | |
while ($transfer = curl_multi_info_read($this->multiHandle)) { | |
$response['responseText'] = curl_multi_getcontent($transfer['handle']); | |
$response['errorNumber'] = curl_errno($transfer['handle']); | |
$response['error'] = curl_error($transfer['handle']); | |
$response['requestInfo'] = curl_getinfo($transfer['handle']); | |
curl_multi_remove_handle($this->multiHandle, $transfer['handle']); | |
} | |
} while ($running === 1); | |
// If there was an error response, something like a time-out or | |
// refused connection error occurred. | |
if ($response['error'] !== '') { | |
$this->log->addError('Curl error: ' . $response['error']); | |
throw new TransportException('Curl error: ' . $response['error']); | |
} | |
// Log all 4xx-5xx errors. | |
if ($response['requestInfo']['http_code'] >= 400) { | |
$this->logRequestFail( | |
$method, | |
$uri, | |
$response['requestInfo']['total_time'], | |
$response['requestInfo']['http_code'], | |
$response['responseText'], | |
$response['error'] | |
); | |
// Throw exceptions on 5xx (server) errors. | |
if ($response['requestInfo']['http_code'] >= 500) { | |
$exceptionText = $response['requestInfo']['http_code'] . ' Server Exception: ' . $response['responseText']; | |
$this->log->addError($exceptionText); | |
throw new ServerErrorResponseException($exceptionText); | |
} | |
} | |
$this->logRequestSuccess( | |
$method, | |
$uri, | |
$body, | |
$response['requestInfo']['http_code'], | |
$response['responseText'], | |
$response['requestInfo']['total_time'] | |
); | |
return array( | |
'status' => $response['requestInfo']['http_code'], | |
'text' => $response['responseText'], | |
'info' => $response['requestInfo'], | |
); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* These are the two relevant setup methods for the curlMultiHandleConnection and GuzzleConnection | |
* objects. Both are shared through the Pimple DIC, so a single multi-handle or Guzzle Client | |
* are shared between all the connections. | |
*/ | |
private function setCurlMultihandle() | |
{ | |
// Only used by some connections - won't be instantiated until used. | |
$this->dic['curlMultiHandle'] = $this->dic->share( | |
function () { | |
return curl_multi_init(); | |
} | |
); | |
} | |
private function setGuzzleClient() | |
{ | |
// Only used by Guzzle connections - won't be instantiated until used. | |
$this->dic['guzzleClient'] = $this->dic->share( | |
function () { | |
$guzzle = new \Guzzle\Http\Client(null,array( | |
'curl.options' => array( | |
'body_as_string' => true | |
) | |
)); | |
return $guzzle; | |
} | |
); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Equivalent to performRequest in curlMultiHandleConnection | |
*/ | |
public function performRequest($method, $uri, $params = null, $body = null) | |
{ | |
$uri = $this->getURI($uri, $params); | |
$request = $this->buildGuzzleRequest($method, $uri, $body); | |
$response = $this->sendRequest($request, $body); | |
return array( | |
'status' => $response->getStatusCode(), | |
'text' => $response->getBody(true), | |
'info' => $response->getInfo(), | |
); | |
} | |
/** | |
* @param string $uri | |
* @param array $params | |
* | |
* @return string | |
*/ | |
private function getURI($uri, $params) | |
{ | |
$uri = $this->host . $uri; | |
if (isset($params) === true) { | |
$uri .= '?' . http_build_query($params); | |
} | |
return $uri; | |
} | |
/** | |
* @param string $method | |
* @param string $uri | |
* @param string $body | |
* | |
* @return Request | |
*/ | |
private function buildGuzzleRequest($method, $uri, $body) | |
{ | |
if ($method === 'GET' && isset($body) === true) { | |
$method = 'POST'; | |
} | |
if (isset($body) === true) { | |
$request = $this->guzzle->$method($uri, array(), $body); | |
} else { | |
$request = $this->guzzle->$method($uri, array()); | |
} | |
return $request; | |
} | |
/** | |
* @param Request $request | |
* | |
* @param string $body | |
* | |
* @return \Guzzle\Http\Message\Response | |
* @throws \Elasticsearch\Common\Exceptions\TransportException | |
*/ | |
private function sendRequest(Request $request, $body) | |
{ | |
try { | |
$request->send(); | |
} catch (ServerErrorResponseException $exception) { | |
$this->process5xxError($request, $exception, $body); | |
} catch (ClientErrorResponseException $exception) { | |
$this->logErrorDueToFailure($request, $exception, $body); | |
} catch (CurlException $exception) { | |
$this->processCurlError($exception); | |
} catch (\Exception $exception) { | |
$error = 'Unexpected error: ' . $exception->getMessage(); | |
$this->log->addCritical($error); | |
throw new TransportException($error); | |
} | |
$this->processSuccessfulRequest($request, $body); | |
return $request->getResponse(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* User: zach | |
* Date: 6/14/13 | |
* Time: 11:13 AM | |
*/ | |
namespace Elasticsearch\Benchmarks; | |
use \Athletic\AthleticEvent; | |
use Elasticsearch\Client; | |
class IndexingEvent extends AthleticEvent | |
{ | |
private $setupClient; | |
/** @var Client */ | |
private $client; | |
/** @var Client */ | |
private $guzzleClient; | |
private $document; | |
private $largeDocument; | |
private $mediumDocument; | |
protected function setUp() | |
{ | |
$clientParams = array( | |
'hosts' => array('localhost:9400'), | |
); | |
$this->client = new Client($clientParams); | |
$guzzleParams = array( | |
'hosts' => array('localhost:9400'), | |
'connectionClass' => '\Elasticsearch\Connections\GuzzleConnection' | |
); | |
$this->guzzleClient = new Client($guzzleParams); | |
$indexParams['index'] = 'benchmarking_index'; | |
// Setup code to create the elasticsearch index - does not go through the proxy | |
$this->setupClient = new Client(); | |
$this->setupClient->indices()->create($indexParams); | |
$this->document = array(); | |
$this->document['body'] = array('testField' => 'abc'); | |
$this->document['index'] = 'benchmarking_index'; | |
$this->document['type'] = 'test'; | |
$this->mediumDocument = array(); | |
$this->mediumDocument['body']['testField'] = str_repeat('a', 5000); | |
$this->mediumDocument['index'] = 'benchmarking_index'; | |
$this->mediumDocument['type'] = 'test'; | |
$this->largeDocument = array(); | |
$this->largeDocument['body']['testField'] = str_repeat('a', 1000); | |
$this->largeDocument['index'] = 'benchmarking_index'; | |
$this->largeDocument['type'] = 'test'; | |
} | |
protected function tearDown() | |
{ | |
$indexParams['index'] = 'benchmarking_index'; | |
$this->setupClient->indices()->delete($indexParams); | |
} | |
/** | |
* @iterations 100 | |
*/ | |
public function guzzleSmall() | |
{ | |
$this->guzzleClient->index($this->document); | |
} | |
/** | |
* @iterations 100 | |
*/ | |
public function curlMultiHandleSmall() | |
{ | |
$this->client->index($this->document); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment