Как реализовать кэш Guava со значением как количество попаданий? - PullRequest
0 голосов
/ 08 октября 2018

Я пытаюсь реализовать кеш, который будет подсчитывать количество попыток входа в систему за последние 5 минут, в своем коде я хочу проверить, не пытался ли пользователь выполнить больше, чем MAX_ATTEMPTS.

Во всехПримеры кода, которые я нашел в Интернете для "Guava Cache", используют метод load, чтобы извлечь значение из какого-либо другого источника или вычислить его, используя какой-либо метод. Как я могу увеличивать его при каждом попадании в кэш?

static LoadingCache<String, Integer> cache = CacheBuilder.newBuilder()
    .maximumSize(100000)
    .expireAfterAccess(5, TimeUnit.MINUTES)
    .build(
            new CacheLoader<String, Integer>() {
                public Integerload(String user) {
                       return ????;
                }
            }
    );

позже во время выполнения я хотел бы проверить:

if(cache.getIfPresent(user) != null && cache.get(user) > MAX_ATTEMPTS)

, а также увеличить его, если:

if(cache.getIfPresent(user) != null && cache.get(user) <= MAX_ATTEMPTS)

Ответы [ 3 ]

0 голосов
/ 09 октября 2018

решено с использованием только функции кэширования Guava (без использования загрузчика)

Кэш выглядит так:

public class ForgetPasswordAttemptsCache {

    private static final Cache<String, Integer> forgetPasswordCache = CacheBuilder.newBuilder()
            .expireAfterAccess(24, TimeUnit.HOURS)
            .build();

    private ForgetPasswordAttemptsCache(){
    }

    public static Cache<String, Integer> getInstance() {
        return forgetPasswordCache;
    }

}

и его использование:

final String email = user.getEmail();
Integer currentCount = ForgetPasswordAttemptsCache.getInstance().getIfPresent(email);

if (currentCount != null && currentCount >= RESET_PASSWORD_MAX_ATTEMPTS) {
    logger.error("User with id: " + user.getId() + " and email: " + email +
            " has reached the maximum number of reset password attempts, the mail will not be sent");
    return;
}

if (currentCount == null) {
    ForgetPasswordAttemptsCache.getInstance().put(email, new Integer(1));
} else {
    ForgetPasswordAttemptsCache.getInstance().put(email, new Integer(currentCount + 1));
}

Спасибо, spi за это решение.(сейчас я ищу способ протестировать его без проведения теста, который выполняется 24 часа.)

0 голосов
/ 10 октября 2018

@ Oren Ваше решение не является поточно-ориентированным, поскольку вы работаете со значением вне Cache.Вам лучше использовать Cache#asMap() просматривать и изменять значение внутри ConcurrentMap#compute(K, BiFunction<K, V, V>) метод:

forgetPasswordCache.asMap().compute(email, (cachedEmail, currentCount) -> {
  if (currentCount != null && currentCount >= RESET_PASSWORD_MAX_ATTEMPTS) {
    logger.error("User with id: " + user.getId() + " and email: " + email +
         " has reached the maximum number of reset password attempts, the mail will not be sent");
    return null;
  }

  if (currentCount == null) {
    return 1;
  } else {
    return currentCount + 1;
  }
});
0 голосов
/ 09 октября 2018

Вы можете попробовать и адаптировать следующий фрагмент:

public class Demo {
    public static void main(String[] x) {
        CacheLoader<String, AtomicInteger> initialValueLoader = new CacheLoader<String, AtomicInteger>() {
            @Override
            public AtomicInteger load(String key) {
                // do not care of the key. everybody starts with 0 login attempts.
                return new AtomicInteger(0);
            }
        };

        LoadingCache<String, AtomicInteger> c = CacheBuilder
            .newBuilder()
            .maximumSize(100000)
            .expireAfterAccess(2, TimeUnit.SECONDS)
            .build(initialValueLoader);

        String user = "bob";

        try {
            // when the user tries to login, increment the attemps by one
            Verify.verify(c.get(user).incrementAndGet() == 1);

            // next call will get one
            Verify.verify(c.get(user).get() == 1);
        } catch (ExecutionException e) {
            throw new RuntimeException("oups: " + e, e);
        }

        // simulate time
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
        }

        // after some time, the cache is cleared
        try {
            Verify.verify(c.get(user).get() == 0);
        } catch (ExecutionException e) {
            throw new RuntimeException("oups: " + e, e);
        }

        System.out.println("done.");
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...