Search code examples
javacachingguava

Guava Cache not expiring after x timeunit when using timed expire


I'm having an issue where my guava cache is not expiring. I'll leave my code down below. The cache only expires one I write to the cache again. But from what I took from that javadocs about timed expiration is that it should expire x timeunit after writing. Any help would be appreciated.

    private static final Cache<UUID, RainbowWrapper> RAINBOWS = CacheBuilder.newBuilder()
        .removalListener(new RemovalListener<UUID, RainbowWrapper>() {
            @Override
            public void onRemoval(RemovalNotification<UUID, RainbowWrapper> notification) {
                CoreAPI.debug("Removing rainbow: " + notification.getKey().toString());
                RainbowWrapper wrapper = notification.getValue();
                for (UUID uuid : wrapper.getUuids()) {
                    CoreAPI.debug("Removing entity: " + uuid);
                    Bukkit.getWorlds().get(0).getEntitiesByClasses(Item.class, ArmorStand.class).stream()
                            .filter(entity -> entity.getUniqueId().equals(uuid))
                            .forEach(org.bukkit.entity.Entity::remove);
                }
            }
        }).expireAfterWrite(FADE_TIME, TimeUnit.SECONDS).build();

Solution

  • This is explained on the Guava wiki under When does Cleanup happen?

    Basically, as long as you do not call any methods of your cache, nothing happens at all, because it is impossible to do without creating an own thread for the cache, which is often undesired and thus not done automatically by the Guava cache.

    If you only have read accesses to your cache, it may also take a while for your removal listener to get called, because Guava assumes that read accesses to the cache should be fast, and thus tries to do as little work as possible for read accesses, which means it typically does not call removal listeners. Only if there have been no write accesses for some time, the cache will do cleanup and call removal listeners also at a read access.

    Note that this still means that the expire feature is working: expired entries won't be returned from any cache methods. It may only happen that the removal listeners are called later than you expect.

    If you want to force timely removal notifications, you should call Cache.cleanUp() regularly (e.g., from a separate thread).

    If it is important for you to get notified as soon as possible when the time elapses, I would simply use a ScheduledExecutorService and submit tasks to it instead of relying on a cache and its removal notifications.