Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[HttpFoundation][HttpKernel] Move ServiceResetListener logic to RequestStack #24689

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

Closed
wants to merge 1 commit into from

Conversation

nicolas-grekas
Copy link
Member

@nicolas-grekas nicolas-grekas commented Oct 25, 2017

Q A
Branch? 3.4
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #24554, #24552
License MIT
Doc PR -

As spotted in linked issues, resetting services should happen before running a 2nd request, and not after each one. This fixes collecting late data after kernel.terminate, and frees the CPU from running reset methods when not using the kernel in a loop.
This must happen before the "kernel.request" event is fired so that the event dispatcher can be profiled.
There is no better place than doing so in RequestStack.

@stof
Copy link
Member

stof commented Oct 25, 2017

Doing this in the RequestStack looks weird to me. I don't think it belongs to the RequestStack. It would be more logic to have the Kernel handling it (near the time it pushes a request to the stack).
I think the stack should stay as dumb as possible.

@javiereguiluz
Copy link
Member

I agree with @stof ... this logic looks out of place inside RequestStack. Sadly I can't provide a specific alternative about where to put this.

@nicolas-grekas
Copy link
Member Author

Doing so in the RequestStack is really the correct place, because only it knows when moving from empty to non-empty state. Making this in the Kernel wouldn't be a better fit, because of this (tracking the master request by-flag is less robust.)
But I'm going to move the logic to a decorator.

@nicolas-grekas
Copy link
Member Author

Note that performance-wise, the current code will always be the fastest.

@@ -18,7 +18,7 @@
"require": {
"php": "^5.5.9|>=7.0.8",
"symfony/event-dispatcher": "~2.8|~3.0|~4.0",
"symfony/http-foundation": "^3.3.11|~4.0",
"symfony/http-foundation": "^3.4|~4.0",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

transitively, this is already the lowest version

@nicolas-grekas
Copy link
Member Author

Now refactored as an inheritance proxy so that only HttpKernel knows about the concern.


return;
if (!empty($services)) {
$container->register('request_stack', ResettingRequestStack::class)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we decorate the existing request stack rather than replacing it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to achieve what?

Copy link
Contributor

@ogizanagi ogizanagi Oct 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Someone might already have replaced the request stack by his own, or decorated it for his own needs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, indeed. So I'm going to add a runtime decorating proxy.

Copy link
Member Author

@nicolas-grekas nicolas-grekas Oct 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait no! that's not how decoration works! So there is no issue with it here.
We don't guarantee BC for ppl that just replace services (otherwise we would be in serious trouble moving forward).
So as is is all good, isn't it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A request_stack decorator would just end up with a ResettingRequestStack instance as inner since this pass runs before decoration happens. Seems fine

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright

private $resettableServices;
private $resetMethods;

public function __construct(\Traversable $resettableServices, array $resetMethods)
Copy link
Contributor

@dmaicher dmaicher Oct 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

previously the services were instantiated lazily together with the listener on dispatch of kernel.terminate, right? Seems now the services would be instantiated before the first master request is handled already, even though they are not necessarily all used during the request.

Means now its affecting performance maybe a bit more than before? I mean before at least it was done after the response was streamed back to the client. Now it will delay handling the first request in some cases maybe.

Maybe its possible to do it completely lazy only if they are actually reset (in case there is a second master request)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The iterator yields only instantiated services, so all is fine.

*
* @author Nicolas Grekas <p@tchwork.com>
*/
class ResettingRequestStack extends RequestStack
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could add an interface on the RequestStack and make this extension deprecated in 4.1 to promote composition over inheritance. Should probably also get @final

@derrabus
Copy link
Member

derrabus commented Oct 26, 2017

Just to document my concern I've raised in #24554 already: I don't think that RequestStack is a good extension point. We add a strange side effect to a simple data structure. I really don't feel good about this.

@nicolas-grekas
Copy link
Member Author

@derrabus this is a decorator, not the main stack anymore. A decorator is the typical design pattern to add feature on top of a more basic one. Anyway, please provide an alternative solution, blocking is not enough if we want a fixed beta2.

@iltar we don't need the interface, the inheritance decorator is really fine IMHO.

@nicolas-grekas
Copy link
Member Author

To anyone who voted 👍 or 👎 here, please provide an actual solution instead.

@linaori
Copy link
Contributor

linaori commented Oct 26, 2017

@nicolas-grekas At the moment this is already an extension point, so composition is not properly possible as they would have to extend the new class instead. I'm not using this feature so it doesn't concern me, nor would I touch the request stack in a way where I'd want to modify it by extending. However, it should be considered that others do, as it's public.

@derrabus
Copy link
Member

@nicolas-grekas I did not mean to block anything, I just disagree with your solution. After all, I believe you chose it, not because you found RequestStack to be the best spot for that logic, but because you could not find a better one. So let's try to solve this together.

I've submitted my alternative suggestion as #24697 now.

@nicolas-grekas nicolas-grekas deleted the reset-early branch October 26, 2017 13:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.