cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Steven Dolg <>
Subject Re: [c3] Conditional GET
Date Thu, 10 Dec 2009 10:40:57 GMT
Sylvain Wallez schrieb:
> Reinhard Pötz wrote:
> <snip/>
>> But let me broaden the picture: Based on our work from about two weeks
>> ago, I created another aspect which implements the support for
>> conditional GET requests and also takes care that a pipeline isn't
>> executed unless it is really necessary. I was also able to fix all
>> failing test cases. I created an issue that contains a patch:
>> Additionally there is also another feature that I would like to add: The
>> current patch only takes care of 'If-Modified-Since' requests. I also
>> want to support 'If-None-Match' requests that are based on the 'ETag'
>> response header. (see
>> Using ETag has the advantage that we could support conditional GET
>> requests also in the case where we can't use a timestamp based approach
>>  (e.g. when using o.a.c.pipeline.caching.ParameterCacheKey) or to
>> provide conditional GET support in REST controllers.
>> As an ETag value we could use the hash code of a pipeline's cache key.
> I don't fully get the context of this conversation, but this last 
> sentence triggered a question to me: how can we validate a cache entry 
> with its _key_? Looking at the code, I see that CacheKey holds both 
> the identifier information (the actual key) and the validity information.
> There is a naming issue here which leads to some confusion between key 
> and key-and-validity that we can see it in the code: ExpiresCacheKey 
> doesn't include the validity information in hashcode() and equals() 
> whereas ParameterCacheKey does. What is the right contract?

I'm not sure I understand what you mean.
The implementations of hashCode() in ExpiresCacheKey and 
ParameterCacheKey are as similar in both the code and actual behaviour 
as they can be.
Neither of them performs any operations necessary to check their 
validity in the hashCode() or equals() methods.

Your confusion might arrise from the point that ParameterCacheKey cannot 
become invalid because the same parameter value means always the same 
parameter value, there is no way this can become invalid (as opposed to 
a cache file contents which can become invalid when the file is changed, 
even if it is still the same file)
So the isValid() method basically performs the equals check, since this 
is a required condition for being valid. (valid = equal & not expired; 
since expired = false here: valid = equal).

The ExpiresCacheKey performs an additional check in its isValid() 
method, namely checking the expiresTimestamp.
This is not done in either the hashcode() or equals() method. So here 
valid := equals & not expired.

This principle holds true for each and every CacheKey currently 
implemented (unless there is faulty implementation).
And this is also the answer to your question:
CacheKey contains information to check its validity, but this 
information is not used for identifying (iow, equals() and hashCode() 
methods) CacheKeys.
Which means frequently invalidated CacheKeys will not fill the cache but 
instead overwrite each other.

> As a side note, both classes include the class' hashcode in the 
> instance's hash code, which means hash codes will be different a every 
> JVM restart, or across JVM instances in a cluster, and is likely to 
> break persistent and distributed caches.

That is a good hint.
We will want to look into that and amend things if necessary.

> That being said, I'm wondering if this aggregation of key and validity 
> won't cause other kinds of problems with distributed cache 
> implementations. For example, Java memcached clients serialize the 
> cache key and use this result as the memcache key. If the key includes 
> validity information, the memcache key will change every time the 
> underlying data changes (e.g. a file's timestamp).
> At first sight, this can sound good as it means we will have a cache 
> miss when the validity has changed, and will even avoid having to 
> compare the validity of cached content. But this can have a desastrous 
> impact on the cache efficiency in situations where you have some often 
> requested content that changes frequently: the cache will quickly fill 
> up with obsolete versions of this content under different key values, 
> that will lead older content to be evicted, reducing the overall cache 
> efficiency. Whereas a key that's only an indentifier will lead the 
> entry to be _replaced_ and not a new one being added.
> So in the end, my feeling is that key and validity information really 
> should be separated.
> Now going back to the ETag discussion, using the pipeline's cache key 
> won't work IMHO because of the implementation of some key's hashcode() 
> using only the identifier part of the key and not the validity. 
> Confusion, I told you ;-)

We (intend to) use a layer for integrating caches since we don't want to 
compile directly against the API of one specific provider and then have 
to stick with that provider till the end of time (Avalon, anyone?)

This additional layer is used to perform validity checks when necessary 
and/or desired and not check the validity if not.
The intention here is to reuse the abstraction layer and not have this 
kind of (critical) logic scattered in the individual cache provider 

So it is possible to check if a CacheKey is pointing to the same 
resource *and* if that cached data is still valid - even tho the 
underlying cache provider has no means of performing the second check 

For details you might want to look at 

> And BTW, what is the "jmxGroupName" property on CacheKey used for?

The jmxGroupName is used for making them accessible via JMX, no?

> Sylvain


View raw message