JakeWharton / DiskLruCache

Java implementation of a Disk-based LRU cache which specifically targets Android compatibility.
http://jakewharton.github.io/DiskLruCache
Apache License 2.0
5.79k stars 1.18k forks source link

Support absolute expiration #3

Closed tonnguyen closed 12 years ago

tonnguyen commented 12 years ago

I'm intending to use DiskLruCache to cache all Http Request from my application. Every request to a server will be cached for re-using.

It would be great if we can configure the absolute expiration for the cache, so after an amount of time, cache will be cleared automatically, in order to get fresh data, and then cache it.

miroslavign commented 12 years ago

Yes, I totally agree with this suggestion. This could be the most useful new feature.

lexs commented 12 years ago

I don't this should be implemented in the library itself. Instead write to a separate index when the entry expires. Then when you read back you can compare this, and if it has expired clear it.

This would also enable you to do conditional get and then update only the expires timestamp.

JakeWharton commented 12 years ago

I'm going to side with @lexs on this and deem it as out-of-scope. There's a few ways to do this with a wrapper around DiskLruCache's classes or a separate index.

fraggle222 commented 11 years ago

Ok, I don't get it. Vote to re-open or please explain: Are there really no expirations of any kind in this code? Most cache's have a way to expire content, that's why they are a cache, not permanent storage. Maybe i'm missing it, if so sorry for the noob comment.

JakeWharton commented 11 years ago

The cache expires by a fixed size and by ordering by recently accessed items. If you don't access entry A while accessing and writing a bunch of others (B, C, D, E, etc.) then eventually A will be bubbled out of the cache. You can read more about LRU on wikipedia: https://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used


Jake Wharton http://about.me/jakewharton

On Wed, Oct 30, 2013 at 7:54 AM, fraggle222 notifications@github.comwrote:

Ok, I don't get it. Vote to re-open or please explain: Are there really no expirations of any kind in this code? Most cache's have a way to expire content, that's why they are a cache, not permanent storage. Maybe i'm missing it, if so sorry for the noob comment.

— Reply to this email directly or view it on GitHubhttps://github.com/JakeWharton/DiskLruCache/issues/3#issuecomment-27395838 .

fraggle222 commented 11 years ago

Thanks for responding. I get LRU. But that leaves the general problem of item expiration unsolved:

Use case: you are utilizing a service that lets you cache images for at most 3 days. After that you are required to refresh the image.

Or anytime you want to have a max age on a particular file or even for the entire cache in general.

Just seems like a common issue and one that I have right now: need to save some images, but I want to force a refresh every x number of days. Images are saved at different times, so not one global timeout in this case.

Seems like I can't use your cache library for this without independently writing the code to check the file last mod times, and that just seems weird to do when I'm using a caching library to control this stuff.

Would prefer DiskLruCache.get(String key, long maxAge); and have it return null if expired or better DiskLruCache.isExpired(String key, long maxAge);

JakeWharton commented 11 years ago

Max age is an application level constraint. You can look at OkHttp which uses this library to implement the HTTP caching semantics as an example. On Oct 30, 2013 8:48 AM, "fraggle222" notifications@github.com wrote:

Thanks for responding. I get LRU. But that leaves the general problem of item expiration unsolved:

Use case: you are utilizing a service that lets you cache images for at most 3 days. After that you are required to refresh the image.

Or anytime you want to have a max age on a particular file or even for the entire cache in general.

Just seems like a common issue and one that I have right now: need to save some images, but I want to force a refresh every x number of days. Images are saved at different times, so not one global timeout in this case.

Seems like I can't use your cache library for this without independently writing the code to check the file last mod times, and that just seems weird to do when I'm using a caching library to control this stuff.

Would prefer DiskLruCache.get(String key, long maxAge); and have it return null if expired or better DiskLruCache.isExpired(String key, long maxAge);

— Reply to this email directly or view it on GitHubhttps://github.com/JakeWharton/DiskLruCache/issues/3#issuecomment-27402224 .

fraggle222 commented 11 years ago

Ok, strange I'll have to take a look at that.

Seems like your library doesn't give any access to the underlying File objects right, just gives access to InputStreams? So I'm not sure how any code can determine a cached files created time or modified time without independently checking the file. This requires knowing the file structure and naming in the cache, which external code shouldn't need to do since that is stuff that is essentially private to your library.

An alternate request then would be to give access to a File object for cached files, or if that is too concrete then to give access to the last time the entry was put into the cache.

{edited at 12:42pm edt}

JakeWharton commented 11 years ago

The time is stored as a key on the entry, not read from the underlying file.

fraggle222 commented 11 years ago

In DiskLruCache? Not seeing that. I'll do some more digging. No timestamps in the journal. No access to Entry from the Editor for a snapshot, no time info in the Entry class anyway, getCleanFile is private. Maybe I'm missing it somewhere. I see no time info anywhere in DiskLruCache, nor any way to get to the underlying file info.

My hack so far: public long getAge(String key) { File file=new File(mDiskCache.getDirectory(),key+".0"); //hack return file.lastModified(); }

DHuckaby commented 11 years ago

Store it separately, DiskLruCache isn't meant to do everything. It is a highly specific datastore. For example, just store the last modified time in SharedPreferences with the same key as your DiskLruCache entry. Update it when you update your entry.

JakeWharton commented 11 years ago

Store the time in the entry of the cache!

DiskLruCache.Editor e = cache.edit("somekey");
e.set(0, "DATE"); // Modification date, or expiration date, or creation date
e.set(1, "DATA");
e.commit();
DHuckaby commented 11 years ago

@JakeWharton's answer has a better solution.

fraggle222 commented 11 years ago

@JakeWharton , ok thanks, I'll try that approach, much appreciated.