Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.7k
[Cache] Symfony PSR-6 implementation#17408
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
a046b58 to42e7c97CompareThere 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 guess you wanted to write $time, and not $expiration
c9d7fae to82324eaCompareandrerom commentedJan 17, 2016
Interesting, like the simplistic approach, and especially that there is only one backend lookup for getItem call. But missing use of multi get / set / (...) to reduce backend roundtrips further on getItems(array) and batch deferred updates. And calls to hasItem and getItem(and opposite) will result in two lookups here, but last point is maybe to be expected given the spec. I know@Nyholm,@aequasi and others have beenworking on this topic, and hope to be able to contribute from eZ as well. Could be an opportunity to join forces. Side: On design side would perhaps opt for following approach:
|
Nyholm commentedJan 17, 2016
Thank you for the ping. I ran this implementation on ourintegration tests and found some issues. Like you do not protect for all the reserved characters and you have forgotten to clear the deferred items on Thephp-cache supports tagging, hierarchal keys and have doctrine bridges in both directions. We are currently outperforming other PSR-6 caches with a factor of 2 and we have ideas for even more performance improvements. We would definitely like to join forces somehow. We are open for a discussion about that. |
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.
implementaton => implementation
b9d7ef8 toc85b7dcComparenicolas-grekas commentedJan 17, 2016
Comments addressed, thank you@Nyholm for the link to the integration test, this will definitely help. |
nicolas-grekas commentedJan 17, 2016
I added testing with cache/integration-tests, I'll look at the failures asap. I already fixed the missing |
Nyholm commentedJan 17, 2016
If the goal is not to replace any existing cache libraries, why build another cache library? Wouldn't it be better if all Symfony components using cache relied on the PSR6 interface and then required the virtual package That way we use the benefit of PSRs and we can let the user decide what cache library to use. If they like to use feature X they install a library with feature X. If they want a strict implementation they would choose a strict implementation. |
fabpot commentedJan 17, 2016
@Nyholm ... and this component is a strict implementation that users can use if they want to, like any other ones. The goal of PSRs (if I get this right) is to allow several implementations with different philosophies, not to standardize on only one. |
Nyholm commentedJan 17, 2016
You are correct. That is the goal of PSRs. But it was this sentence I reacted to:
If the goalis to provide a strict implementation of PSR-6 thatwill replace (or be an option to) any existing library, then I agree that we need this component. Otherwise I do not see the benefits at all. |
fabpot commentedJan 17, 2016
Understood, we definitely want to provide a strict implementation thatcan replace existing libraries :) |
Nyholm commentedJan 17, 2016
Okey, awesome. Im happy to help.@nicolas-grekas do you want PR's with more adapters now or once this is merged? |
nicolas-grekas commentedJan 17, 2016
@Nyholm thank you that's much appreciated. Your test suite is already an amazing help. I think it would be easier to add more adapters after this one has been merge.
I didn't read anything about this in PSR-6, did I miss something? For the other ones, I'll check tomorrow hopefully:
|
dunglas commentedJan 17, 2016
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 do you need to do this?
It breaks the usage ofCacheItemInterface interface used as type hinting.
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.
@blanchonvincent the PSR specifies that implementation are not compatible. So the type hinting is specified by the PSR interface, but the $item MUST be an instance from the same implementation (i.e: I cannot make work my CacheItem from my custom Redis implementation to work with your custom Memcached implementation of CacheItemPool).
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.
You breaking the whole idea of PSR-6 you can interchange multiple libraries together... That's why Interfaces 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.
@GCDS did you read@xavierleune's comment just in top of yours?
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.
From thePSR itself:
Calling Libraries SHOULD NOT assume that an Item created by one Implementing Library is compatible with a Pool from another Implementing Library.
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.
Ahh, sorry I thought differently...
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.
BTW, Interoperability between implementations is possible using something like the attached ProxyAdapter
Nyholm commentedJan 18, 2016
We have given some thoughts in to this. The PSR doc block on Consider this: $item =$pool->getItem('key');$pool->save($item);// Assume this is okey$pool->hasItem('key');// Should return true, yes? Or else, what is the point of saving?/** * Doc block for get(): * If isHit() returns false, this method MUST return null. Note that null * is a legitimate cached value, so the isHit() method SHOULD be used to * differentiate between "null value was found" and "no value was found." * * Doc block for isHit(): * Confirms if the cache item lookup resulted in a cache hit. */$pool->getItem('key')->isHit();// Must be false because "no value was found."// So ...$pool->hasItem('key') !==$pool->getItem('key')->isHit();// This makes no sense. The pool should not have an item that never can be a hit. That would be a stale item and should be removed. |
nicolas-grekas commentedJan 18, 2016
@Nyholm I don't get your example, to me, assuming "key" is not already in the cache: $pool->hasItem('key');// false$item =$pool->getItem('key');$item->get();// null$item->isHit();// false$pool->save($item);// true$item =$pool->getItem('key');$item->get();// null$item->isHit();// true -> a value has been found, we saved it before! |
Nyholm commentedJan 18, 2016
You have not saved any value. Since: "Note that null is a legitimate cached value, so the isHit() method SHOULD be used to differentiate between "null value was found" and "no value was found."" The last two rows in you example: $item->get();// null$item->isHit();// true -> a value has been found, we saved it before! If The point is, |
nicolas-grekas commentedJan 18, 2016
My example above clearly allows to differentiate between a null a "found" vs a null as "not found". Nothing in the spec says that |
ghost commentedJan 18, 2016
@nicolas-grekas Thank you for working on this - it is awesome! We should merge this. |
dunglas commentedJan 18, 2016
+1 to merge it now. It will allow to start migrating metadata systems and other places in Symfony using Doctrine Cache internally to PSR-6. |
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 think it miss
provides: { "psr/cache-implementation": "1.0"},?
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.
@joelwurtz indeed, fixed thanks
fabpot commentedJan 19, 2016
Thank you@nicolas-grekas. |
This PR was merged into the 3.1-dev branch.Discussion----------[Cache] Symfony PSR-6 implementation| Q | A| ------------- | ---| Bug fix? | no| New feature? | yes| BC breaks? | no| Deprecations? | no| Tests pass? | yes| Fixed tickets | -| License | MIT| Doc PR | -From the provided README.md:This component provides a strict [PSR-6](http://www.php-fig.org/psr/psr-6/) implementation for adding cache to your applications. It is designed to have a low overhead so that caching is fastest. It ships with a few caching adapters for the most widespread and suited to caching backends. It also provides a `doctrine/cache` proxy adapter to cover more advanced caching needs.Todo:- [ ] add more tests- [ ] add a FilesystemAdapterCommits-------91e482a [Cache] Symfony PSR-6 implementation
Tobion commentedJan 19, 2016
IMO namespaces handling should be a separate decorator and not built into the adapter directly. Seedoctrine/cache#96 |
Tobion commentedJan 19, 2016
I also want to express my objections against the recent fast merges of new components. This was merged in less than two days which does not give enough time to review and discuss a full new component at all. Also it's against our own rules which says
I hope it's not going to be of the same quality as the LDAP component. |
andrerom commentedJan 19, 2016
True, it probably should be, but also a bit of a orange to apple comparison. In doctrine this is a namespace kept in cache and that needs to be checked on every cache lookup, that is not the case here(luckily, the extra cache lookup adds overhead, use case can be covered by tagging instead to avoid it). |
nicolas-grekas commentedJan 19, 2016
@Tobion sorry if you feel uncomfortable, we merged quickly that's true... I invite you to open a PR to move the namespace concept in it's own decorator if you think it's better (taking@andrerom into account). The component will see more enhancements until 3.1 is released, but at least we don't have to discuss about its interfaces, which makes the situation totally different from the Ldap component hopefully. |
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 not aconst?
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 a const is public...
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.
@internal? Or a private static property? This one looks a bit weird.
aurimasniekis commentedJan 19, 2016
My suggestion for namespace would be to let Adaptor generate key with a namespace. For e.g. most Redis tools groups keys if they have |
nicolas-grekas commentedJan 19, 2016
@GCDS namespace (or prefix really) are already managed by adapters (they must deal with it in their constructor). Which means a Redis adapter could do whatever you'd need there. To me, the simple prefixing logic is rightfully in the abstract, because adding a prefix is really something common. Doing namespaces àla doctrine/cache is for a decorator, or at least not for the abstract, I agree. |
aurimasniekis commentedJan 19, 2016
Ahh yeah, sounds correct to me :) |
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.
What about adding a constructor toCacheItem marked with@internal? It will be easier to understand. (Currently even PHPStorm isn't able to interpret this snippet and marks it in red).
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.
Btw it will remove the duplication of this factory closure inProxyAdapter.
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 preferred raw speed over phpstorm compliance: a constructor would slow down things for no valid reason (adding one function call in the chain). I doubt@internal would be enough to prevent erroneous user side instantiation. The current no-constructor-nor-setter (for key and isHit) means we technically annoy users enough so that they are free to missuse but forced to think about it :)
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.
Isn't a constructor call or a closure call in the chain similar in term of perfs?
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 of course, but making the constructor public has drawback IMHO (as detailed above). This drawback could be fixed by using a private constructor + a rebound closure, which is when an additional function call comes up. That's what I meant :)
From the provided README.md:
This component provides a strictPSR-6 implementation for adding cache to your applications. It is designed to have a low overhead so that caching is fastest. It ships with a few caching adapters for the most widespread and suited to caching backends. It also provides a
doctrine/cacheproxy adapter to cover more advanced caching needs.Todo: