adding async expiration listener outside of builder causes problems
See original GitHub issueThe behavior I’m seeing in my app is that the async expiration listener that I add after building the ExpiringMap doesn’t receive its callbacks and some of the items in the map don’t expire.
You can see a unit test for this on my fork that recreates the problem.
Adding in Builder and After works
ExpiringMap<String, String> map = ExpiringMap.builder()
.expiration(100, TimeUnit.MILLISECONDS)
.asyncExpirationListener((thekey, thevalue) -> {
System.out.println("builder one called");
})
.build();
map.addAsyncExpirationListener((thekey, thevalue) -> {
System.out.println("after builder called");
});
Adding only after the builder doesn’t work
ExpiringMap<String, String> map = ExpiringMap.builder()
.expiration(100, TimeUnit.MILLISECONDS)
.build();
map.addAsyncExpirationListener((thekey, thevalue) -> {
System.out.println("after builder called");
});
In this case, the expiration listener isn’t called and I’m also seeing that some items don’t expire from the map. In all cases I’m adding the listener immediately after building the map and before putting any items in it.
Note that in my branch I added priority to the TestNG methods. If I run the whole suite and your existing tests run first then everything works. If I just run my test then it fails. If I sequence the tests such that mine run first then the failure is present. I haven’t dug into the ExpiringMap or its builder to see what might be sensitive to the ordering of the tests but I don’t see anything shared between them the way the existing tests were written.
Issue Analytics
- State:
- Created 6 years ago
- Comments:6 (4 by maintainers)
Top GitHub Comments
This was released in 0.5.10.
The source of the problem is in ExpiringMap’s private constructor where it only initializes the static LISTENER_SERVICE and THREAD_FACTORY if the builder has async listeners.
This explains why the tests need to be ordered they way they are.