Geyser14
Geyser14

Reputation: 1425

Guava Cache<K, V>.put(key, value) not adding values to my cache; put() method not working

I have a simple cache intended for storing Guava RateLimiter instances by IP. See code block below. The put() call does not put anything into cache. Is there some limitation against storing a RateLimiter in a Guava Cache? Is there something obvious I'm missing?

@Component
public class MyRateLimiter {

  public static final Logger LOGGER = LoggerFactory.getLogger(MyRateLimiter.class);
  public static long CACHE_SIZE = 1000L;
  public static long TIMEOUT = 10L;

  private static Cache<String, RateLimiter> cache = CacheBuilder.newBuilder()
        .maximumSize(CACHE_SIZE)
        .expireAfterWrite(TIMEOUT, TimeUnit.MINUTES)
        .build();

  public boolean tryAcquire(String key, double secondsBeforeNextOperation) {
      RateLimiter rateLimiter = cache.getIfPresent(key);
      if (rateLimiter == null) {
          rateLimiter = getNewRateLimiter(secondsBeforeNextOperation);
          cache.put(key, rateLimiter);  // <- This executes..
      }
      return rateLimiter.tryAcquire();  // <- But cache is still empty at breakpoint here
  }

  private RateLimiter getNewRateLimiter(double secondsBeforeNextOperation) {
      return RateLimiter.create(1 / secondsBeforeNextOperation);
  }

}

This code happens to run in a Spring Component but it is singleton-scoped by default and the cache is static. Furthermore, I set a breakpoint on the return rateLimiter.tryAcquire() line and cache is still empty, even one line of code after the cache.put() line just executed.

JVM is Java 8 and I'm running in Spring Boot.

---UPDATE---

Here is my tryAcquire() method where I use get(K, Callable<V>):

public boolean tryAcquire(String key, double secondsBeforeNextOperation) {
    RateLimiter rateLimiter = null;
    try {
        rateLimiter = cache.get(key, () ->
                getNewRateLimiter(secondsBeforeNextOperation));
    } catch (ExecutionException e) {
        LOGGER.warn("Throttling cache was not able to be read.");
        return false;
    }
    return rateLimiter.tryAcquire();  // <-- cache still empty at this breakpoint
}

Upvotes: 1

Views: 903

Answers (3)

Brunaldo
Brunaldo

Reputation: 324

This was happening to me because the expireAfterWrite was being set as 0

Upvotes: 0

Maksim R
Maksim R

Reputation: 11

Faced with the same problem and decided to debug it, the deletion occurs at the end of the logic of the put method in the "evictEntries" method because maxSegmentWeight = 0, add a custom weigher which return 0

    private final Cache<Long, Object> cache =
    CacheBuilder.newBuilder()
        .expireAfterWrite(60, TimeUnit.SECONDS)
        .weigher((key, value) -> 0)
        .maximumWeight(1000L)
        .build();

Upvotes: 1

isomeme
isomeme

Reputation: 471

Exactly how are you determining that the cache is empty on the line with your breakpoint comment? I'd be very interested to see the result of printing/logging the value of cache.asMap() at that same place.

Upvotes: 0

Related Questions