How to configure guava cache to remove item after a read?

2.3k views Asked by At

I would like to remove (invalidate) an item after it was read from a cache.

So item should be present in a cache until a first read.

I've tried adding expireAfterAccess(0, TimeUnit.NANOSECONDS) but then cache is not populated.

Is there any way to use guava cache in such manner or do I need to invalidate item manually after a read?

3

There are 3 answers

3
maaartinus On BEST ANSWER

This won't work. "Access" means "read or write access" and when it expires immediately after read, then it also expires immediately after write.

You can remove the entry manually. You can use the asMap() view in order to do it in a single access:

String getAndClear(String key) {
    String[] result = {null};    
    cache.asMap().compute(key, (k, v) ->
        result[0] = v;
        return null;
    });
    return result[0];
}

You could switch to Caffeine, which is sort of more advanced Guava cache and offers very flexible expireAfter(Expiry).

However, I don't think, that what you want is a job for a cache. As nonces should never be repeated, I can't imagine any reason to store them. Usually, you generate and use them immediately.

You may be doing it wrong and you may want to elaborate, so that a possible security problem gets avoided.

0
Oleksandr Bondarchuk On

In my example nonce are created twice:

LoadingCache<String, String> cache = CacheBuilder.newBuilder().expireAfterAccess(0, TimeUnit.NANOSECONDS)
    .build(new CacheLoader<String, String>() {
        @Override
        public String load(String key) throws Exception {
            return createNonce();
        }
    });

@Test
public void test_cache_eviction() throws Exception {
    String nonce1 = cache.getUnchecked("key");
    String nonce2 = cache.getUnchecked("key");
}

public String createNonce() {
    String createdNonce = "createdNonce";
    System.out.println(createdNonce);
    return createdNonce;
}

In logs "createdNonce" are printed twice.

0
cruftex On

The operation get and remove is a simple remove on the map interface:

 Object cachedValue = cache.asMap().remove(key);