1
0
mirror of https://github.com/guzzle/guzzle.git synced 2025-02-24 10:03:27 +01:00

Ensuring exceptions are not thrown in pool

This commit is contained in:
Michael Dowling 2014-10-05 23:49:15 -07:00
parent 294f670ad3
commit 87470bf043
4 changed files with 72 additions and 20 deletions

View File

@ -19,7 +19,7 @@ class CancelledFutureResponse extends FutureResponse
*/
public static function fromException(RequestException $e)
{
return new CancelledFutureResponse(new RejectedPromise($e));
return new self(new RejectedPromise($e));
}
public function realized()

View File

@ -3,6 +3,7 @@ namespace GuzzleHttp;
use GuzzleHttp\Event\RequestEvents;
use GuzzleHttp\Message\RequestInterface;
use GuzzleHttp\Message\ResponseInterface;
use GuzzleHttp\Ring\Core;
use GuzzleHttp\Ring\Future\FutureInterface;
use GuzzleHttp\Event\ListenerAttacherTrait;
@ -157,7 +158,9 @@ class Pool implements FutureInterface
// Dereference any outstanding FutureResponse objects.
while ($response = array_pop($this->derefQueue)) {
try {
$response->deref();
} catch (\Exception $e) {}
}
// Clean up no longer needed state.
@ -205,7 +208,7 @@ class Pool implements FutureInterface
callable $onRejected = null,
callable $onProgress = null
) {
return $this->promise->then($onRejected, $onRejected, $onProgress);
return $this->promise->then($onFulfilled, $onRejected, $onProgress);
}
private function coerceIterable($requests)
@ -248,12 +251,13 @@ class Pool implements FutureInterface
$hash = spl_object_hash($request);
$this->derefQueue[$hash] = $response;
// Use this function for both resolution and rejection.
$fn = function ($value) use ($request, $hash) {
unset($this->derefQueue[$hash]);
$this->deferred->progress([
'request' => $request,
'result' => $value
]);
$result = $value instanceof ResponseInterface
? ['request' => $request, 'response' => $value, 'error' => null]
: ['request' => $request, 'response' => null, 'error' => $value];
$this->deferred->progress($result);
$this->addNextRequest();
};

View File

@ -6,6 +6,7 @@ use GuzzleHttp\Event\ErrorEvent;
use GuzzleHttp\Event\CompleteEvent;
use GuzzleHttp\Event\EndEvent;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Ring\Exception\CancelledException;
use GuzzleHttp\Ring\Future\FutureInterface;
/**

View File

@ -3,7 +3,7 @@ namespace GuzzleHttp\Tests;
use GuzzleHttp\Client;
use GuzzleHttp\Event\RequestEvents;
use GuzzleHttp\Exception\CancelledRequestException;
use GuzzleHttp\Message\CancelledFutureResponse;
use GuzzleHttp\Pool;
use GuzzleHttp\Ring\Client\MockAdapter;
use GuzzleHttp\Ring\Future\FutureArray;
@ -173,18 +173,65 @@ class PoolTest extends \PHPUnit_Framework_TestCase
Pool::batch($client, $requests, ['complete' => 'foo']);
}
/**
* This does not throw a cancelled access exception because of the
* cancelled() check in Pool::addNextRequest.
*/
public function testDoesNotAddCancelledResponsesToDerefQueue()
public function testEmitsProgress()
{
$c = $this->getClient();
$req = $c->createRequest('GET', 'http://foo.com');
$req->getEmitter()->on('before', function (BeforeEvent $e) {
CancelledRequestException::create($e->getRequest());
});
$p = new Pool($c, [$req]);
$p->deref();
$client = new Client(['adapter' => function () {
throw new \RuntimeException('No network access');
}]);
$responses = [new Response(200), new Response(404)];
$client->getEmitter()->attach(new Mock($responses));
$requests = [
$client->createRequest('GET', 'http://foo.com/baz'),
$client->createRequest('HEAD', 'http://httpbin.org/get')
];
$pool = new Pool($client, $requests);
$count = 0;
$thenned = null;
$pool->then(
function ($value) use (&$thenned) {
$thenned = $value;
},
null,
function ($result) use (&$count, $requests) {
$this->assertSame($requests[$count], $result['request']);
if ($count == 0) {
$this->assertNull($result['error']);
$this->assertEquals(200, $result['response']->getStatusCode());
} else {
$this->assertInstanceOf(
'GuzzleHttp\Exception\ClientException',
$result['error']
);
}
$count++;
}
);
$pool->deref();
$this->assertEquals(2, $count);
$this->assertEquals(true, $thenned);
}
public function testDoesNotThrowInErrorEvent()
{
Server::flush();
Server::enqueue([new Response(404)]);
$client = new Client();
$requests = [$client->createRequest('GET', 'http://foo.com/baz')];
$c = false;
// "Cancel" the error.
$requests[0]->getEmitter()->on(
'error',
function (ErrorEvent $e) use (&$c) {
$c = true;
$e->intercept(
CancelledFutureResponse::fromException($e->getException())
);
}
);
$result = Pool::batch($client, $requests);
$this->assertTrue($c);
}
}