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
WIP: Http cache multi-tagging: MVC #1898
Conversation
e95ce6f
to
381ea01
Compare
@@ -302,6 +302,9 @@ services: | |||
- $content.default_ttl$ | |||
tags: | |||
- { name: kernel.event_subscriber } | |||
calls: | |||
- [setConfigurator, ['@ezplatform.http_cache.response_configurator']] | |||
- [setDispatcherTagger, ['@ezplatform.http_cache.response_tagger.dispatcher']] |
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 using setters here, instead of constructor arguments?
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 I didn't want to add them as constructor arguments... 'cause of bit of BC, and because of quantum.
But I agree that this isn't ideal. I had two options in mind:
a) Deprecate this listener (and untag the service ? what is BC supposed to be like on a listener ?), and write a new one
b) add the services at the end in the constructor, and ignore that it is a ugly
c) ... ?
I'm open to suggestions, because I would like to get rid of these calls. In any case, it's not enough even for BC, as I don't test if the configurator is there or not. If it is not, we need to tag using the old approach for BC.
Or am I overthinking 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.
If you want to go the BC way, assuming that this listener is extended by some:
- Create a new class with all you need and make it inherit from the deprecated one
- On the deprecated one, you'll probably need to change visibility on properties
- Trigger deprecation errors from the deprecated one.
- Redefine the service to match the new class
WDYT?
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.
Sounds good to me, I'm on it. Thank you !
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.
😉
Examples: | ||
- (123|456|789) => Purge locations #123, #456, #789. | ||
- .* => Purge all locations. | ||
- If "http" is used, only one Http PURGE request will be sent, with xkey header containing tags to purge seperated by space. |
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.
Will there be a BC somehow with former X-Location-Id
?
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 updated VCL should handle both, as well as SymfonyCache. So yes.
But the MVC layer will only send xkey
once this is merged, not X-Location-Id
. Do you think that this is a problem ?
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.
Note to self: change xkey
to key
.
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.
OK fine then 👍
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.
Removed this changeset from this PR, moved it to the purge client one ( #1894).
/** | ||
* A view that contains relation data. | ||
*/ | ||
interface RelationView |
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 part we considered to rather get users to do from templates / view manually right? As it's not always relevant to tag the relation. If so we would need to start using for instance fos_httpcache_tag.
Reason: Currently we'll tag if there are relations, but ideally it should only be tagged if it is used. (but we still need to tag it here, as we don't want inline calls for it to show up a 404, as opposed to updating this objects view cache to signal that field is updated..)
@andrerom the files you might wanna look in particular are the Taggers:
Hint just in case: the tags are added to the Response by the ResponseCacheConfigurator. That's where we would make the |
64ff00a
to
c340cfd
Compare
Cleaned up and reworked. Removed quite a few superfluous files. We are down to Location and ContentInfo taggers (and their view delegators). Tagging of related content is now done using a |
The CacheViewEventListener is modified to use Taggers and a ResponseCacheConfigurator. The ResponseCacheConfigurator centralizes cache configuration handling for a Response: ``` $configurator->makePublic($response); $configurator->addTags($response, ['location-2', 'content-345']); ``` Any Value Object may have a Tagger. A Tagger can add tags to a Response, by mapping properties from the Value it handles: $tagger->tag($configurator, $response, $content); To add the tags to the Response, Taggers are given the ResponseCacheConfigurator. In addition to Taggers that map values from the value objects, other taggers may extract a value object, and delegate its tagging to another Tagger. One example is ContentView, that is delegated to ContentInfoTagger by the ContentValueViewTagger. This commit also integrates phpspec. The objects defined here are all covered by their own specs, that tries to describe the behaviour that can be expected from them.
2f4e7c8
to
1709db1
Compare
ok, is FOS configured to use the right header somewhere? |
How is this modeled from high level? |
Probably not, good point.
As described in the PR's description :) Short: the HttpCache event subscriber will pass the (Content)View to the DispatcherResponseTagger. The DispatcherResponseTagger will give the View to every tagger. The |
Fixed CS, and added a specification document. |
Replaced by http://github.com/ezsystems/ezplatform-http-cache. Please do not delete the branch yet. |
The objective is to add to Responses from the MVC layer a
xkey
header with the tags matching the value objects they contain. For a typical content view, it would be likexkey: content-1, location-2, content-type-1
.As this value <=> cache tag mapping also applies to REST embedding, the logic must be re-usable by the REST API.
Architecture
It articulates around
ResponseTaggers
. Those will, for a given value object type, add tags to aResponse
. While some may add tags directly (ContentInfoTagger
,RelationTagger
), others will extract one or more value objects from the one they were given, and delegate its tagging to others Taggers (ContentValueViewTagger
,RestContentTagger
).To do the actual tagging, the Taggers are given a
ResponseCacheConfigurator
. This configurator centralizes the cache configuration of the response, included but not limited to thexkey
header name. It can also make the response public, and set the shared max age:The actual tagging is done by the
HttpCacheResponseSubscriber
, that replaces (and deprecates)CacheViewResponseListener
. It uses aConfigurator
and aResponseTagger
. TheResponseTagger
is a special one, theDispatcherTagger
. It has all the tagger services tagged withezplatform.cache_response_tagger
.The listener will tell the dispatcher
ResponseTagger
to tag theResponse
with the View object it gets from the request attributes.Tagging example
Taking ContentView as an example, the call chain is as follows:
Usage in REST
In the current REST embedding implementation, an extra REST controller layer is added so that tags can be added to a
CachedValue
decorator. The controllers implementation contains the tagging logic.The idea is to remove this controller layer, and use the tagger from the
CachedValue
andResourceLink
visitors to tag the HTTP responses.Additional Taggers will be needed to extract actual repository value objects from the REST aggregate value objects (example: RestContent).
PhpSpec
The classes from this feature have been specificed using phpspec, "A php toolset to drive emergent
design by specification.". Please have a look at the execution result from travis, they should explain the architecture above quite well.
The commit adds phpspec, as well as spec-gen, a library that generates code based on specifications.
Testing done
Behat
The pull-request includes three behat scenarios that cover the main lines of content view cache tagging. The sentences are not implemented.
TODO
ResponseCacheConfigurator::makePublic()
and::setSharedMaxAge()
to one::configure()
call. The settings can be used to set bothcache-control
ands-maxage
.xkey
header for cache tags