-
Notifications
You must be signed in to change notification settings - Fork 84
Have a method to add tags to the TagSubscriber directly #182
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
Conversation
I think we should add the Twig function here. Do you want to do so here or in a separate PR? |
i'd rather do a separate PR. not good to keep PRs open longer than needed... |
.. tip:: | ||
|
||
If you do not yet have the response available, you can use the | ||
``TagListener::addTags($tags)`` method to have your tags added once the |
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.
TagSubscriber
This makes the subscriber stateful for something tied to a given Request, which is a bad idea IMO. It means it is now impossible to handle several requests with your kernel without shutting it down between requests (to drop the container and build a new one). |
@@ -63,12 +86,16 @@ public function onKernelResponse(FilterResponseEvent $event) | |||
{ | |||
$request = $event->getRequest(); | |||
$response = $event->getResponse(); | |||
|
|||
$tags = array(); | |||
if ($request->isMethodSafe()) { |
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 having a different logic for safe responses ?
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.
because on unsafe methods, the tags will be invalidated rather than added to the response (unsafe responses are not cached)
when invalidating, the user should directly call the tag invalidation rather than add them here. but we could either accept them here anyways, or throw an error if there are any because its the wrong way to do things.
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.
@ddeboer what do we want to do about this? allow to invalidate tags by adding them to the tagHandler in an unsafe request, or throw an exception in this case and tell that to invalidate the user should explicitly call invalidate?
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 prefer the exception, for I suspect it gets confusing to users if we let addTags()
do invalidation too. The distinction makes sense: you have only one response during the request/response cycle that you want to set exactly the right set of tags on. While invalidating, however, you can just call invalidateTags()
with some tag(s), and later in the cycle call it again with some other tag(s).
@stof Good point. Do you have any suggestion as to how we could offer this functionality (tagging responses when they’re not yet available) without introducing a stateful service? |
$tags = array(); | ||
if ($request->isMethodSafe()) { | ||
$tags = $this->tags; | ||
$this->tags = 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.
this was my attempt to avoid adding the tags again on the next request. but the else case should also empty them (or do an error, see above).
could we end up with a mixup on subrequests? at least with ESI, each request is sent before the next is done so this should be enough.
do subrequests inside symfony (twig calling a controller and those) trigger the response event? if they do, are the headers of the responses merged? if not, we already have a problem with the current 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.
while i agree that becoming stateful is not elegant, i don't see a better option. would we need a TagStack or something where we push and pop when subrequests are triggered?
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.
@stof do you have a better suggestion how to do this, or how to avoid statefullness alltogether?
313bf04
to
12e4467
Compare
so, what are we going to do? @stof sorry for prodding, but is resetting the tags good enough? or do you have a better idea what we could do? |
Resetting the tags is wrong, because the controller for the master request is likely to be called before the subrequest, and your logic would then add these headers on the response of the subrequest triggered in the template instead of adding it on the master response. IMO, a solution could be to associate the tags to the current request when setting them (getting the current request from the RequestStack for Symfony 2.4+ and using a setter for the request on 2.3 thanks to the synchronized services to keep the support for the LTS release). Then, in the kernel.response even, you would get the tags associated to the Request available in the event (and then drop them from the storage because they won't be needed anymore) |
All right, so let’s try to group tags by the response they should be applied to. |
yeah, i wanted to look into that, but realized it would make a lot more sense to do that in a TagHandler than adding more non-event things into the Tag event listener class and started with FriendsOfSymfony/FOSHttpCache#162 as precondition. |
I guess this can be finished now, since FriendsOfSymfony/FOSHttpCache#162 and FriendsOfSymfony/FOSHttpCache#171 have been merged. |
12e4467
to
41d4c34
Compare
|
||
Use ``tagResponse($response, $tags)`` to set tags on a response:: | ||
Inject the ``CacheManager`` (service ``fos_http_cache.cache_manager``) and |
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.
TODO: adjust the doc to the new architecture
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.
Todo still open?
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.
so i propose that we only tag the response to the master request as we otherwise lose the tags of subrequests. note that this will be a behaviour change for existing features: the tag annotation in the subrequest gets lost in the 1.2 bundle. i think the new behaviour is correct and consider the other thing a bug. |
Then call ``invalidateTags($tags)`` to invalidate the tags you set:: | ||
Or inject the ``TagSubscriber`` (service ``fos_http_cache.event_listener.tag``) | ||
and call ``addTags($tags)`` to set tags that will be added to the response once | ||
it exists:: |
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.
“Or if you have no access to a Response object inject…”
👍 |
@@ -86,8 +113,13 @@ public function onKernelResponse(FilterResponseEvent $event) | |||
} | |||
|
|||
if ($request->isMethodSafe()) { | |||
// For safe requests (GET and HEAD), set cache tags on response | |||
$this->cacheManager->tagResponse($response, $tags); | |||
if ($event->isMasterRequest()) { |
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.
argh, this is only available in symfony 2.4+, but not 2.3. i will fix that line to work with 2.3
@stof do you agree that we tag only on response to master request, not response to subrequests (you talked about using the request stack and associate tags with requests). it seems to me to make no sense to ever tag a response to a subrequest, as the headers of those responses are simply discarded. |
fb89e32
to
594625f
Compare
@@ -67,6 +67,8 @@ public function setGenerateUrlType($generateUrlType) | |||
* response | |||
* | |||
* @return $this | |||
* | |||
* @deprecated Add tags with TagHandler::addTags and then use TagHandler::tagResponse |
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 go to the TagHandler here. so people who mix up new and old things might get into troubles. but otherwise we complicate things quite a bit.
*/ | ||
public function __construct(CacheManager $cacheManager = null, $commandName = 'fos:httpcache:invalidate:tag') | ||
public function __construct(TagHandler $tagHandler = null, $commandName = 'fos:httpcache:invalidate:tag') |
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.
if people defined their own service for the InvalidateTagCommand or extended the command, this is a BC break. do we care about it or can we assume this an edge case? if we care, what are alternatives that make sense?
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.
we can keep the BC method of CacheManager of course, but people using the new TagHandler then will be just as confused.
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 BC way would be to allow both CacheManager and TagHandler as constructor arguments, check the type and throw an exception if it is neither of both.
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.
594625f
to
7df5eb3
Compare
// For non-safe methods, invalidate the tags | ||
$this->cacheManager->invalidateTags($tags); | ||
$this->tagHandler->invalidateTags($tags); |
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 a bit of a weird interaction with the tag handler:
- for tagging the response, the only way to go is to do $tagHandler->addTags($tags); $tagHandler->tagResponse($response);
- for invalidating, the only way to go is to $tagHandler->invalidateTags($tags);
so tagging a response is only possible from the values in the handler, invalidating is only possible with outside tags.
also, as we have no way to reset the tags on tagResponse, we will keep the tags in the handler and if there is ever more than one response sent, tags will accumulate. should we add a reset method to the tagHandler and trigger that reset in tagResponse?
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.
Yes, this is unfortunate. It’s due to the TagHandler
having two (albeit closely related) responsibilities instead of one: both tagging safe responses and invalidating unsafe ones. I don’t see how we can clear this up without splitting the class into two, which may be overkill.
As for resetting: is our current TagHandler
suitable for tagging multiple responses? Magically resetting between tag actions may also be confusing if a user wants to tag two responses identically.
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 lets wait for a concrete use case and for now keep it with this flaw.
@ddeboer had another go on this. i think things are shaping up, i added some comments on the code. glad for some feedback / opinion so that we can wrap this up. |
@ddeboer ping |
d3c3709
to
7eaffe9
Compare
only open point i can see now is whether we want to have something more elegant than when we clear that, i can squash the commits and we can merge. |
@@ -22,7 +22,7 @@ | |||
], | |||
"require": { | |||
"php": ">=5.3.3", | |||
"friendsofsymfony/http-cache": "~1.2", | |||
"friendsofsymfony/http-cache": "~1.3", |
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.
Needs FriendsOfSymfony/FOSHttpCache#190 so tag 1.3.2 and change this to ~1.3,>=1.3.2
7eaffe9
to
612bcc6
Compare
depend on fos httpcache 1.3.2 or newer, squashed commits. if travis is happy, this is now ready to merge. |
612bcc6
to
c72bb68
Compare
Small doc issue in the build. |
c72bb68
to
6853411
Compare
… request does not exist yet
6853411
to
712de49
Compare
now its green. |
Have a method to add tags to the TagSubscriber directly
Great, thanks! |
This is useful to tag responsens when the response object does not yet exist or is not known.
This solves part of #181
@ddeboer do you want me to add a twig extension to tag responses from inside twig templates here? or should we provide that from SymfonyCmfHttpCacheBundle rather? the cmf bundle will extend it to handle doctrine objects in addition to just strings.
TODO