-
-
Notifications
You must be signed in to change notification settings - Fork 9.5k
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
[RFC] The new Cache component should be a centerpiece feature of Symfony #17537
Comments
Hi @javiereguiluz,
To be honest I don't see why Symfony should provide his own implementation of Cache when a lot of good libraries already exists. Also, components are merged in organisation fast, maybe too fast ... look at Ldap component: tagged as internal and with no docs. Regards, |
@mickaelandrieu thanks for your comments. About the dependency with this component: the default value for |
I don't like the idea of injecting a default cache shared by all services needing a cache. This would mean that each service needing a cache will need to build their cache key with their own unique prefix to ensure there is no conflict with caching done in totally unrelated parts of the app. This is a bad idea as it is far easier to create a mess (which would be undetected until the day you end up with a corrupted cache in prod creating weird bugs) than to get everything right. And regarding the Doctrine case, I don't really agree with you, as Doctrine does not depend on a PSR-6 cache (and won't depend on it AFAIK). Thus, it has some cases with special needs which just cannot suit a typehint against PSR-6 (I'm thinking about the second level cache here for instance). And btw, Doctrine caches rely on being able to use the keys they want. Avoiding conflicts between different caches must be handled by the caches themselves when needed (through namespacing). |
@stof thanks for your comments ... although they go too deep in the code. The namespace problem would be easy to solve. Just append the name of the component (which is unique) to the namespace (e.g. if cache namespace = |
@javiereguiluz but this would still mean you have to use different cache services for each place (configured with a different namespace). You cannot share the cache service between them. The namespace is part of the cache configuration, not of the cache usage. |
@javiereguiluz I'm also interested on benchmarks, if someone in Symfony team is already working on this RFC :) Regarding your proposal on configuration, use a boolean or a string to define cache key make sense. Maybe can we use Others ideas:
|
@stof I'm not aware of the internal details. I just want to answer this question: how can a Symfony developer easily use a cache for all the services of the application? |
@javiereguiluz you cannot easily use the same cache for all services (as you then have to make them all aware that they are not in control of their cache keys, which means you have to implement them in a specific way). Trying to make them use the same cache service is precisely the wrong thing in your proposal. Regarding this issue, there are actually several distinct steps:
Regarding the configuration, what we could imagine is having a framework:
validation:
cache:
enabled: true
template: db
id: ~ # use this instead of template to use your own PSR-6 service for full flexibility The config normalization would allow the |
I like the idea of an central cache because you can extend the cache component with an profiler and a cache tab in the symfony toolbar. the last proposal with enabled: true and template is fine, please do not use cache: true and cache: db together because it is too much magic. Because the cache component is a new feature, it will be released in symfony 3.1. |
This is a fine idea, symfony's current cache setup is byzantine and poorly documented. |
I agree with @stof: having a single cache service makes no sense. Each code needing cache must have its own storage with tailored performance and items segregation. |
I agree with that. The discussion is about: should the developer do everything by hand and result in a verbose config file ... or should Symfony framework help me with this? I want to do this:
And if someday I use Memcache, APCu or whatever, I want to tell Symfony: instead of Redis, use Memcache ... but keep caching everything. |
Symfony could help by providing with an easy to configure, specific interface cache infrastructure. Bundles then can resort to that to implement their own caching strategies. It's the whole point of using a framework. At the moment there's a disconnect in between caching on the framework itself, doctrine and third party bundles. |
What I find useful is if we make it possible to configure some abstract adapters like this: cache:
adapters:
apc:
type: apcu
default_lifetime: 30
tmp:
type: filesystem
directory: /tmp
app_cache:
type: filesystem
directory: %kernel.root_dir%/../var/cache Then in your own services you could inject a special services:
app.some_cool_service:
class: AppBundle\SomeClass
arguments:
- '@cache'
tags:
- name: cache
adapter: apc
namespace: prefix The In the core we could use a similar approach to enable caching for our components: framework:
validator:
cache: apc This configuration would automatically tag a service related to the Validator component. |
i like @xabbuh proposal! 👍 |
@xabbuh I'm not fully convinced by the need of tagging. Would be more straight forward if you could create cache services with the adapter configuration (although I'm not sure if adapters is a good config name here). The following configuration would register two services -
|
@jakzal The drawback is that you would then have to configure one adapter per service that gets injected the cache. Otherwise you would need to take care of the cache prefix/namespace in your custom code. |
Yeah, that's a good thing I think. Tags would be a bit magic. Unless you read the code you don't know it creates a service behind the scenes. Configuring that service instead is more explicit. |
@xabbuh that's an implementation detail. Each cache service prepends a unique prefix silently. We already do that in some places. Example: // Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
if (isset($config['cache']) && $config['cache']) {
$container->setParameter(
'serializer.mapping.cache.prefix',
// next line adds 'serializer_' prefix "automagically"
'serializer_'.$this->getKernelRootHash($container)
); |
The service name is a good prefix candidate btw |
@xabbuh we could configure the components with a cache service and have each component decorate this service with a cache pool that handle the prefixing. |
@javiereguiluz This approach does only work for code that we control in the core. But it does not make sense to let users do the same in their code when they just want to get a cache adapter injected. However, another solution I see is to create a compiler pass that scans every definition for constructor and method arguments that are references and whose referenced service name is something like |
I created #17868 which integrates the Cache component into the FrameworkBundle. It's not finished but I would like to hear your thoughts on it. |
…as-grekas) This PR was merged into the 3.1-dev branch. Discussion ---------- [Cache] Count cache hits/misses in ProxyAdapter | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #17537 partially | License | MIT | Doc PR | - I propose to add this subset of the `Doctrine\Common\Cache\Cache` interface so that we can build data collectors on top and show these stats in the web profiler. ping @javiereguiluz Commits ------- e6f21f9 [Cache] Count cache hits/misses in ProxyAdapter
…h, nicolas-grekas) This PR was merged into the 3.1-dev branch. Discussion ---------- [FrameworkBundle] integrate the Cache component | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #17537 | License | MIT | Doc PR | - Last commit is the diff with #17868. Commits ------- 4152634 [FrameworkBundle] Add default pool & system adapter 714b916 [FrameworkBundle] Add & use Psr6CacheClearer 4740c5c [FrameworkBundle] use abstract cache.pool decoration and aliases 92b1a20 [FrameworkBundle] Fix and add tests for cache pool wiring e44bfdc [FrameworkBundle] Add cache-pool tag and wiring 281eafa [FrameworkBundle] Integrate the Cache component bc51fde [Cache] Normalize constructor arguments order
TL;DR of this issue:
There is a lot of work around the new Cache component lately. But in my opinion, we are not talking about "the big picture" and how to make Cache a centerpiece feature for Symfony. This is how I imagine the Cache component being used in Symfony apps:
Defining application caches
When defining one cache, Symfony names it
default
automatically (same behavior as "swiftmailer" mailers and "doctrine" managers)Complex caches can define arguments:
You can also define lots of different caches in a single app (in this case is mandatory to name one of them
default
):They are available in the application as
cache.default
andcache.db
services.The
cache
service is an alias forcache.default
.Configuring the application caches
Params such as
default_lifetime
andnamespace
are available for any cache type:Using caches in Symfony components
All Symfony components define a
cache
option. Its value can be:true
, thedefault
cache is used:id
of the cache:This cache can also be used for third-party bundles:
Thoughts? Comments? Other ideas?
The text was updated successfully, but these errors were encountered: