How to update specific cached route?

2019-07-29 17:15发布

I am running a Symfony2 app and I have a question about caching.

There is a comment on an answer here in SO that says:

you could create a command that only updates this one cached route. or maybe consider using a kernel event listener that newly registers the route on every request if you can afford the performance impact.

How could I update only this one cached route?

2条回答
Explosion°爆炸
2楼-- · 2019-07-29 17:42

Everything written by nifr is true, but doesn't really help you.
Symfony's built in router designed to support 'static' routes, so on the first cache warmup the routes will be generated and cached. If you check the mentioned cache files you will see that the routes saved in a static private variable.

There is no simple way to update a route (or change routes).

If you check the CacheClearCommand you will see that the implementation is quite complex. Some suggest to delete the whole cache dir, which I don't recommend, it is quite heavy and makes your site hang on until the cache is regenerated (even you can get exceptions of missing files / and logged out users if the sessions saved under the cache folder)

Calling the cache_warmer warmup has no effect if the cache already delegated.

If you just remove the two related cache file and then call the warmUp on the router would be a better solution, but also not nice one..

            $cacheDir = $this->container->getParameter("kernel.cache_dir");
            // Delete routing cache files
            $filesystem   = $this->container->get('filesystem');
            $finder = new Finder();
            /** @var File $file */
            foreach ($finder->files()->depth('== 0')->in($cacheDir) as $file) {
                if (preg_match('/UrlGenerator|UrlMatcher/', $file->getFilename()) == 1) {
                    $filesystem->remove($file->getRealpath());
                }
            }
            $router = $this->container->get('router');
            $router->warmUp($cacheDir);
  • Override the default Router class

As of 2.8 the Router class is defined with a parameter router.class See here: https://github.com/symfony/framework-bundle/blob/v2.8.2/Resources/config/routing.xml#L63

Add something like this to your config.yml

parameters: router.class: "My\Fancy\Router"

You can implement your own Router class, extending the original Router, and also you will need to extend the UrlMatcher and UrlGenerator classes to call the parent implementation and add your own routes to match against / generate with. This way you don't need to refresh the cache, because you can add your routes dynamically.

Note: I'm not sure if you can rely on this on long term, if you check master, the definition has changed, the parameter is not there anymore:

https://github.com/symfony/framework-bundle/blob/master/Resources/config/routing.xml#L54

查看更多
走好不送
3楼-- · 2019-07-29 17:49

Where are cached routes stored?

The cache classes for url matching/generation can be found in app/cache/environment and are called appEnvironmentUrlGenerator.php and appEnvironmentUrlGenerator.php with "environment" being one of dev,prod, .. etc.

API reference:

http://api.symfony.com/2.3/Symfony/Component/Routing/Matcher/UrlMatcher.html http://api.symfony.com/2.3/Symfony/Component/Routing/Generator/UrlGenerator.html

How does it work?

The router service receives a url-matcher and a url-generator when being constructed. Those are then being used inside the match() and generate() methods of the router.

https://github.com/symfony/symfony/blob/2.3/src/Symfony/Component/Routing/Router.php

For warming up the cache the RoutingCacheWarmer uses the router's warmUp() method (if it implements WarmableInterface).

查看更多
登录 后发表回答