Comments (12)
Yeah, we normally use Awaitility, but it wasn't important in this case. I will test it next week, when I am working on this again and let you know. I'm pretty sure I already tested it with an executor as well. I just removed it to keep the test as small as possible.
from caffeine.
Thanks! Can you check if this is the same as #1478? Sorry, I haven't had time to work on this project and will try to trace through your test this evening.
from caffeine.
Oh, that other issue was only for an AsyncCache and unrelated to this.
Here your tests passes for me and I see multiple refreshes. If I add a println to your loader then it shows two refreshes. So it seems to be working on v3.1.8. What version are you using?
from caffeine.
Sorry, I should have written the test, so that it fails. In the correct case, all the times(x) should increase, but it doesn't in the second one.
from caffeine.
It should fail like this.
@Test
public void refreshingCacheWithRuntimeException() throws InterruptedException {
RuntimeExceptionTestCacheLoader runtimeExceptionTestCacheLoader = Mockito.spy(new RuntimeExceptionTestCacheLoader());
LoadingCache<String, String> cache = Caffeine.newBuilder()
.refreshAfterWrite(Duration.ofNanos(1))
.expireAfterWrite(Duration.ofSeconds(1))
.build(runtimeExceptionTestCacheLoader::apply);
cache.put("key", "value");
String value = cache.get("key");
assertEquals("value", value);
verify(runtimeExceptionTestCacheLoader, timeout(1000).times(1)).apply("key");
value = cache.get("key");
assertEquals("value", value);
// This should've already called the loader again, but it doesn't.
verify(runtimeExceptionTestCacheLoader, timeout(1000).times(2)).apply("key");
// Wait for it to expire
Thread.sleep(1500);
assertThrows(RuntimeException.class, () -> cache.get("key"));
verify(runtimeExceptionTestCacheLoader, timeout(2000).times(3)).apply("key");
}
public static class RuntimeExceptionTestCacheLoader implements Function<String, String> {
@Override
public String apply(String key) {
throw new RuntimeException("Test");
}
}
from caffeine.
I think you might be hitting a race condition because you are using the default executor, making things async. If I use a caller runs executor and make it more explicit using a CacheLoader
, then I think it gives the right results?
@Test
public void refreshingCacheWithRuntimeException() throws InterruptedException {
var runtimeExceptionTestCacheLoader = Mockito.spy(new RuntimeExceptionTestCacheLoader());
LoadingCache<String, String> cache = Caffeine.newBuilder()
.executor(Runnable::run)
.refreshAfterWrite(Duration.ofNanos(1))
.expireAfterWrite(Duration.ofSeconds(1))
.build(runtimeExceptionTestCacheLoader);
cache.put("key", "value");
String value = cache.get("key");
assertEquals("value", value);
verify(runtimeExceptionTestCacheLoader, timeout(1000).times(1)).reload(eq("key"), anyString());
value = cache.get("key");
assertEquals("value", value);
// This should've already called the loader again, but it doesn't.
verify(runtimeExceptionTestCacheLoader, timeout(1000).times(2)).reload(eq("key"), anyString());
// Wait for it to expire
Thread.sleep(1500);
assertThrows(RuntimeException.class, () -> cache.get("key"));
verify(runtimeExceptionTestCacheLoader, timeout(2000).times(1)).load("key");
}
public static class RuntimeExceptionTestCacheLoader implements CacheLoader<String, String> {
@Override
public String load(String key) {
System.err.println("Loading key: " + key);
throw new RuntimeException("Test");
}
@Override
public String reload(String key, String oldValue) {
System.err.println("Refreshing key: " + key);
throw new RuntimeException("Test");
}
}
from caffeine.
fyi adding .executor(Runnable::run)
to your test passes
from caffeine.
When you do want to write a concurrent test, using a FakeTicker
and Awaitility
to manage time and concurrency really helpful. Using sleeps is unfortunately error prone so its better to coordinate it more explicitly. Those two are really good tools.
from caffeine.
Actually, I tested it really quick, yes adding an executor seems to fix it. What I did was adding a scheduler in the past.
from caffeine.
Thanks for your help! Really appreciate it.
from caffeine.
thanks. When I sprinkle some awaits after the cache.get
calls then it passes using the default executor,
await().until(() -> cache.policy().refreshes().isEmpty());
from caffeine.
wonderful! glad its not an issue. let me know if you run into anything else.
from caffeine.
Related Issues (20)
- Mutable key may cause cpu load 100% HOT 5
- Race condition in FrequencySketch HOT 10
- Get the least recent used key-value HOT 1
- Deadlock in Caffeine? HOT 5
- Request: Version of LoadingCache with Synchronous Behavior for Invalidate HOT 3
- Outdated documentation on how to get traces automatically HOT 2
- Throughput issues / threads are parked HOT 32
- BoundedLocalCache.doComputeIfAbsent calls slow IdeKotlinModuleDependentsProvider on the UI thread and freezes for 65sec HOT 5
- Different behavior from expireAfter and expireAfterWrite HOT 4
- LocalAsyncCache#handleCompletion does not properly handle cancellation in mapping function and logs the warning HOT 4
- The new created entry is easy to be evicted when maxWeight is set. HOT 7
- Question: difference in performance between `Cache#get()` and `Cache.asMap()#compute` HOT 5
- Make checker-qual dependency optional? HOT 1
- Why weak or soft keys/values can not be combined with Async[Loading]Cache? HOT 1
- Allow transferring eviction metadata HOT 4
- Pinning of values in the cache HOT 12
- I am using reactive version of caffeine cache version 3.1.8 HOT 3
- Sometimes StackOverflowError (reflect.InvocationTargetException) occurs while init caffein cache with spring boot HOT 4
- [Docs] Update Wiki page about Statistics HOT 2
- is StatsCounter solely intended for consumption by Cache implementors? HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from caffeine.