I had a lengthy conversation with catch today at BADCamp about how we're going to manage the process of getting the moving parts in place for the ESI/subrequest fanciness that we've been building toward. We are going to rejigger the way we're dealing with the various issues, so I'm documenting the roadmap here rather than in any of the specific issues.
The most important point is that catch said very firmly that he considers clean and working partial-page caching (via ESI and similar) to be a release-blocker for Drupal 8. We've done a ton of work so far to enable it, and we cannot release without it or we'll end up with performance regressions in Drupal 8. That, of course, is not acceptable. Therefore, the various moving parts for ESI are not 1 December feature-freeze sensitive, and we don't need to panic about getting them in before then. That allows us to change our strategy a bit. However, I would also appreciate confirmation from Dries and webchick that is the case. (Arguably it's making block caching actually work, and block caching is an existing feature, so it's not a new feature! Or something...)
Rather than put the existing generator code in now, we're going to postpone that on rebuilding path aliasing and output path caching. Therefore, the plan of attack is as follows:
- This is a critical bug, fixed by refactoring the path alias system into properly injectable libraries. Add a null implementation of the Generator, rather than the current implementation in. Update: This is folded into the following task. . That null implementation is useful in that it allows us to wrap the matcher and the null generator into a Router object (a Symfony thing that is really just a combination of a matcher and a generator) With a Router, that gives us interface compatibility with the Symfony CMF Routing component. That means that, once the CMF Routing component merges in the PartialMatcher design we implemented, we can drop our code and use the CMF Routing component 98% verbatim. That gives us a shared routing component between Drupal, Symfony CMF, and ezPublish. Which is just awesome. Update: The CMF Router has been rewritten by Drupalers, and the code to update Drupal to use it is here:
- Once the path alias refactoring is in, we can then enhance the existing generator code to be more fully developed rather than a minimal implementation that is only practically useful for ESI. (See below for details of what that means.)
We will hold off on heavily refactored upstream in Symfony, so we're tracking that closely and will adjust accordingly once the dust settles.for now as well. It may also get deprecated in favor of subclassing HttpKernel::getInternalPath() to hard-code the ESI internal path. TBD. Update: The HttpKernel class is being
Once those are in place (either taking over getInternalPath() or a fully fleshed out generator, or both), we'll be able to issue HttpKernel::render() calls that will sort out themselves whether to use hInclude, ESI, or an in-process subreqest. And that will allow us to finally leverage HTTP itself to handle partial page caching in an intelligent way.
- Switch page caching over to HttpCache, so that we have a consistent cache API for everything.
- Introduce a new way to define partial responses, which could be via subrequest or ESI or whatever else. (This is part of SCOTCH.)
The new, fully-developed generator () will incorporate the url() function as an additional method. Then, it will be modified to accept the event dispatcher as a dependency, allowing it to fire events. It will then fire an event for both route-based lookups and arbitrary URL lookups to allow event listeners to modify the path. Essentially, incorporating hook_url_outbound_alter() into all link generation calls. One of those listeners will be path aliasing, based on the cleaned up component above.
That normally would be a terrible idea for performance, but we are already caching alias lookups smartly. Instead, we'd extend the caching logic (another dependency for the generator) to wrap around all lookups, both route-based and arbitrary URL based. That gives us a single intelligent cache for all outgoing routes, so the typical case is cached with no event listener firing. (They may end up being two separate cache items; implementation detail.) We can then with more or less equal speed generate URLs based on routes or arbitrary links. Sweet.