Created
April 10, 2014 15:49
-
-
Save kdrakon/10396036 to your computer and use it in GitHub Desktop.
A Guava cache that defaults to old values in the event of failure
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.concurrent.Callable; | |
import java.util.concurrent.ExecutionException; | |
import java.util.concurrent.ExecutorService; | |
import java.util.concurrent.Executors; | |
import java.util.concurrent.TimeUnit; | |
import com.google.common.cache.CacheBuilder; | |
import com.google.common.cache.CacheLoader; | |
import com.google.common.cache.LoadingCache; | |
import com.google.common.util.concurrent.ListenableFuture; | |
import com.google.common.util.concurrent.ListenableFutureTask; | |
public class KindaLikeASelfRefreshingCache | |
{ | |
static class CacheLoaderA extends CacheLoader<String, String> | |
{ | |
private static final ExecutorService service = Executors.newSingleThreadScheduledExecutor(); | |
private volatile boolean shouldFail = true; | |
@Override | |
public String load(String key) throws Exception | |
{ | |
/* | |
* The first call to load() happens on the first get() of the cache. Subsequent calls | |
* are made concurrently via the reload() method. | |
*/ | |
// we'll fail every other execution | |
shouldFail = !shouldFail; | |
if (shouldFail) | |
{ | |
System.out.println("Throwing exception, we'll be returning the old value for now"); | |
throw new Exception(); | |
} | |
return key.concat("_VALUE"); | |
} | |
@Override | |
public ListenableFuture<String> reload(final String key, final String oldValue) throws Exception | |
{ | |
System.out.println("Starting concurrent thread to get new value"); | |
ListenableFutureTask<String> task = ListenableFutureTask.create(new Callable<String>() { | |
@Override | |
public String call() throws Exception | |
{ | |
try | |
{ | |
// try to get a new value | |
return load(key); | |
} catch (Throwable e) | |
{ | |
// or return the old one in the event of failure | |
return oldValue; | |
} | |
} | |
}); | |
// run in the background so that concurrent get() requests still return values. | |
service.execute(task); | |
return task; | |
} | |
} | |
public static void main(String[] args) throws InterruptedException | |
{ | |
LoadingCache<String, String> cache = | |
CacheBuilder.newBuilder().refreshAfterWrite(2, TimeUnit.SECONDS).build(new CacheLoaderA()); | |
while (true) | |
{ | |
/* | |
* I make requests faster than the timeout above to show that values -- 'old' or 'new' | |
* are consistently returned | |
*/ | |
Thread.sleep(500); | |
try | |
{ | |
System.out.println("Returning: " + cache.get("key")); | |
} catch (ExecutionException e) | |
{ | |
// should never happen | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
this is what i want ,thank you very much!