Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[HttpClient] add ResponseSetMonitor to trigger callbacks on response completion #32174

Open
wants to merge 1 commit into
base: 4.4
from

Conversation

Projects
None yet
3 participants
@nicolas-grekas
Copy link
Member

commented Jun 25, 2019

Q A
Branch? 4.4
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #32142
License MIT
Doc PR -

Follows some discussions on Slack+Github: how do we trigger callbacks when responses complete?
Here is a quick poc doing so:

$client = HttpClient::create();
$monitor = new ResponseSetMonitor($client);
$monitor->add($client->request(...), $onHeaders, $onBody, $onError);
// [...]
$monitor->tick(); // non-blocking call
// [...]
$monitor->tick(0.001); // don't make the tick last more than 1ms
// [...]
$monitor->complete(); // complete responses and consider timeouts as errors
// [...]
$monitor->cancel() // cancel all pending responses - usually run after a ->tick($someTimeout)

Of course, since there is no event loop under the hood, one still needs to "tick" to move the network read/writes forward.

Useful in the component? If you think so I'd happily accept a PR that adds tests on top :)

@nicolas-grekas nicolas-grekas added this to the next milestone Jun 25, 2019

@nicolas-grekas nicolas-grekas force-pushed the nicolas-grekas:hc-monitor branch from 3419652 to 68c15a0 Jun 25, 2019

@nicolas-grekas nicolas-grekas changed the title [HttpClient] add ResponseMonitor to trigger callbacks on response completion [HttpClient] add ResponseSetMonitor to trigger callbacks on response completion Jun 25, 2019

@nicolas-grekas nicolas-grekas force-pushed the nicolas-grekas:hc-monitor branch from 68c15a0 to 64d54d8 Jun 25, 2019

@nicolas-grekas nicolas-grekas force-pushed the nicolas-grekas:hc-monitor branch from 64d54d8 to 74c2003 Jun 26, 2019

private $onError;
private $responses;
public function __construct(HttpClientInterface $client, callable $onHeaders = null, callable $onBody = null, callable $onError = null)

This comment has been minimized.

Copy link
@lyrixx

lyrixx Jul 9, 2019

Member

IMHO, the onHeaders callable should be the last argument, it's less useful than the body or error.
Same for add method

$onBody($response);
}
if (null === $onBody || $chunk->isLast()) {

This comment has been minimized.

Copy link
@lyrixx

lyrixx Jul 9, 2019

Member

why checking null === onBody ? if it's the last chunk, it should be removed from the responses stack.
IMHO, there is a leak here

$onError = $onError ?? $this->onError;
unset($this->responses[$response]);
if (null !== $onError) {

This comment has been minimized.

Copy link
@lyrixx

lyrixx Jul 9, 2019

Member

if would use a positive if:

if($onError) {
}
}
if (null !== $error) {

This comment has been minimized.

Copy link
@lyrixx

lyrixx Jul 9, 2019

Member

Only the last failed response will throw an error

$remainingTimeout = $timeout;
if (!$errorOnTimeout && $remainingTimeout) {
$startTime = microtime(true);

This comment has been minimized.

Copy link
@lyrixx

lyrixx Jul 9, 2019

Member

Why using a system why startTime when you can decrease remainingTimeout and check when it's <0 ?

foreach ($this->client->stream($this->responses, $remainingTimeout) as $response => $chunk) {
try {
if ($chunk->isTimeout() && !$errorOnTimeout) {
continue;

This comment has been minimized.

Copy link
@lyrixx

lyrixx Jul 9, 2019

Member

The response should be removed from the responses stack

This comment has been minimized.

Copy link
@lyrixx

lyrixx Jul 9, 2019

Member

Okay, got it. The responses is already removed.
Sometimes it is removed, sometimes it it not ¯_(ツ)_/¯
And all stack trace I got are really hard to debug:

PHP Fatal error:  Uncaught Symfony\Component\HttpClient\Exception\TransportException: Couldn't resolve host name for "http://klmfdslmkfksd.com/robots.txt". in /home/rio/rio/server/backend/vendor/symfony/symfony/src/Symfony/Component/HttpClient/Response/CurlResponse.php:264
Stack trace:
#0 /home/rio/rio/server/backend/vendor/symfony/symfony/src/Symfony/Component/HttpClient/Response/ResponseTrait.php(276): Symfony\Component\HttpClient\Response\CurlResponse::perform(Object(Symfony\Component\HttpClient\Internal\CurlClientState), Array)
#1 [internal function]: Symfony\Component\HttpClient\Response\CurlResponse::stream(Array)
#2 /home/rio/rio/server/backend/vendor/symfony/symfony/src/Symfony/Component/HttpClient/Response/CurlResponse.php(121): Generator->current()
#3 /home/rio/rio/server/backend/vendor/symfony/symfony/src/Symfony/Component/HttpClient/Response/ResponseTrait.php(67): Symfony\Component\HttpClient\Response\CurlResponse::Symfony\Component\HttpClient\Response\{closure}(Object(Symfony\Component\HttpClient\Response\CurlResp in /home/rio/rio/server/backend/vendor/symfony/symfony/src/Symfony/Component/HttpClient/Chunk/ErrorChunk.php on line 105

As you can see, I did not see my code. 😢

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.