-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[VarDumper] Fix dumping by splitting Server/Connection out of Dumper/ServerDumper #27614
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
[VarDumper] Fix dumping by splitting Server/Connection out of Dumper/ServerDumper #27614
Conversation
67478cb
to
18514e5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now green (deps=high needs merge to master), but untested on a real app.
Here are some comments to help @ogizanagi and others review.
|
||
if (!isset($serverDumperHost)) { | ||
$container->getDefinition('var_dumper.command.server_dump')->setClass(ServerDumpPlaceholderCommand::class); | ||
if (!class_exists(ServerDumper::class)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this check is not needed since VarDumper is a mandatory requirement of DebugBundle
|
||
list('name' => $name, 'file' => $file, 'line' => $line, 'file_excerpt' => $fileExcerpt) = $this->sourceContextProvider->getContext(); | ||
|
||
if ($this->dumper) { | ||
if ($this->dumper instanceof Connection) { | ||
if (!$this->dumper->write($data)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is the root of the issue: not being able to know if we wrote anything to the server to set $this->isCollected
correctly
* @param ContextProviderInterface[] $contextProviders Context providers indexed by context name | ||
*/ | ||
public function __construct(string $host, DataDumperInterface $wrappedDumper = null, array $contextProviders = array()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't get why we need to have any wrapped dumper actually. This wrapped dumper currently cannot be configured, it's a hardcoded thing. Looks unneeded to me, is it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you think this isn't useful?
This is the mechanism that allows seamless usage of the server dumper with another dumper as fallback, meaning the behavior is the same as using the wrapped dumper directly when the server is not up.
I don't get what is "hardcoded" here.
$socket = stream_socket_client($this->host, $errno, $errstr, 1, STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT); | ||
|
||
if ($socket) { | ||
if ($socket = stream_socket_client($this->host, $errno, $errstr, 0, STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT | STREAM_CLIENT_PERSISTENT)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the equivalent monolog code connects in async mode, not sure why that's not the case here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had issues with async causing first dumps to not be sent to the server during the time the connection is up (IIRC). This is actually the same for the monolog code, at least when I tested it months ago.
e7ffb40
to
575e072
Compare
if ($connection) { | ||
$connection->write($data); | ||
} | ||
$dumper->dump($data); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it an issue to always write to the local console even when there is a connection?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd say yes. While running tests, it would output twice otherwise.
f544f0c
to
8b49b00
Compare
$this->contextProviders = $contextProviders; | ||
$this->socket = $this->createSocket(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's connect early. That's not an issue since this is async and it lets some time for the connection to be opened (might be useful: this is async)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be enough to workaround the async issue mentioned earlier, but not bullet proof I think.
PR verified on a website-skeleton, works as expected now IMHO. |
<service id="var_dumper.server_dumper" class="Symfony\Component\VarDumper\Dumper\ServerDumper"> | ||
<argument>null</argument> <!-- server host --> | ||
<argument type="service" id="var_dumper.cli_dumper" /> | ||
<service id="var_dumper.server_connection" class="Symfony\Component\VarDumper\Server\Connection"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should it be hidden ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now, we hide only services with "random" names, not sure this PR should be the one changing this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that's true. I'm quite sure I reviewed some PRs hiding some service names. But I'm still fine if the main rule is to hide only "random" names.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't find any with a quick grep
, let's let it as is.
* | ||
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com> | ||
*/ | ||
class ServerDumper implements DataDumperInterface | ||
class Connection |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest marking this class as @internal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the suggested code, marking it @internal
would mean someone using the component out of symfony full-stack cannot reliably wire this in their own application (we're saying them we can break this at any time).
@@ -9,14 +9,16 @@ | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\VarDumper\Dumper\ContextProvider; | ||
namespace Symfony\Component\VarDumper\Server\ContextProvider; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we actually rename these classes in a patch release ? they're not marked on @internal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's my question here yes: are we OK to do with this BC break now, for something that really nobody (or very very few) will have used already? I'd like we answer by "yes"...
Thanks for giving it a look :)
Well, I don't agree. To me, the culprit here really is the |
|
So, I tried again keeping |
Yes I also struggled with the
Hope you're wrong ^^' |
8b49b00
to
220cb20
Compare
220cb20
to
cc05eda
Compare
I reverted the big BC break (there are still some minor on the edges, but this is required for the bugfix and OK for a (failure will be fixed by a merge up to master) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested and code looks good to me, thanks.
However, I encountered an issue that previously didn't exist: at least with php built-in webserver & bin/console server:run
, as soon as the connection is lost (by shutting down the dump server previously up, executing a request and re-uping the server), the server won't get any input as stream_socket_sendto
will throw a "Broken pipe" error.
Steps to reproduce:
bin/console server:run
bin/console server:dump
- make a request calling
dump()
. At this stage, the dump is properly collected by the server. - Shutdown the server.
- Make the same request again.
- Re-up the server (
bin/console server:dump
). Do some more requests. Dumps will never reach the server until you restart the web server.
@@ -29,6 +29,8 @@ | ||
|
||
$server->start(); | ||
|
||
echo "READY\n"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
@ogizanagi I don't reproduce this behavior :( stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR);
+ fclose($this->socket);
+ $this->socket = false; |
It works 👍 |
It works, but only on second request after re-uping the server. Note that commenting the |
cc05eda
to
0d22f42
Compare
I removed the async flag + constructor connection, does it fix it? |
No, it doesn't work at all now, unless you restore a timeout in But honestly, if you want to give a try to async with previous version + patch above, I won't personally mind because I didn't reproduced on a different machine but with very similar env. We may reconsider if we have other reports. Or create another PR for async. |
namespace Symfony\Component\VarDumper\Server; | ||
|
||
use Symfony\Component\VarDumper\Cloner\Data; | ||
use Symfony\Component\VarDumper\Server\ContextProvider\ContextProviderInterface; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-use Symfony\Component\VarDumper\Server\ContextProvider\ContextProviderInterface;
+use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface;
0d22f42
to
ee6a631
Compare
Pushed again, with your patch and the connection in the constructor removed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With typo fixed (and tests ok)
|
||
private function createSocket() | ||
{ | ||
if ($socket = stream_socket_client($this->host, $errno, $errstr, 1, STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC | STREAM_CLIENT_PERSISTENT)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- STREAM_CLIENT_ASYNC
+ STREAM_CLIENT_ASYNC_CONNECT
fc10fd7
to
65dcc8a
Compare
65dcc8a
to
1435d67
Compare
… of Dumper/ServerDumper (nicolas-grekas) This PR was merged into the 4.1 branch. Discussion ---------- [VarDumper] Fix dumping by splitting Server/Connection out of Dumper/ServerDumper | Q | A | ------------- | --- | Branch? | 4.1 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #27622 | License | MIT | Doc PR | - Right now, the `dump()` function is broken on 4.1 as soon as one sets up a `dump_destination` for the dump server (as done by default by our Flex recipe). #27397 describes the issue and proposes a tentative fix. Yet, I think the issue is deeper and exists at the design level. Writting to the server should not happen in a `DumperInterface`, that's not its semantics. Instead, I propose a `Connection` object that will allow `DumpDataCollector` to have all the info it requires to do everything on its own. My bad for not spotting this at the review stage. Commits ------- 1435d67 [VarDumper] Fix dumping by splitting Server/Connection out of Dumper/ServerDumper
Right now, the
dump()
function is broken on 4.1 as soon as one sets up adump_destination
for the dump server (as done by default by our Flex recipe). #27397 describes the issue and proposes a tentative fix. Yet, I think the issue is deeper and exists at the design level. Writting to the server should not happen in aDumperInterface
, that's not its semantics. Instead, I propose aConnection
object that will allowDumpDataCollector
to have all the info it requires to do everything on its own.My bad for not spotting this at the review stage.