Yet another cache proposal

705 views
Skip to first unread message

Florin Patan

unread,
Dec 1, 2012, 2:41:23 PM12/1/12
to php...@googlegroups.com
In an attempt to unify the proposals as well as some information from real life scenarios,
I've created the following proposal for caching interfaces: 

Please review it and help me improve it so that at some point we could vote on this matter
and give the community a direction for this matter.

Thank you for your time and support!


Best regards.

Robert Lemke

unread,
Dec 21, 2012, 4:47:20 AM12/21/12
to php...@googlegroups.com
Hi Florin,

thank you for picking up that topic.

I would like to point you to the cache implementation of TYPO3 Flow [1]. It has been in use for quite some time and mostly differs from you proposal in these aspects:

- separation between cache frontend and backend to allow for speed optimization with certain frontends (e.g. no serialize necessary if straight value can be stored)
- cache backends provide differing capabilities, for example some can be frozen, some can be used for storing PHP code which can be required() right through the backend
- cache entries are taggable
- caches can be frozen (that is, put into an optimized read-only mode)

And some more features we learned to love ...

It's certainly not possible to put all of these features into a standard, but especially the separation between frontend and backend has become quite handy.

Best,
Robert

Fabien Potencier

unread,
Dec 21, 2012, 5:09:33 AM12/21/12
to php...@googlegroups.com
On 12/21/12 10:47 AM, Robert Lemke wrote:
> Hi Florin,
>
> thank you for picking up that topic.
>
> I would like to point you to the cache implementation of TYPO3 Flow [1].

Is it available as a Composer package? I've just had a look and it does
not seem to be.
> --
> You received this message because you are subscribed to the Google
> Groups "PHP Framework Interoperability Group" group.
> To post to this group, send email to php...@googlegroups.com.
> To unsubscribe from this group, send email to
> php-fig+u...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/php-fig/-/6I3kHVVXXs0J.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

Robert Lemke

unread,
Dec 21, 2012, 5:12:53 AM12/21/12
to php...@googlegroups.com
Hi Fabien,

On 21.12.2012, at 11:09, Fabien Potencier <fabien.p...@gmail.com> wrote:

>> I would like to point you to the cache implementation of TYPO3 Flow [1].
>
> Is it available as a Composer package? I've just had a look and it does not seem to be.


It is part of typo3/flow [1]. However, if there is there is some broader interest, I could imagine extracting it into a dedicated package and probably also removing remaining dependencies on the Flow core - I'd need to check what that would imply though.

Cheers,
Robert

[1] https://packagist.org/packages/typo3/flow

--
Robert Lemke
Lead Developer TYPO3 Neos and TYPO3 Flow
Co-Founder TYPO3 Association

Blog: robertlemke.com/blog
Get involved: typo3.orgflow.typo3.orgneos.typo3.org





Florin Patan

unread,
Dec 21, 2012, 7:42:01 AM12/21/12
to php...@googlegroups.com
Hi Robert,


I'll take a look at TYPO3 Flow for sure, thanks for pointing it out.
Can you describe the uses cases and how you reached to the need of those features so we could have a overview/starting point for talking about them?
Unfortunately I haven't used TYPO3 Flow nor did I had a need for those features until now, with locking being an exception, so my research might not reflect actual practice.


Best regards,
Florin

Robert Lemke

unread,
Dec 21, 2012, 8:13:18 AM12/21/12
to php...@googlegroups.com
Hi Florin,

On 21.12.2012, at 13:42, Florin Patan <flori...@gmail.com> wrote:

I'll take a look at TYPO3 Flow for sure, thanks for pointing it out.
Can you describe the uses cases and how you reached to the need of those features so we could have a overview/starting point for talking about them?
Unfortunately I haven't used TYPO3 Flow nor did I had a need for those features until now, with locking being an exception, so my research might not reflect actual practice.

yes, sure - I'll be brief though, cause I'm about to leave for holidays ;-)

Tagging:

Given you want to cache some rendered content about a customer and two metrics. There might also be other caches containing information about that customer. If you tag all cache entries containing information about that customer with his customer number, you can globally flush cache entries by that tag if the customer was modified or removed. There are some more use cases, but I hope you get the idea.

Frontends:

Our frontends conveniently serialize content (simple types, objects, object trees ...) before it is stored in the cache. If you know that you'll only store string values, you can use a specialized frontend for that which doesn't try to serialize the content. With the specialized PhpFrontend you can store and include PHP code:

$cache->set('MyPhpCode', '<?php class Foo { .... } ?>');
...
$cache->requireOnce('MyPhpCode');

Freezable Backends:

Our cache backends will check if an entry is expired while it is fetched. This causes a little overhead in some backends (for example the FileBackend). If you are sure that you only fill the cache once and then leave it as is (for example, for code caches), you can freeze a cache for better performance.

Apart from that we have some semi-complete documentation here (lacking the latest features from the upcoming 2.0 release):


Hope that helps!

Cheers,
Robert

Florin Patan

unread,
Dec 26, 2012, 6:04:24 PM12/26/12
to php...@googlegroups.com, rob...@typo3.org
I've made some changes to the proposal, specifically to the extended version, which you can view here:

I do see the reasons of why one should have locking, namespaces and tags into a caching implementation, but I think this should be a good starting point for a discussion.
What features do current caching methods support and what are the features that are really needed by the existing/future implementations.

There's a section on the GitHub PR, https://github.com/php-fig/fig-standards/pull/63, called "Lack of certain features, see tagging, namespace or locking" which should help you understand why I've skipped these features from the original proposal but by no means it should be viewed as a unchangeable thing.

I'll give more thinking about splitting caches into backend/frontend and so on but I think this is more of implementation detail rather that something that should be standardized via this PR. Grouping caching areas like this wouldn't make sense for simple libraries for example imho.

Jason Judge

unread,
Dec 27, 2012, 12:39:49 PM12/27/12
to php...@googlegroups.com, rob...@typo3.org
The getByNamespace() method includes a parameter $includingChildren. Does that really mean just children, or does it refer to all descendant namespaces too? I suspect it is the latter.

-- Jason

Florin Patan

unread,
Dec 27, 2012, 12:48:25 PM12/27/12
to php...@googlegroups.com, rob...@typo3.org
If you set the $includingChildren parameter to true then the driver will retrieve the children as well as the objects specified in the main namespace.


-- Florin

Handrus Nogueira

unread,
Dec 27, 2012, 12:55:17 PM12/27/12
to php...@googlegroups.com, rob...@typo3.org
I believe Jason was asking if the children of the children (and so on) would be retrieved as well.


2012/12/27 Florin Patan <flori...@gmail.com>
--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To post to this group, send email to php...@googlegroups.com.
To unsubscribe from this group, send email to php-fig+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/vmwXgb2F3iMJ.

For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Handrus Stephan Nogueira

Florin Patan

unread,
Dec 27, 2012, 1:08:59 PM12/27/12
to php...@googlegroups.com, rob...@typo3.org
Yes, all children must be retrieved.

We could have a depth parameter instead that controls the level of nesting before we stop retrieving objects BUT like I've said in the GitHub PR, supporting this would cause a large headache for storing engines that don't provide/can't emulate this easily, I'm thinking right now on Memcached/Redis/APC mainly. You could sort of do it in MongoDB/other NoSQL solutions or with files but I'm not aware of such a solution currently.

This is why I want to first have things clarified about need for locking (which can be relatively easily done in all current solutions), tags and namespaces (harder things to implement safe for (No)SQL solutions) or anything else I might have skipped.

--Florin

Jason Judge

unread,
Dec 27, 2012, 6:34:06 PM12/27/12
to php...@googlegroups.com, rob...@typo3.org


On Thursday, 27 December 2012 18:08:59 UTC, Florin Patan wrote:
Yes, all children must be retrieved.

We could have a depth parameter instead that controls the level of nesting before we stop retrieving objects BUT like I've said in the GitHub PR, supporting this would cause a large headache for storing engines that don't provide/can't emulate this easily, I'm thinking right now on Memcached/Redis/APC mainly. You could sort of do it in MongoDB/other NoSQL solutions or with files but I'm not aware of such a solution currently.

My point, in case I wasn't clear, is that the common understanding of "children" is that it is a depth of just one. Children are just the first level in the list of descendants. Your children's children are not your children. It was just a relatively minor point about the language being used, as it could mislead. To say all children must be retrieved, does not say anything about the depth of descendants.

Anyway, it could be that I have misunderstood, but I just thought it should be pointed out. It was just a point of language and not about functionality.
 

Lukas Smith

unread,
Dec 27, 2012, 7:05:59 PM12/27/12
to php...@googlegroups.com, rob...@typo3.org

On Dec 28, 2012, at 24:34 , Jason Judge <jason...@consil.co.uk> wrote:

>
>
> On Thursday, 27 December 2012 18:08:59 UTC, Florin Patan wrote:
> Yes, all children must be retrieved.
>
> We could have a depth parameter instead that controls the level of nesting before we stop retrieving objects BUT like I've said in the GitHub PR, supporting this would cause a large headache for storing engines that don't provide/can't emulate this easily, I'm thinking right now on Memcached/Redis/APC mainly. You could sort of do it in MongoDB/other NoSQL solutions or with files but I'm not aware of such a solution currently.
>
> My point, in case I wasn't clear, is that the common understanding of "children" is that it is a depth of just one. Children are just the first level in the list of descendants. Your children's children are not your children. It was just a relatively minor point about the language being used, as it could mislead. To say all children must be retrieved, does not say anything about the depth of descendants.
>
> Anyway, it could be that I have misunderstood, but I just thought it should be pointed out. It was just a point of language and not about functionality.

in other words it seems instead of "includingChildren" it should be named "includingDecendants" or rather "includeDecendants".
as for depth, imho we should add that, but make its implementation optional.

regards,
Lukas

Florin Patan

unread,
Dec 30, 2012, 3:56:57 PM12/30/12
to php...@googlegroups.com, rob...@typo3.org
I'm not sure why the implementation should be optional or even how we could have that implementation optional.
I think that by having the depth parameter directly instead of a boolean parameter would make more sense for the users as they would know what to expect from it.


Best regards and Happy Holidays!

André R.

unread,
Jan 4, 2013, 4:18:17 PM1/4/13
to php...@googlegroups.com
[ To get this going I would like to suggest that we discuss the common Interface first (PR #63), and discuss the followup extended interfaces (PR #not-yet): namespaces, tagging & depth later (in another thread).  ]


First, thanks for restarting this cache discussion, much appreciated!

Some comments on PR #63:
  1. I don't quite see the need for both a CacheItem & the &$exists param, the Item can either have a isValid() method, or get() can return null if there is no value (aka no cache item). Both alternatives would make sure BatchDriverInterface->getMultiple() gets this exists capability as well.
  2. A good step in right direction on removing constructors from the interfaces, but as mentioned in the PR I would even remove setCacheDriver(DriverInterface $cacheDriver); as a proxy implementation might take several drivers in it's constructor and allow for built in support for cache hierarchies, avoiding user code to have to deal with this like in the PR description example and the options example by @schmittjoh.
  3. hasSerializationSupport() is defined on both DriverInterface and BatchDriverInterface.
  4. Is hasSerializationSupport() need in the first place? We could also require that drivers need to handle this transparently, making them choose the best serializer available for the driver and making setSerializer() and related user code logic for this unneeded.
  5. I might have misunderstood but it should be documented that ItemInterface is a value/naked object, and no backend calls will be executed on it's set* & get* methods. If this is true, Item could be a class with properties instead of interface with methods, enforcing no logic.
  6. Is DriverInterface->set() $lifeTime a ttl? or a timestamp?
  7. Do we need the metadata functions on the basic / common cache interfaces? What is the use case and how is it supposed to be stored by the driver? (ignore last question if assumptions in 8 are correct)
  8. * I might have misunderstood something else as well, but it seems like the proxy will always have to store a hash value with the 'value', '_ttl' and '__expires' keys in addition to other meta data to be able to populate the CacheItem, if this is the case then &$exists can effectively be removed from DriverInterface->get() as false is not a valid value for CacheProxies.

Florin Patan

unread,
Jan 4, 2013, 5:39:29 PM1/4/13
to php...@googlegroups.com
Thanks for posting this here André.

Please see my comments below:

On Friday, January 4, 2013 11:18:17 PM UTC+2, André R. wrote:
[ To get this going I would like to suggest that we discuss the common Interface first (PR #63), and discuss the followup extended interfaces (PR #not-yet): namespaces, tagging & depth later (in another thread).  ]
 
That's the reason I've split the interfaces into two proposals but kept them in a single branch.
While there's a need for those 'advanced' features, there's really not much support for them, safe for maybe locking which can be done relatively easily in any system that I can think of.
If people are ok with having this topic split then more on the 'advanced' features could be discussed when the time for them will come.

First, thanks for restarting this cache discussion, much appreciated!

Some comments on PR #63:
  1. I don't quite see the need for both a CacheItem & the &$exists param, the Item can either have a isValid() method, or get() can return null if there is no value (aka no cache item). Both alternatives would make sure BatchDriverInterface->getMultiple() gets this exists capability as well.
 The reason for this is to make it more APC::fetch look-alike. On the other hand NULL would indeed make sense as it allows further features, see below, so I'll change this.
  1. A good step in right direction on removing constructors from the interfaces, but as mentioned in the PR I would even remove setCacheDriver(DriverInterface $cacheDriver); as a proxy implementation might take several drivers in it's constructor and allow for built in support for cache hierarchies, avoiding user code to have to deal with this like in the PR description example and the options example by @schmittjoh.

I wanted to have a feedback from at least one more person in regards to this.
We could have the method changed to:
addCacheDriver(DriverInterface $cacheDriver, $priority = 100, $overwriteExisting = false); 

In this case $priority could be just about any integer as there's no need add limits. We'll just need to specify that the value is extracted in the highest priority order.
Since I'm not sure what happens when you want to add another driver with the same priority an existing one I've added the $overwriteExisting for it in the signature but I think that we should discard it and use overwrite as default procedure. Any thoughts on this? 

  1. hasSerializationSupport() is defined on both DriverInterface and BatchDriverInterface.
 
Thanks! Copy paste isn't that good sometimes :) 

  1. Is hasSerializationSupport() need in the first place? We could also require that drivers need to handle this transparently, making them choose the best serializer available for the driver and making setSerializer() and related user code logic for this unneeded.

The reason for it is so that you can inject your serializer if you want to, making the drivers more compatible with each-other across implementations. It indeed brings some problems and more code to user-land. We can drop it altogether if there's no need for it. It's always easier to delete rather that add. 
 
  1. I might have misunderstood but it should be documented that ItemInterface is a value/naked object, and no backend calls will be executed on it's set* & get* methods. If this is true, Item could be a class with properties instead of interface with methods, enforcing no logic.

You got it right, there shouldn't be any logic in the Item in regards to backend calls BUT, for example, you could chose to provide more metadata functionality, like having a method called increaseRefreshCount() so that you can control the number of times the object was refreshed in the main priority cache backend before you perform logic on it, like a full refresh of the item in all cache backends.

It would indeed be possible to have this with a class by extending it but I'm not sure how FIG should provide code like this. There's some discussion in the other threads about this topic so maybe a by-law should be considered to have a clear direction for this.
 
  1. Is DriverInterface->set() $lifeTime a ttl? or a timestamp?

Most common case is a TTL in seconds so but I'll need to add this to the specs. The Item should store the timestamp of the save moment as well in order to have a way to compute the expiration time.  

  1. Do we need the metadata functions on the basic / common cache interfaces? What is the use case and how is it supposed to be stored by the driver? (ignore last question if assumptions in 8 are correct)

I'm not sure there's a need for metadata in the existing systems for simple use cases. It was added with the purpose of expansion, see the Extended version. 

  1. * I might have misunderstood something else as well, but it seems like the proxy will always have to store a hash value with the 'value', '_ttl' and '__expires' keys in addition to other meta data to be able to populate the CacheItem, if this is the case then &$exists can effectively be removed from DriverInterface->get() as false is not a valid value for CacheProxies. 

Then way I see this working is just dumping the CacheItem object in the cache driver (APC/Memcached/DB via serialize()) directly. You can see demo implementation of how I'd see this done. As for &$exists I've covered it above.



Best regards,
Florin

Robert Hafner

unread,
Jan 7, 2013, 1:29:09 AM1/7/13
to php...@googlegroups.com

I'm still going to point out that I think this proposal makes far more sense-


Of course, the fact that I wrote it probably has something to do with that (admitting bias). 


Robert







--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To post to this group, send email to php...@googlegroups.com.
To unsubscribe from this group, send email to php-fig+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/QHPxiZxKV94J.

Florin Patan

unread,
Jan 7, 2013, 3:12:37 AM1/7/13
to php...@googlegroups.com
I've made the changes suggested by André.

Best regards.

Florin Patan

unread,
Jan 7, 2013, 3:23:04 AM1/7/13
to php...@googlegroups.com
Hi Robert,


I for one clearly don't want to help creating a standard which will then be considered by everyone as sucky as it might affect in my career path. 

So if this is nonsense, prove why and how another approach, yours or the one from evert is better, with arguments or a pro/con list and help creating a better world ;)

Thanks!



Have a nice day. 

Robert Hafner

unread,
Jan 7, 2013, 9:38:51 PM1/7/13
to php...@googlegroups.com
I for one clearly don't want to help creating a standard which will then be considered by everyone as sucky as it might affect in my career path. 

So are you purposely being childish here, or am I just misreading that? My career path is doing just fine, and my caching library is actually being used by people.


So if this is nonsense, prove why and how another approach, yours or the one from evert is better, with arguments or a pro/con list and help creating a better world ;)

Since you're the one with "yet another" proposal, how about you explain why the other ones don't work?


Robert


To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/f50MlRF7YVIJ.

Jordi Boggiano

unread,
Jan 8, 2013, 3:55:33 AM1/8/13
to php...@googlegroups.com
On 08.01.2013 03:38, Robert Hafner wrote:
>> I for one clearly don't want to help creating a standard which will
>> then be considered by everyone as sucky as it might affect in my
>> career path.
>
> So are you purposely being childish here, or am I just misreading that?
> My career path is doing just fine, and my caching library is actually
> being used by people.

The way I understand it (although it tripped me up at first as well) he
is asking for feedback on his proposal because he doesn't want to be
responsible for creating a crappy proposal, should it be accepted.

Anyway yes it would be nice to have the various proposals' authors
comment on the others and try to find common ground, otherwise I am
afraid this will die out.

Cheers

--
Jordi Boggiano
@seldaek - http://nelm.io/jordi

Florin Patan

unread,
Jan 8, 2013, 4:43:14 AM1/8/13
to php...@googlegroups.com
It seems I need to learn how to express myself better in English but yes, that's what I've meant. I don't consider the other proposals crappy but if this one doesn't make sense and gets accepted then it wouldn't look that good for me, right?

As for comments on the proposal from Robert, I'll give them in his thread, this went off-topic and I don't want that.


Have a nice day. 

André R.

unread,
Jan 9, 2013, 1:15:38 AM1/9/13
to php...@googlegroups.com
On Friday, January 4, 2013 11:39:29 PM UTC+1, Florin Patan wrote:
Thanks for posting this here André.

Please see my comments below:

On Friday, January 4, 2013 11:18:17 PM UTC+2, André R. wrote:
[ To get this going I would like to suggest that we discuss the common Interface first (PR #63), and discuss the followup extended interfaces (PR #not-yet): namespaces, tagging & depth later (in another thread).  ]
 
That's the reason I've split the interfaces into two proposals but kept them in a single branch.
While there's a need for those 'advanced' features, there's really not much support for them, safe for maybe locking which can be done relatively easily in any system that I can think of.
If people are ok with having this topic split then more on the 'advanced' features could be discussed when the time for them will come.


1. I'm basically suggesting we are should do a basic / common PSR, and just make room for a one/several followup PSR's for the more advance topics later, to make sure there are a chance it wil get accepted soon.

2. But I also agree with Jordi that the three proposals should be merged (not literally, just that the three of you should find a common ground)  before taking this to a vote/ review to the whole list.

3. Since I wrote my review of your PR I have gotten around to actually try out Stash

So with that in mind, some comments inline:
 

First, thanks for restarting this cache discussion, much appreciated!

Some comments on PR #63:
  1. I don't quite see the need for both a CacheItem & the &$exists param, the Item can either have a isValid() method, or get() can return null if there is no value (aka no cache item). Both alternatives would make sure BatchDriverInterface->getMultiple() gets this exists capability as well.
 The reason for this is to make it more APC::fetch look-alike. On the other hand NULL would indeed make sense as it allows further features, see below, so I'll change this.


Well there was several alternatives in my point above, if you instead make sure cacheItem has isValid / isMiss like in the proposal from Robert,  it can work like this with no need to check for null return type:

$item = $cache->get( ... );
if ( $item->isMiss() )
{
      $item->value( loadData( ... ) );
      $cache->set( $item );
}
return $item->value();

  1. A good step in right direction on removing constructors from the interfaces, but as mentioned in the PR I would even remove setCacheDriver(DriverInterface $cacheDriver); as a proxy implementation might take several drivers in it's constructor and allow for built in support for cache hierarchies, avoiding user code to have to deal with this like in the PR description example and the options example by @schmittjoh.

I wanted to have a feedback from at least one more person in regards to this.

+1, please do
 
We could have the method changed to:
addCacheDriver(DriverInterface $cacheDriver, $priority = 100, $overwriteExisting = false);


This implies a lot of logic that some implementations might not want to implement, some might not want to provide hierarchal cache layers.
 


In this case $priority could be just about any integer as there's no need add limits. We'll just need to specify that the value is extracted in the highest priority order.
Since I'm not sure what happens when you want to add another driver with the same priority an existing one I've added the $overwriteExisting for it in the signature but I think that we should discard it and use overwrite as default procedure. Any thoughts on this? 

  1. hasSerializationSupport() is defined on both DriverInterface and BatchDriverInterface.
 
Thanks! Copy paste isn't that good sometimes :) 

Your welcome, easy to overlook when you have seen your own proposal to many times :)

 

  1. Is hasSerializationSupport() need in the first place? We could also require that drivers need to handle this transparently, making them choose the best serializer available for the driver and making setSerializer() and related user code logic for this unneeded.

The reason for it is so that you can inject your serializer if you want to, making the drivers more compatible with each-other across implementations. It indeed brings some problems and more code to user-land. We can drop it altogether if there's no need for it. It's always easier to delete rather that add. 


It is :)
 
 
  1. I might have misunderstood but it should be documented that ItemInterface is a value/naked object, and no backend calls will be executed on it's set* & get* methods. If this is true, Item could be a class with properties instead of interface with methods, enforcing no logic.

You got it right, there shouldn't be any logic in the Item in regards to backend calls BUT, for example, you could chose to provide more metadata functionality, like having a method called increaseRefreshCount() so that you can control the number of times the object was refreshed in the main priority cache backend before you perform logic on it, like a full refresh of the item in all cache backends.


The item can have as many functions as you like, my main point is to clearly document that changes won't take affect before you set it to CacheProxyInterface / CachePoolInterface*.

This last part is what I prefer in this proposal over how Roberts proposal and Stash does it, I was quite surprised when I realized Stash fetching/storing data on changes to CacheItem. But there might be some good reasons for it that we're not seeing even if it then looks like race conditions are possible depending on what kind of invalidity strategy you take.

* "Proxy" and "Pool" seems to be quite similar concept wise btw, so might be possible to merge the concepts here.
 

It would indeed be possible to have this with a class by extending it but I'm not sure how FIG should provide code like this. There's some discussion in the other threads about this topic so maybe a by-law should be considered to have a clear direction for this.

interface is fine (ref main point above).

 
 
  1. Is DriverInterface->set() $lifeTime a ttl? or a timestamp?

Most common case is a TTL in seconds so but I'll need to add this to the specs. The Item should store the timestamp of the save moment as well in order to have a way to compute the expiration time.  

Ok, so it for instance can take either a ttl in seconds or a DateTime object then, like stash.
doc please :)
 

  1. Do we need the metadata functions on the basic / common cache interfaces? What is the use case and how is it supposed to be stored by the driver? (ignore last question if assumptions in 8 are correct)

I'm not sure there's a need for metadata in the existing systems for simple use cases. It was added with the purpose of expansion, see the Extended version. 

If it is needed for future extensions, then by all means keep it, but document the use cases / why it is there.

 

  1. * I might have misunderstood something else as well, but it seems like the proxy will always have to store a hash value with the 'value', '_ttl' and '__expires' keys in addition to other meta data to be able to populate the CacheItem, if this is the case then &$exists can effectively be removed from DriverInterface->get() as false is not a valid value for CacheProxies. 

Then way I see this working is just dumping the CacheItem object in the cache driver (APC/Memcached/DB via serialize()) directly. You can see demo implementation of how I'd see this done. As for &$exists I've covered it above.



Ok, thanks for the clarifications.

 



Best regards,
Florin

Florin Patan

unread,
Jan 13, 2013, 5:38:03 PM1/13/13
to php...@googlegroups.com
This proposal has suffered some important changes since it was first published.

I've talked to Evert Pot so we could improve this proposal and keep it simple as
well. He agreed that first we should get a simple version of this and then get
other PSRs to include more advanced functionalities. Also Beau Simensen was
very helpful in getting this as simple and clear as possible without sacrificing any
further extensibility from other PSRs.

So now we are down from three different proposals to two proposals. I'll talk with
Robert on IRC/mail in the next day or two about this and how we could improve it
in order to maybe get down to a single proposal and have it ready for more talks
or even voting. I would have done it sooner but I've been a busy in the past couple
of days.

Thank you for your time.

Florin Patan

unread,
Jan 23, 2013, 3:42:15 AM1/23/13
to php...@googlegroups.com
This has been updated with a couple of clarifications, changed the methods order
a bit to be more consistent and a couple of small tweaks to improve readability.

You can view the document here:


Thank you.

André R.

unread,
Jan 23, 2013, 4:49:52 AM1/23/13
to php...@googlegroups.com
Very clear, simple and well documented!

Nice touch to just return null when no value exists, makes sense with a cache item class.


Some potential issues:
1. I see the Proxy / Pool / Service has been skipped, first I thought this might be a loss of future proofing as there is room for a Service that irons out differences between different cache backends based on which future cache proposal they implement. But a service can either have it's own API or simply also implement CacheInterface + future more advance cache interfaces, so this it is probably a strength to leave it out of the PSR for now.
Short: No issue here.

2. There is no flush / purge functionality, this can be argued to allow bad practice, so I'm fine with leaving it out for now.
Short: No issue here.

3. In the lack of hierarchical cache and cache iteration possibility, there should be a section describing best practice for clearing a large section of the cache. Example: Somehow your application allows you to do large bulk changes, either a subtree delete, a subtree move, a delete by tag or a change tag on all matches and so on. What is best practice for clearing / updating cache on all those affected items?
Short: Lack of best practice in the spec for dealing with big cache changes & potentially a need for future cache functionality to deal with mass changes efficiently.


Hope this helps,
André, eZ Publish

Paul Dragoonis

unread,
Jan 23, 2013, 6:52:25 AM1/23/13
to php...@googlegroups.com
Hi Andre,

The purpose of this initial cache PSR is to release a very simple and working cache class with the most basic but functional methods, i.e: exists/get/set/remove.

The fancy things you're asking about such as pooling and hierarchical stacks should come at a later PSR.

Thanks,
Paul.


--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To post to this group, send email to php...@googlegroups.com.
To unsubscribe from this group, send email to php-fig+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/OzQz3lhq_TIJ.

André R.

unread,
Jan 24, 2013, 5:59:20 AM1/24/13
to php...@googlegroups.com


On Wednesday, January 23, 2013 12:52:25 PM UTC+1, Paul Dragoonis wrote:
Hi Andre,

The purpose of this initial cache PSR is to release a very simple and working cache class with the most basic but functional methods, i.e: exists/get/set/remove.

The fancy things you're asking about such as pooling and hierarchical stacks should come at a later PSR.

Which was my conclusions in the mail as well, with the exception of #3.

#3 is an open issue, imho there needs to be a short description on how to deal with mass cache clearing, possibilities could be:
- It could propose that you keep list of keys in a separate key/value (but pity we don't have ->append)
- It could propose you wait for a future iteration interface
- It could propose that you (background process recommended) fetches all objects affected from your backend and update / delete each and every cache item connected to these objects.

Florin Patan

unread,
Jan 24, 2013, 8:25:07 AM1/24/13
to php...@googlegroups.com
Hi Andre,


Sorry for late response.

I don't want to push this yet as I haven't had time to match with Robert and talk to him about the proposal.
Right now Evert Pot and Beau Simensen helped me getting this into a much simpler form and with Roberts help we'll be able to have this proposed for more discussion/voting if 

There is also a more advanced proposal which adds the reminder of the functionality that you also mention at #1.

I'm not sure if it's right for a PSR to suggest existence of a future PSR given the current context when it's been a while since we are talking about caches.
Also, I think that by having a line such as: "For more advanced functionality check for a advanced PSR" won't look quite right.

Thanks for #2, I've totally forgot to add it. I'm not sure if flush or clear should be used but we can sort this out I guess.

Now to be more accurate on your #3. The omission is done specifically as the terms 'tag', 'namespace' and 'locking' are missing in this PSR.
Since the interface implements bulk operations one should be able to assume that those functions should be used by the user to perform the mentioned actions.

It would be indeed nice to describe how certain functionality should be done/implemented but in the light of the rage against existing PSRs it might be seen as trying to impose a certain way of solving problems.
Maybe a reference implementation could exist with some FAQ section for it, I could certainly do it, but for consistency we should do the same for the existing PSRs as well.

Have a nice day,
Florin

Bernhard Schussek

unread,
Jan 25, 2013, 4:10:45 AM1/25/13
to php...@googlegroups.com
One short addition: Should ItemInterface not be named CacheItemInterface? After all, this is describing a "cache item", not some arbitrary item (just like it's "CacheInterface" and not "ContainerInterface").

Cheers,
Bernhard

--
Bernhard Schussek
Blog: http://webmozarts.com
Twitter: http://twitter.com/webmozart


2013/1/24 Florin Patan <flori...@gmail.com>
To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/UTNu50Th_MQJ.

Florin Patan

unread,
Jan 25, 2013, 4:59:39 AM1/25/13
to php...@googlegroups.com
Bernhard you are right. It should be more accurate named. I've changed it to that.

Florin Patan

unread,
Jan 28, 2013, 7:00:30 AM1/28/13
to php...@googlegroups.com
I've added some new appendix clarifications which should help people in developing their library.
The diff can be found here and you can view the rendered proposal here.

Evert Pot / Beau Simensen if you have time to review the changes I've added to this since our
talk on IRC, please do so and let me know if you are still ok with the current specification.

Also I'm currently waiting for a reply from Robert as he said he's working with several voting
members to update and clarify his proposal. If anyone that's working with Robert could shed
some light on what's going on, please do so if the time that Robert has doesn't allow him to
do it. Not only it would help me and others better understand the proposal that's being done
but also it would help you getting early feedback on it.

Thank you all for your time and feedback so far.


Best regards.

Dmitrii Chekaliuk

unread,
Jan 28, 2013, 7:40:25 AM1/28/13
to php...@googlegroups.com
Hi Florin,

Why does CacheInterface::set() accept mixed type values rather than
instances of CacheItemInterface like setMultiple()?

And there is a typo (fecthing) in 4.2.

Yours faithfully,
Dmitrii

On 28.01.2013 14:00, Florin Patan wrote:
> I've added some new appendix clarifications which should help people
> in developing their library.
> The diff can be found here
> <https://github.com/dlsniper/fig-standards/commit/8d0eb150eecc05a4f06916f0ed8ed64f68496e0e>
> and you can view the rendered proposal here
> <https://github.com/dlsniper/fig-standards/blob/cache-proposal/proposed/psr-cache.md>.
> --
> You received this message because you are subscribed to the Google
> Groups "PHP Framework Interoperability Group" group.
> To post to this group, send email to php...@googlegroups.com.
> To unsubscribe from this group, send email to
> php-fig+u...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/php-fig/-/YWvp4EEJHvkJ.

Florin Patan

unread,
Jan 28, 2013, 7:59:22 AM1/28/13
to php...@googlegroups.com
Hi Dmitrii,


Thank you for your feedback.

The method signature was a mistake from the refactoring I've done and I've left
it unchanged. I've fixed it as well as the typo. Also, I've documented the way to
use the setMultiple method.

You can view the diff here.


Have a nice day,
Florin 

Paul Dragoonis

unread,
Jan 28, 2013, 8:37:13 AM1/28/13
to php...@googlegroups.com
Hi Florin,

I'm trying to review the latest PR that we've been working towards, which i believe is PR #11. However we also have PR #63.

Which one should be considered as your proposal so that I may review it?


To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/6g4o3KQAZTkJ.

Florin Patan

unread,
Jan 28, 2013, 8:51:40 AM1/28/13
to php...@googlegroups.com
Hi Paul,

Currently #63 is a cleaned, better documented superset of #11.

It has most ideas taken out of it, combined with feedback from discussions + feedback from this thread.

Last time I've talked to Evert Pot, the original author of #11, we agreed about having this pushed forward
and I've tried to reach a consensus with Robert, author of #17. So far approaching him has been rather
hard due to various reasons and when I've finally got in contact with him he said he'll send an e-mail
which explains why this proposal sucks and his is better. Also, Robert said that there's something
we've all missed in the thread where he explains why race conditions are fixed in his proposal so I'm
eagerly waiting for it, if I'm missing such a big point. I've yet to receive the e-mail but I don't want to
talk more about this in this thread, if you want I can talk on #php-fig.

I still need Everts confirmation about his ok with the proposal but nothing major was changed since last
time I've talked to him, mostly adding the Appendix section and some cleaning up so it should be safe
to assume that since nothing changed functionality wise that he'll still be ok with it.

Thank you for your interest in having this solved ;)


Best regards,
Florin

Paul Dragoonis

unread,
Jan 28, 2013, 9:00:06 AM1/28/13
to php...@googlegroups.com, ted...@tedivm.com
Thanks for the reply Florin.

Robert,

Can you please outline what problems you see with the #63 proposal.
If you have already highlighted this on the mailing list then please just re-post it

Thanks,
Paul.


To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/tC0n6hXytDMJ.

Florin Patan

unread,
Jan 28, 2013, 9:02:29 AM1/28/13
to php...@googlegroups.com
Please do not read the: "which explains why this proposal sucks and his is better." as being a form of
disrespect or competition, Robert didn't used those words nor we are in a competition.

The users should get the best interface possible from a interface, not from an author.

I'm sorry if I've triggered any negative reaction, it was not my intention by far.


Have a nice day,
Florin

Marc Bennewitz

unread,
Jan 29, 2013, 5:43:07 PM1/29/13
to php...@googlegroups.com
I notices the following lines within you proposal:
> If the user does not provide a TTL value then the `Cache` MUST set a
default
> value that is either configured by the user or, if not available, the
maximum
> value allowed by cache system.
>
> It will be the implementation job to define what values are considered
valid
> or invalid for the specific storage but the user MUST be aware of the
accepted
> values by the underlying solution both for TTL values as well as for
key names.

... and the method "set" is defined to support a TTL as argument.
> public function set($key, $value, $ttl = null);

That's not compatible with Zend\Cache\Storage because the following:
- A TTL needs to be supported by a storage engine OR the time
information MUST
be stored together with each item.
- Storages supporting TTL by calculating it against
last-modification-time of an
item and the current time requires to have the TTL available on
reading the item.

I changed your proposal a bit to go the way Zend\Cache\Storage does to
support such
implementations:
https://github.com/marc-mabe/fig-standards/commit/cc4448596f14f85459e3c0f29f17a86d27ae9b31

Thoughts ?

On 01.12.2012 20:41, Florin Patan wrote:
> In an attempt to unify the proposals as well as some information from
> real life scenarios,
> I've created the following proposal for caching interfaces:
> https://github.com/php-fig/fig-standards/pull/63
>
> Please review it and help me improve it so that at some point we could
> vote on this matter
> and give the community a direction for this matter.
>
> Thank you for your time and support!
>
>
> Best regards.
> --
> You received this message because you are subscribed to the Google
> Groups "PHP Framework Interoperability Group" group.
> To post to this group, send email to php...@googlegroups.com.
> To unsubscribe from this group, send email to
> php-fig+u...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/php-fig/-/lXgZ9YvyrbQJ.

Florin Patan

unread,
Jan 30, 2013, 9:15:25 AM1/30/13
to php...@googlegroups.com
Mark, thanks for the input.

The problem on having a setTtl on Cache, or ExpireableCacheInterface as you
call it, will mean that every item that you set via that instance will either have the
same ttl or you'll need to call the setTtl function every time you want to store a
item.

While it's true that most of the times the items saved in cache will have the
same ttl for a certain item type, one could implement a driver using the above
interface then collect all items at runtime and then proceed to save them at the
end of the script using register_shutdown_function().

I'd rather solve this by moving the 'setDefaultTtl' to the interface, as you did, and
then override the set function to use the signature that it currently has in this
proposal, with the $ttl = null. This way, you'll get solve the issue on non-ttl aware
drivers as well as setting the global driver ttl for every item.

What do you think?

Florin Patan

unread,
Jan 30, 2013, 9:17:06 AM1/30/13
to php...@googlegroups.com
Aaand sorry for typo in your name, auto-correct is having it's day today :)

Maarten Hagoort

unread,
Jan 31, 2013, 7:48:23 AM1/31/13
to php...@googlegroups.com
I've made an interface that should be compatible with any type of handler.
Tested with file and memory based systems.
The TTL is based per key as you might want a twitter feed to cache for 30 minutes but a parsed template file for ever.
If you want a parsed template be cached until filemtime is changed then it can be compared as well.

http://code.google.com/p/dragonfly-cms/source/browse/includes/poodle/cache/interface/adapter.php

Florin Patan

unread,
Jan 31, 2013, 10:41:20 AM1/31/13
to php...@googlegroups.com
Hi,


I've looked up at the interface but besides the mtime function it doesn't seem to have anything
that's different from the current proposals.

I wouldn't include mtime() in such a generic interface as the current proposal since not all caching
systems support retrieving the value of it and if one should store the time with the item as it would
mean a increase in the stored size for the item.

I had the same thing in the original proposal but the general thinking for this proposal is to have the 
basics down then, in the next proposal, iron out things such as tags, namespaces, locking, item
expiration detection and possibly more.

We also have areas where drivers can't support features from multi* methods but those are rather
easy to emulate as well as cheap in terms of costs from driverland (so to speak).



Have a nice day :)

Florin Patan

unread,
Jan 31, 2013, 10:43:32 AM1/31/13
to php...@googlegroups.com
Marc, since I feel it's a good idea to have this debated a bit more, can you make
the updates I've suggested and then make a PR to my repo or just link it from 
your repo so that others can review it better?

If not, I'll take care of this this weekend.


Thanks.

On Wednesday, January 30, 2013 12:43:07 AM UTC+2, Marc Bennewitz wrote:

Marc Bennewitz

unread,
Jan 31, 2013, 4:24:29 PM1/31/13
to php...@googlegroups.com
Florian,

the logical difference is what the CacheInterface is for.

For ZF an instance of Zend\Cache\Storage\StorageInterface is an object to
store only one type of items. So the TTL is the same for each item of the same
type. If you would like to store different types of items you should instantiate
different objects of Zend\Cache\Storage\StorageInterface.

That means the TTL is part of configuration the same way as a path would be
on filesystem based caches or the host/port using memcached/redis etc.

To handle different handles on resource based caches (like memcached)
a resource manager come to play (Zend\Cache\Storage\Adapter\MemcachedResourceManager)
and such resources can be shared by different instance of Zend\Cache\Storage\StorageInterface.

Greetings
Marc
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.

To post to this group, send email to php...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/yzn7GMeT56MJ.

Florin Patan

unread,
Feb 6, 2013, 4:34:29 AM2/6/13
to php...@googlegroups.com
I think that it's waay too much for a system that should be simple.

Say I have a CMS and I want to store articles, comments, pages, subpages,
blocks, DB results for various sections and so on. If I understood you right,
it would mean to create a object for each and every one of the above types
that implement the interface. Then I need to use some resource manager
to go from this to storage.

I think that having a simple implementation that doesn't try to achieve total
abstraction for the sake of abstraction is the best solution.

Look at how different are the caching systems in use today. None have the
exact same set of features/way of doing them. They all have custom features
and so on. 

Also, I really don't see the need to take control from the user and pass it to a
library. Users should be in control of their systems and if they are not prepared
to do that, then they should (be) learn(ed) how to do it rather that giving them a
implementation that will hurt them in the long run.

Marc Bennewitz

unread,
Feb 8, 2013, 2:09:56 AM2/8/13
to php...@googlegroups.com
Florian,

I'm on you to say the ZF2 way is too much for a simple (and global) interface.
I only explained the way ZF2 does it ;)

But in result I mean it's unhelpful to describe a global interface that's not
possible with some implementations.

For me I think to describe an additional interface to support TTL could the
way to got to support expirable storages in a basic way. You can go and
extend the basic interface to add the additional $ttl argument on set if you like.

Greetings,
Marc
To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/OPgPtjmKFs8J.

Florin Patan

unread,
Feb 10, 2013, 5:07:42 PM2/10/13
to php...@googlegroups.com
Hi Marc,


Sorry for the delay.

Unfortunately I'm not very sure what to understand from your e-mail, really
sorry about that, but if I read it right, then you suggest to add a separate
interface for TTL aware storages.

That would totally be fine with me, I do understand why you want to have
it separated. I think it would be nice if you can provide a concrete example
of a storage that is not TTL aware or a case when this is not needed/used
and that would suffer from lacking this feature. You can send a PR to my
repo and have the changes for the interfaces done + the example I've
mentioned and we'll continue from there. Does it sound good for you?


Best regards,
Florin

Beau Simensen

unread,
Feb 12, 2013, 8:47:16 PM2/12/13
to php...@googlegroups.com
I apologize for the delay on getting back to this thread. :(

The [current proposed psr-cache][1] looks radically different from where it was when I last saw it. I was mostly pretty happy with it with the exception of the exists() method. Since then a few big things have changed. I wish I had been paying more attention so I could have seen what the reasoning was.


CacheInterface::exists or CacheItemInterface::exists/isMiss/etc

The race condition problem for having exists() on Cache Interface makes me think we should leave it out entirely. If I call $cache->exists('foo'), and it is true, and then call $foo = $cache->get('foo') and still have to check to ensure that $foo !== null, what is the point?

I think it would be better to have a CacheItem always returned and provide a check on the object to determine whether or not it was a miss / is expired / exists.

$cacheItem = $cache->get('foo');
if ($cacheItem->isMiss()) {
    $cacheItem->setValue($this->expensiveOperation());
}

$foo = $cacheItem->getValue();


CacheInterface::setDefaultTtl

I do not think setDfaultTtl belongs on the interface. This is a configuration level thing. This was discussed at great length. Giving consumers of CacheInterface the idea that they should be able to alter the default TTL for the entire application is something that should not be allowed. It will get abused and people will not be happy about it.


CacheItemInterface::setTtl and CacheItemInterface::getRemainingTtl

Why were these removed from the proposal? If we have setValue() we should probably have both of these. CacheItemInterface either needs to be a value object or it needs to be mutable and encapsulate all of the things that setValue defines as what is getting cached (essentially $value and $ttl).


TTL

I think I've heard Evert say a number of times that the [Spring cache interface][2] is a really good starting point. It doesn't deal with "exists" or "ttl" or anything like that, so we're already going above and beyond that. I'd argue that doing something really close to this interface for the first cache PSR would go a long way toward standardizing on cache.

If we decide to get TTL into the mix we should be very careful how we do it.




Florin Patan

unread,
Feb 18, 2013, 11:21:04 AM2/18/13
to php...@googlegroups.com
Hey there.


Since 'exists' and the likes seem to be rather a point that many don't agree with, I'll remove it from the proposal. Its use case would be to check if a key exists in the cache without retrieving it but since this would fall into a rather narrow use case, I think it's better to remove it indeed.

I've removed 'CacheItemInterface::setTtl and CacheItemInterface::getRemainingTtl' from this proposal only to have them in the extended version, the one where some of the other functionalities are described. The reason I've did so is that not all people would need it and it would make storing the items less space consuming. If more people would think about adding this back then I see no reason why we can't have it here, aside from the increased space requirements for storing the items.

'CacheInterface::setDefaultTtl' while it is a configuration function I believe that since we specify the existence of such a functionality, having a function present in the common interface for enabling that functionality should be there as well. If others agree, I'll remove it as well, or if you can point me out some more documentation to better learn about how to treat these things then it will be great :)

As for the TTL. This is a open question as well.
The model I have in mind is that when you want to save something to cache you will also know what's the time out for that item. When you want to save three different items and you don't specify the TTL when you save the item then you'll need to have three different instances of the adapter that use the same connection only to have different timeouts in those instances or the same instance which just bounces the intervals back and forth. Or maybe I'm missing something. There was the proposal above with having the TTL specified with the save function in a interface called TtlAware or similar, I think that it would that be a better approach in this case, what do you think?

I'll update the changes as soon as possible.



Best regards.

Beau Simensen

unread,
Feb 18, 2013, 12:14:24 PM2/18/13
to php...@googlegroups.com
Hi Florin!

Thanks for all of your hard work on this. :)

Since 'exists' and the likes seem to be rather a point that many don't agree with, I'll remove it from the proposal. Its use case would be to check if a key exists in the cache without retrieving it but since this would fall into a rather narrow use case, I think it's better to remove it indeed.
I strongly favor removing it from the proposal.

I've removed 'CacheItemInterface::setTtl and CacheItemInterface::getRemainingTtl' from this proposal only to have them in the extended version, the one where some of the other functionalities are described. The reason I've did so is that not all people would need it and it would make storing the items less space consuming. If more people would think about adding this back then I see no reason why we can't have it here, aside from the increased space requirements for storing the items.
If we do not have the ability to update the TTL from the cache item interface itself I would suggest making cache item interface a value object and to remove $cacheItem->setValue() as well. It will make the cache item interface simpler and there will only ever be one path for updating or setting a cached value, calling $cacheItem->setValue().

I think it is fine to include the advanced cache item TTL related stuff in a future proposal in order to keep the first proposal simple and easier to implement.

'CacheInterface::setDefaultTtl' while it is a configuration function I believe that since we specify the existence of such a functionality, having a function present in the common interface for enabling that functionality should be there as well. If others agree, I'll remove it as well, or if you can point me out some more documentation to better learn about how to treat these things then it will be great :)
I strongly think this does not belong in the interface. A "default TTL" is very much an implementation / configuration detail that does not belong int he public API for cache consumers. At best the TTL be advisory anyway as some cache implementations may not support a TTL at all. Setting it at the user level does not seem like something we should allow.

Simple **highly contrived** example showing why this could be bad/dangerous:

class FooVendor\FooService
{
    public function __construct(Psr\Cache $cache)
    {
        // We need to have all of our cache items default to 300 seconds.
        // Implication here is that this value is IMPORTANT to the internal
        // workings of this particular service and that we need it to be this
        // value otherwise bad things may happen.
        $cache->setDefaultTtl(300);
        $this->cache = $cache;
    }
    public function cacheThis($thing)
    {
        $this->cache->set('foo', $thing);
    }
}

class BarVendor\BarService
{
    public function __construct(Psr\Cache $cache)
    {
        // We need to have all of our cache items default to 9000 seconds.
        // Implication here is that this value is IMPORTANT to the internal
        // workings of this particular service and that we need it to be this
        // value otherwise bad things may happen.
        $cache->setDefaultTtl(9000);
        $this->cache = $cache;
    }
    public function cacheThis($thing)
    {
        $this->cache->set('fbar', $thing);
    }
}

$cache = new SomePsrCache;
$fooService = new FooService($cache); // default cache now 300
$barService = new BarService($cache); // default cache now 9000

$fooService->cacheThis($someFooObject);
$barService->cacheThis($someBarObject);


$fooService is under the mistaken impression that the default TTL is still 300. It is not! It is actually 9,000. Add another level (BazService) that does something entirely different and now you have three services, each relying on having set the default TTL (or even been aware that there is such a thing) and only one is actually doing what is expected. Now say you have a large DiC configuration that has hundreds or thousands of services defined, many of which are consuming the cache interface, each potentially thinking they can set the default TTL and/or relying on knowing that the default TTL is set to some known value and you are going to have a bad time trying to figure out why some objects live longer than they are supposed to and others are not living as long as you expected.

Hopefully this helps illustrate how dangerous it is to give the consumer of a cache interface any hint that the default cache TTL is in any way something they should care about or rely on.

This doesn't mean that we don't talk about a notion of a default TTL. Users of the cache should be aware that when they call set w/ a TTL that TTL will be used if the cache supports TTL and if they do not specify a TTL, they will get the "default value that is either configured by the user or, if not available, the maximum value allowed by the cache system." In other words, if you want to be specific about how long your object stays in the cache you should specify a TTL when you call set() and not rely on a "default TTL."

Thanks again for your work on this so far. :)


-- 

Beau Simensen

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/hEuk8rcKi90J.

Marc Bennewitz

unread,
Feb 22, 2013, 12:55:22 PM2/22/13
to php...@googlegroups.com
Hi Florian and Beau,

Sorry for the really late response :/


Unfortunately I'm not very sure what to understand from your e-mail, really
sorry about that, but if I read it right, then you suggest to add a separate
interface for TTL aware storages.
Thats exactly what I mean


That would totally be fine with me, I do understand why you want to have
it separated. I think it would be nice if you can provide a concrete example
of a storage that is not TTL aware or a case when this is not needed/used
and that would suffer from lacking this feature. You can send a PR to my
repo and have the changes for the interfaces done + the example I've
mentioned and we'll continue from there. Does it sound good for you?
Because a cache could simply any storage (in theory) it's every storage
not supporting item expire by default like the filesystem or dba/dbm like
kv storages.
I could send you a PR for the changes of next time
https://github.com/marc-mabe/fig-standards/commit/cc4448596f14f85459e3c0f29f17a86d27ae9b31

CacheInterface::setDefaultTtl

I do not think setDfaultTtl belongs on the interface. This is a configuration level thing. This was discussed at great length. Giving consumers of CacheInterface the idea that they should be able to alter the default TTL for the entire application is something that should not be allowed. It will get abused and people will not be happy about it.


CacheItemInterface::setTtl and CacheItemInterface::getRemainingTtl

Why were these removed from the proposal? If we have setValue() we should probably have both of these. CacheItemInterface either needs to be a value object or it needs to be mutable and encapsulate all of the things that setValue defines as what is getting cached (essentially $value and $ttl).


TTL

I think I've heard Evert say a number of times that the [Spring cache interface][2] is a really good starting point. It doesn't deal with "exists" or "ttl" or anything like that, so we're already going above and beyond that. I'd argue that doing something really close to this interface for the first cache PSR would go a long way toward standardizing on cache.
I'm fine with it completely removing al TTLs from the first version to be sure - this could be done in later versions of this document


As for the TTL. This is a open question as well.
The model I have in mind is that when you want to save something to cache you will also know what's the time out for that item.
In my opinion this isn't the case over all - sure for web apps it's 95% that what you want but what if you prefer other strategies?
 
When you want to save three different items and you don't specify the TTL when you save the item then you'll need to have three different instances of the adapter that use the same connection only to have different timeouts in those instances or the same instance which just bounces the intervals back and forth. Or maybe I'm missing something. There was the proposal above with having the TTL specified with the save function in a interface called TtlAware or similar, I think that it would that be a better approach in this case, what do you think?
Yes that's the case with `ExpireableCacheInterface` (see link above) or you have to set the ttl before every read/write *BUT* nobody says it's last you can do with it!
It's possible anymore to define a TTL argument on `set()` (or using another function like redis does) to obviate dangerous implementations/usages suggested by Beau.
If that will be defined in an interface of a psr or will be up to the implementor could be a next question.

Florin Patan

unread,
Feb 24, 2013, 1:30:14 PM2/24/13
to php...@googlegroups.com
Hello,


I've updated the proposal to the latest suggestions. I think it's in a good place right now.
Thanks for your feedback.



Best regards,
Florin

Florin Patan

unread,
Feb 24, 2013, 1:46:15 PM2/24/13
to php...@googlegroups.com
Hello,


I've did some thinking on this one but according to earlier responses in other threads, FIG interfaces should be ok if they cover 80% of the uses cases.
And I think this proposal currently does so.
For the examples you've proposed I could say:
- database: add the expected expiry time when saved in a separate field and to the queries according to that. Auto-expiry could be emulated by a cron that runs every minute to delete the old records
- file system: checking for the mtime of the file might not be reliable and also if you want to store PHP and use it directly (for example) wrapping the contents in the file would break it. So for this case indeed this interface poses some challenges.
I've added the TtlAwareCacheInterface to fix this, but the question remains: do we really this?


Best regards,
Florin

Florin Patan

unread,
Feb 24, 2013, 1:54:53 PM2/24/13
to php...@googlegroups.com
Hello,


I've updated the interface again to the latest proposals. As always, any comments are welcomed.

After this, the next interface related to caching should be found here (not updated at time of writing): https://github.com/dlsniper/fig-standards/blob/extended-cache-proposal/proposed/psr-extended-cache.md

If there's any interest in seeing standardizing the caching interfaces effort going further, I guess this will need a FIG member (I'm currently not, should I be?) to raise the attention for it and make it better or to propose it for voting please do so as I've done all that I could do for it so far.

Thank you all for your efforts in making this.



Best regards,
Florin

Andrew Eddie

unread,
Feb 25, 2013, 2:58:43 AM2/25/13
to php...@googlegroups.com
On Monday, 25 February 2013 04:54:53 UTC+10, Florin Patan wrote:
I've updated the interface again to the latest proposals. As always, any comments are welcomed.
 

I think there's a typo:

"interface CacheInterface extends CacheInterface"

should be: ??

"interface TtlAwareCacheInterface extends CacheInterface"

Just want to clarify something. When you set, are you setting by the native value or passing in a CacheItem (or either)?

$cache->set('foo', 'bar');

or

$cache->set('foo', new My\CacheItem('bar'));

But when you are getting, a CacheItem is always returned, so you need to do this:

$cache->get('foo')->getValue();

Is that right?

Thanks in advance.

Regards,
Andrew Eddie

Paul Dragoonis

unread,
Feb 25, 2013, 3:15:55 AM2/25/13
to php...@googlegroups.com
Thanks Andrew for pointing this out.

All get() methods here impliy they return the CacheItem interface so I would assume you need to pass one in.

The set() param is 'mixed' which is unclear but a little more flexible, perhaps you want your driver implementation to automatically spawn CacheItem's for you when you pass in your object.

Florin, what were your intentions here of set being 'mixed' ?

Thanks,
Paul Dragoonis

 

Is that right?

Thanks in advance.

Regards,
Andrew Eddie

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/R_yIrCl6ZFUJ.

Florin Patan

unread,
Feb 25, 2013, 4:11:34 AM2/25/13
to php...@googlegroups.com
Hello,


Sorry for the mistake, copy-paste needs more love :d

Also, I've updated the proposal to better describe the role of the CacheItem.

The mixed value is specified there in order to reflect that it can accept any type of user values, not just a restricted set of value types.

One does not need to use a CacheItem in order to send it to the storage as it will introduce unnecessary complexity. Every time you need to store something you already know the key, the value and, maybe, the TTL for the item so there's no need to create a object, pass it to the driver which will the get the value from the object and store it.

I hope this answers the questions. Let me know if I should detail further on this.


Best regards,
Florin

Paul Dragoonis

unread,
Feb 25, 2013, 4:35:22 AM2/25/13
to php...@googlegroups.com
On Mon, Feb 25, 2013 at 9:11 AM, Florin Patan <flori...@gmail.com> wrote:
Hello,


Sorry for the mistake, copy-paste needs more love :d

Also, I've updated the proposal to better describe the role of the CacheItem.

The mixed value is specified there in order to reflect that it can accept any type of user values, not just a restricted set of value types.

One does not need to use a CacheItem in order to send it to the storage as it will introduce unnecessary complexity. Every time you need to store something you already know the key, the value and, maybe, the TTL for the item so there's no need to create a object, pass it to the driver which will the get the value from the object and store it.

I hope this answers the questions. Let me know if I should detail further on this.


Hi Florin,

To confirm I understand your answer, you are saying you 'set' a value which can be a scalar and this will be sent to the cache server as the scalar value, and when you run a get() it gets created into an object at run-time. 

This has some nice performance enhancements, but it needs to be clear in the docs that the 'set' is not cache item and the 'get' is, much more than just phpdoc stuff since it's easy to miss that kind of stuff.

One downside of this is where do you set the ttl and such for the cache item upon set()?
 
To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/7PJ8seVdkXIJ.

Florin Patan

unread,
Feb 25, 2013, 5:07:32 AM2/25/13
to php...@googlegroups.com
Hey Paul,


Yes, you've understood correctly.

Does this https://github.com/dlsniper/fig-standards/blob/cache-proposal/proposed/psr-cache.md#41-usage-of-cacheitem need to be reworked? If so feel free to send a PR to my repo and I'll merge it asap. I'm not sure how to better describe this at the current moment.

The TTL must be sent as an argument of the TtlAwareCacheInterface::set() implementation. If we want to have more functionality for the CacheItem then we could specify this in the extended proposal but all people here seem to want something very easy to use and as basic as possible without sacrificing any of the core features.

For example we could add a TtlAwareItem which can have the TTL set on the item and a AdvancedCacheInterface which can accept only a AdvancedCacheItem as a parameter to the set function.

If you wish, we could start to talk about the extended proposal in a separate thread but for now, I think that the most common case is to have the key, value and ttl of a item when you want to store them to cache.


Best regards,
Florin

Beau Simensen

unread,
Feb 25, 2013, 12:49:32 PM2/25/13
to php...@googlegroups.com
I am a little unhappy with the TtlAwareCacheInterface for two reasons.

First, I feel that the TTL related stuff should either be completely thought out or it should be ignored entirely. Seeing TtlAwareCacheInterface makes me think there should be a TtlAwareCacheItemInterface somewhere, and if discussion on that is supposed to be for a "future proposal," I feel like TtlAwareCacheInterface should be in the same future proposal as well.

Second, on the technical side of things, I believe that TtlAwareCacheInterface cannot be implemented as an extension of CacheInterface in this way. I do not believe you extend a method signature like this. I created a little simple example and I got a Declaration of bar::set() must be compatible with that of foo::set() fatal error. Is there another way we can do something like this?



Some ideas I have:

1) Remove all talk of TTL entirely (remove TtlAwareCacheInterface and all discussion relating to TTL from the document) and call it good. This would put us close to Spring's cache except we'd support batching. I'm a bit afraid that this might close PSR\Cache to much extension in the future, though.

2) Remove TtlAwareCacheInterface and add $ttl as an optional third param to CacheInterface's set() like was originally there. This will allow for TTL on the cache item to be addressed in future proposals and gives implementors of the existing proposal some additional useful functionality in being able to set a TTL. This may still be problematic on the extension front, but it would be easy to address the TTL aware cache item in a future proposal without breaking changes.

3) We make the third argument to set() an options array that can be used to extend cache down the line. I'm not a huge fan of setting options like this but it seems like it would be a way to allow for implementors to support one or more extended cache proposals without worrying about the limitations of the CacheItem set() method signature.

For example, if we want to include the notion of a TTL in the first cache proposal (from just the cache interface side):

use Psr\Cache\CacheInterface;

$cache->set('foo', 'bar', array(
    CacheInterface::TTL => 300,
);

If we want to not include TTL in the first proposal and do all of the TTL related stuff in an extended proposal:

use Psr\TtlAwareCache\TtlAwareCacheInterface;

$cache->set('foo', 'bar', array(
    TtlAwareCacheInterface::TTL => 300,
);


Alternately, we could skip the constant strings and just define plain strings:

$cache->set('foo', 'bar', array('ttl' => 300));


Each successive cache extending PSR would have to be mindful of collisions.

Paul Dragoonis

unread,
Feb 25, 2013, 12:51:41 PM2/25/13
to php...@googlegroups.com
I don't like the TtlAware stuff.

set($key, $val, $ttl), this is nice enough, or an options array is more extensible.


To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/ZL1OXemwlYcJ.

Beau Simensen

unread,
Feb 25, 2013, 12:52:51 PM2/25/13
to php...@googlegroups.com
I have some concerns about the name flush(). It would be easy to misinterpret this as meaning "sync changes to the cache," similar to how ORM solutions offer a flush() method. Of course you'd only make this mistake once. :) But even in the document comments it is already being clarified that the flush() method actually clears the content of the cache. Why not just call it clear?

From:

    /**
     * This allows to clear (flush) all the cache contents
     *
     * return Boolean
     */
    public function flush();

...to...

    /**
     * This allows to clear all the cache contents
     *
     * return Boolean
     */
    public function clear();

Florin Patan

unread,
Feb 26, 2013, 5:10:39 PM2/26/13
to php...@googlegroups.com
Beau, you are right.

I've fixed it and it should be visible now.


Thanks!

Florin Patan

unread,
Feb 26, 2013, 5:22:13 PM2/26/13
to php...@googlegroups.com
I'll address both Paul and Beau here.

It does make sense if you look on the problem from the storage engine perspective, some might not have TTL or be hard to emulate (see file caching).
I've asked which is preferable, cover 80% of the use cases or 100%. The current solution covers 100% of the cases (in regards to TTL at least).
Currently I'd rather leave this as a open question in order to get more feedback then chose a solution or another based on the responses.
I don't want to have too many changes as I think this is mature enough and I believe this is the last point that needs to be tackled and I hope you agree with me.
I for one, would revert to the old format but I do see the advantages this has, albeit limited.
As usual, it would be really nice if more people would jump on this and say their opinion as it would help us improve this.


Best regards,
Florin

Paul Dragoonis

unread,
Feb 26, 2013, 5:50:43 PM2/26/13
to php...@googlegroups.com
Honestly, how can you not cover TTL? I have category data that really never changes coz it's a fixed tree, so that's like infinite TTL or say TTL of once per month, but then I have Product pricing data that i expire every 24 hours coz things like that change a lot. 

You need TTL's and the proposal has to contain it else it's not viable. You default the TTL to 'null' and then the cache implementation will decide what to do about that if their driver does/doesn't handle stuff like that.


To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/BMxhMpF3JMAJ.

Florin Patan

unread,
Feb 26, 2013, 6:15:06 PM2/26/13
to php...@googlegroups.com
Paul, for that case as well as many others, we certainly need a TTL.

But then we also have the following cases: template / configuration caches or parsed code (annotations) caches. Usually you won't change the key to store them, they will be stored until regenerated and usually they'll be stored in files. Having null as default and then null as parameter doesn't help much as in these case and also for the mentioned functionality doesn't provide a clear and intuitive way to what will happen when the user will be in such a situation.

Having a TtlAwareInterface helps solving this problem imo. This way, TTL is not missing, when the engine supports it and we have all the basic functionality right here, in just one PSR.

Does it make sense? Or am I trying too much to find something good in this?


Best regards,
Florin

Beau Simensen

unread,
Feb 26, 2013, 6:29:21 PM2/26/13
to php...@googlegroups.com
As I mentioned earlier, the interface won't work as you think it will. I am pretty sure it is not possible to extend a method signature that way.

The options I see for us:

1) Remove ttl entirely from the proposal.
2) Include ttl in the set method signature.
3) Add an $options = null argument I'm the set method signature.

I think 3 (or something like it) would be the best way to keep the base cache interface extensible.

Discussion would be required around what would go into the options hash and how to define/set them so future extensions can be consistent.

If we go with option 3 we can table all talks of ttl and move that to a future extended proposal or we can decide to build ttl into the base cache proposal. I'm up for either.

Long story short, both for philosophical reasons but more importantly technical reasons, the TtlAware interface should be dropped.

I have proposed three alternatives. Happy to discuss other options as well.
To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/zuwfdKT7QEwJ.

Paul Dragoonis

unread,
Feb 26, 2013, 6:29:32 PM2/26/13
to php...@googlegroups.com
It does make sense but TTL is a basic requirement and should be in our PSR.

I see your argument that some file-based caching utilities might not use TTL's, but that's fine the 'null' usually implies infinite, i.e: never expire so by the API having set($key, $val, $ttl = null) means that implementors either set this to be infinite in the system or they just completely ignore it, but it stops us from needing extended PSR's or for extra interfaces for stuff that is a basic requirement of caching wether the implementor wants to use it or not.


To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/zuwfdKT7QEwJ.

Florin Patan

unread,
Feb 26, 2013, 6:41:19 PM2/26/13
to php...@googlegroups.com
I'd like 3) more that 2) as it allows for further extension.

Also, I've checked before submitting the change, the syntax is valid in PHP and I think I was against PHP 5.4/E_ALL (which includes E_STRICT iirc).

But besides this, I do believe that 3) is the better one so if Paul as the others are ok with this as well, I'll change the interfaces one more time by Friday or a Thursday.

I really hope this will be the last time I change it and we can compare the advantages/disadvantages with the one proposed by Robert and submit one or both to voting so we could move on.

Thank you all for helping out in creating and refining this.


Best regards,
Florin

Paul Dragoonis

unread,
Feb 26, 2013, 6:47:35 PM2/26/13
to php...@googlegroups.com
On Tue, Feb 26, 2013 at 11:41 PM, Florin Patan <flori...@gmail.com> wrote:
I'd like 3) more that 2) as it allows for further extension.

Also, I've checked before submitting the change, the syntax is valid in PHP and I think I was against PHP 5.4/E_ALL (which includes E_STRICT iirc).

But besides this, I do believe that 3) is the better one so if Paul as the others are ok with this as well, I'll change the interfaces one more time by Friday or a Thursday.

An extensible array syntax on the end is fine with me. 

Declaration: function set($key, $val, array $options = array())

Usage: $cache->set($key, $val, array('ttl' => 86400));
Constants Usage: $cache->set($key, $val, array(Cache::OPTION_TTL => 86400));

I would prefer to use class constants to hide people away from the keys used.
 
To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/swbctxAMN80J.

Andrew Eddie

unread,
Feb 27, 2013, 4:45:03 AM2/27/13
to php...@googlegroups.com
On 27 February 2013 09:47, Paul Dragoonis <drag...@gmail.com> wrote:
Usage: $cache->set($key, $val, array('ttl' => 86400));
Constants Usage: $cache->set($key, $val, array(Cache::OPTION_TTL => 86400));

What other options do you want to allow for when setting a value in the cache?

Regards,
Andrew Eddie 

Florin Patan

unread,
Feb 28, 2013, 5:46:51 AM2/28/13
to php...@googlegroups.com
Say we later define a tagable interface or a namespace interface which allows for setting any of those.
Having separate methods is not that great so that's why I think having a method that allows an options array is good.
What do you think?


Regards,
Florin

Paul Dragoonis

unread,
Feb 28, 2013, 6:22:11 AM2/28/13
to php...@googlegroups.com
On Thu, Feb 28, 2013 at 10:46 AM, Florin Patan <flori...@gmail.com> wrote:
Say we later define a tagable interface or a namespace interface which allows for setting any of those.
Having separate methods is not that great so that's why I think having a method that allows an options array is good.
What do you think?

Good example Floring. It has the extensibility factor. If the code had a 'TaggableInterface' typehint to it then a handler would be able to interact with $options['tag'] option, something like this:

$cache->set($key, $val, array(
    Cache::OPTION_TTL => 86400,
    Cache::OPTION_TAG => $myTag
));

Yes?
 


Regards,
Florin

On Wednesday, February 27, 2013 11:45:03 AM UTC+2, Andrew Eddie wrote:
On 27 February 2013 09:47, Paul Dragoonis <drag...@gmail.com> wrote:
Usage: $cache->set($key, $val, array('ttl' => 86400));
Constants Usage: $cache->set($key, $val, array(Cache::OPTION_TTL => 86400));

What other options do you want to allow for when setting a value in the cache?

Regards,
Andrew Eddie 

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/W7aa7g1W1K4J.

Florin Patan

unread,
Feb 28, 2013, 8:57:10 AM2/28/13
to php...@googlegroups.com
Hi Paul,


Yes, that's right.

A 'TaggableCacheInterface' for the cache driver could look like:

interface TaggableCacheInterface 
{
    const OPTION_TAG = 'tag';
}

Also, later on, if we get to have tags, we could add them on the CacheItem and have the method CacheItem::getTags() and maybe the implemation could look like:

class AdvancedCache extends Cache implements TaggableCacheInterface
{
    public function save(AdvancedCacheItem $item)
    {
       $options = array();
       if ($item instanceof TaggableCacheItemInterface) {
           $options[TaggableCacheInterface::OPTION_TAG] = $item->getTags();
       }

       $options[CacheInterface::OPTION_TTL] = $item->getTtl();

       parent::save($item->getKey(), $item->getValue(), $options);
    }
}


This is just a proof of concept :)



Regards,
Florin

Paul Dragoonis

unread,
Feb 28, 2013, 9:00:12 AM2/28/13
to php...@googlegroups.com
Looks sensible Florin. Thanks.


To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/OEuruHeNKPcJ.

Robert Hafner

unread,
Feb 28, 2013, 5:55:56 PM2/28/13
to php...@googlegroups.com

In my option an "options" argument is going to cause more harm than good. It opens the way for people to support non-standard options (therefore reducing the benefits of this standard), it's not enforceable in any real way, and we're still going back to needing things like "TTLEnabledCacheItemInterface". 



Robert




To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/OEuruHeNKPcJ.

Beau Simensen

unread,
Feb 28, 2013, 6:01:19 PM2/28/13
to php...@googlegroups.com
Hi Robert!

Thanks for the input. :)

We'd still want TtlEnabledCacheItemInterface or TtlAwareCacheItemInterface either way to add ttl related methods to the cache item. The problem $options is trying to solve is ensuring that we can leave set() open for extension in the future. Do you have a suggestion for how we can accomplish that without using $options? Or in your experience would you say that there are no other options that need to be set at the time of "set" besides a ttl type value?

-- 

Beau Simensen

Florin Patan

unread,
Mar 1, 2013, 3:57:22 PM3/1/13
to php...@googlegroups.com
I've been thinking a bit, and actually saw this one in reality:D, and you are right on this.
Enforcing that only certain keys must be passed would be next to impossible as PHP folks tend to 
The other option would be 2) and to have the next PSR accept only a Item in the save() function so that all the needed information is on the item itself.

Paul, Beau, others, what do you think. Would it make sense? Have 2) used?


Best regards,
Florin

Florin Patan

unread,
Mar 1, 2013, 3:59:14 PM3/1/13
to php...@googlegroups.com
* PHP folks tend to have more standard free things rather that well defined standards.

Paul Dragoonis

unread,
Mar 1, 2013, 4:52:45 PM3/1/13
to php...@googlegroups.com
On Fri, Mar 1, 2013 at 8:57 PM, Florin Patan <flori...@gmail.com> wrote:
I've been thinking a bit, and actually saw this one in reality:D, and you are right on this.
Enforcing that only certain keys must be passed would be next to impossible as PHP folks tend to 
The other option would be 2) and to have the next PSR accept only a Item in the save() function so that all the needed information is on the item itself.

My vote from the beginning is set($key, $val, $ttl = null).. I've already laid out why this is good for libraries that do and don't support expiration.

Is there anything else I missed? I'd like to get final version of your proposal, robert's and everts so I can get a mass vote going to get consensus of which one people like more.
 
To view this discussion on the web visit https://groups.google.com/d/msg/php-fig/-/DreP3r0iJzgJ.

Marc Bennewitz

unread,
Mar 2, 2013, 2:10:35 AM3/2/13
to php...@googlegroups.com
For me the $options argument is a good one together with well defined constants on interface level.
Not having interface constants would open to non standard option keys.
Working with interfaces as markers for storage features also is a good idea in my opinion to inform the consumer what the cahe supports. Or what's wrong with marker interfaces here?

PS: That also could make TTL vs. TTD usage be standard by different constants.

Marc

Andrew Eddie

unread,
Mar 2, 2013, 2:20:20 AM3/2/13
to php...@googlegroups.com
On 2 March 2013 07:52, Paul Dragoonis <drag...@gmail.com> wrote:
My vote from the beginning is set($key, $val, $ttl = null).. I've already laid out why this is good for libraries that do and don't support expiration.

Paul, are you saying we should just have that in CacheInterface? Either way I agree.

As far as options go, I can't see how we'd be able to lock it down tight enough to be used consistently across the board. I'd leave options out of it.

I'm also eager to see a final draft - it's good timing.

Regards,
Andrew Eddie

Florin Patan

unread,
Mar 2, 2013, 9:06:30 AM3/2/13
to php...@googlegroups.com
Everyone,


Please review the proposal as well. I've updated to include the last feedback and I plan not to change anything in it, from functional point of view unless I've missed something critical in it.

I'll gladly update anything that's related to typos/grammar and suggestions on how to improve the documentation for it.

Paul, feel free to use this version for submission to the rest of the voting members.

Thank you all for contributing to this effort.



Best regards,
Florin

Andrew Eddie

unread,
Mar 2, 2013, 3:45:37 PM3/2/13
to php...@googlegroups.com
On 3 March 2013 00:06, Florin Patan <flori...@gmail.com> wrote:
Please review the proposal as well. I've updated to include the last feedback and I plan not to change anything in it, from functional point of view unless I've missed something critical in it.

Just a small request. Can you include the link when you update it please :)

Regards,
Andrew Eddie

Florin Patan

unread,
Mar 2, 2013, 3:48:12 PM3/2/13
to php...@googlegroups.com

Andrew Eddie

unread,
Mar 2, 2013, 10:41:53 PM3/2/13
to php...@googlegroups.com
That's looking really great. There are a few grammar issues in there and I'd like to see the DocBlocks expanded a bit - what is the best way to help you with that? Offline?

Regards,
Andrew Eddie 

Paul Dragoonis

unread,
Mar 2, 2013, 11:02:46 PM3/2/13
to php...@googlegroups.com
Hi Andrew,

If you fork Florin's (dlsniper) repository to your github account, you can push changes to your own fork of it, and request a PR from your fork/repo, to florin's repo.

Hope that made sense.

Cheers,
Paul


--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.
Message has been deleted
Message has been deleted

Florin Patan

unread,
Mar 4, 2013, 3:34:01 AM3/4/13
to php...@googlegroups.com
Andrew feel free to fork, edit and send a PR, I'll merge it asap. Or if you want you can send me an e-mail with the changes or write them here :)

Thank you for helping out ;)


Regards.

Amy Stephen

unread,
Mar 5, 2013, 11:21:56 PM3/5/13
to php...@googlegroups.com
Florin -

Thanks for your work on this, appreciate how you are balancing all of these comments and ideas.

I was looking at these messages and the history on the proposal, but I can't seem to figure out when the "multiple" methods were added. If you have quick access to a link where this was discussed, I'd appreciate.

My gut feeling is getMultiple, setMultiple and removeMultiple, could be removed and iterated outside of the cache package, but I'd like to understand why this was added.

It's not a big deal, I just thought your new, simplified version was nice and easy for the first go at the Interface.

Anyone else starting to think a basic data mapper - with a create, read, update, delete method - might cover many interfaces?

Again, thanks for your work - what a patient person. =)

On Saturday, December 1, 2012 1:41:23 PM UTC-6, Florin Patan wrote:
In an attempt to unify the proposals as well as some information from real life scenarios,
I've created the following proposal for caching interfaces: 

Please review it and help me improve it so that at some point we could vote on this matter
and give the community a direction for this matter.

Thank you for your time and support!


Best regards.

Florin Patan

unread,
Mar 6, 2013, 3:52:55 AM3/6/13
to php...@googlegroups.com
Hey Amy,


The *Multiple methods where added from the start as generally the various caching backends have the ability to perform operations on multiple keys at once.
This is needed especially when you can optimize the save/retrieve process of cached items and handle these operations in batches.
As an example:
- you want to cache 30 products
- you can go the way: 30 requests to save each record or do one request to save 30 records
- due to latency and other factors, generally is faster to have one request instead of 30 (safe for a few cases where caching to APC would be just about slightly faster)

It's true that some backends might not support multiple operations but the implementing libraries can then emulate this from their code and away from the userland.

Meanwhile, all three proposals have been merged into a single one by Paul Dragoonis and you can have a look on it here: https://github.com/dragoonis/fig-standards/blob/master/proposed/psr-cache.md

There are a few things that would need to be ironed out before submitting it for everyone but if you have anything that could help out, feel free to either send a PR on GH or comment here (until the big thread opens ofc). I don't have any eta for when Paul is going to open the proposal but I think it would happen soonish :)

There was an idea to only leave three methods: set() get() and remove() which could accept a string or an array but like I've said, I'm not a big fan of that, aside from the fact that you can typehint array, as it would make the userland code potentially unclear about what's happening there and you'd need some way to unify the method parameters as well since set($key, $value, $ttl) is not the same as set(array($key => $value, $key2 => $value), $ttl) or even set(array($key => array($value, $ttl), $key2 => array($value2, $ttl2))). Paul said he'll leave this as a open question for the proposal and have everyone look on it and have a vote on this option as well.


Best regards,
Florin
Reply all
Reply to author
Forward
0 new messages