Skip to content

Expiration triggered by cache.asMap iterators doesn't notify RemovalListener #487

@avgustinmm

Description

@avgustinmm

I have an 'expire after access' cache (Caffeine version: 2.8.8) with values that I need to close (grpc managed channels). I have two close points:

  • in removal listener - when value is not used for some time
  • when my service is stopping - iterating cache.asMap().values() in order to close all that left

however, asMap iteration doesn't return expired values (which, seeing some posted issues, seems expected) , but the problem is that RemovalListener doesn't get notifications for expired entries.

There is a simple code that demonstrates this:

final LoadingCache<String, String> cache = Caffeine.newBuilder().weakKeys().removalListener((key, value, reason) -> {
  System.out.println("[" + value + "] remove -(" + reason + ")");
}).expireAfterAccess(1, TimeUnit.SECONDS).build(key -> {
  System.out.println("[" + key + "] create");
  return key;
});

for (int i = 0; i < 10; i++) {
  cache.get(String.valueOf(i));
}

Thread.sleep(2_000);

final Collection<String> values = cache.asMap().values();
System.out.println("cache.asMap() size: " + values.size());
for (final String value : values) {
  System.out.println("->cache.asMap()  value: " + value);
}

I found out that cache.cleanUp() just before cache asMap() will trigger expiration that notifies RemovalListener, but this just could mitigate the issue (will notify for some expirations). However, if an entry expire between cleanUp and asMap - this entry will still be lost.

I believe that triggered by cache.asMap iteration expirations shall notify RemovalListener.
Is there a way to implement that value cleanup correctly with current Caffeine release?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions