根据时间戳条件删除 Caffeine 条目

Delete Caffeine entries based on a timestamp condition

有没有办法根据时间戳条件删除咖啡因条目?例如。, 在 T1 我有以下条目

K1 -> V1
K2 -> V2
K3 -> V3

时间 T2 我只更新 K2K3。 (我不知道这两个条目是否会有 exact 时间戳。K2 可能有 T2K3 可能是 T2 + some nanos。但是为了这个问题让我们假设他们这样做)

现在我希望咖啡因使条目 K1 -> V1 无效,因为 T1 < T2.

执行此操作的一种方法是遍历条目并检查它们的写入时间戳是否 < T2。收集这些密钥,最后调用 invalidateKeys(keys).

也许有一种非迭代的方式?

如果您使用的是expireAfterWrite,那么您可以获得按时间戳顺序排列的条目快照。由于此调用需要获得逐出锁,因此它提供了一个不可变的快照而不是迭代器。那很乱,例如您必须提供一个可能不正确的限制,它取决于到期时间。

Duration maxAge = Duration.ofMinutes(1);
cache.policy().expireAfterWrite().ifPresent(policy -> {
  Map<K, V> oldest = policy.oldest(1_000);
  for (K key : oldest.keySet()) {
    // Remove everything written more than 1 minute ago
    policy.ageOf(key)
      .filter(duration -> duration.compareTo(maxAge) > 0)
      .ifPresent(duration -> cache.invalidate(key));
  }
});

如果您自己维护时间戳,则可以使用 cache.asMap() 视图进行无序迭代。这可能是最简单和快速的。

long cutoff = ...
var keys = cache.asMap().entrySet().stream()
  .filter(entry -> entry.getValue().timestamp() < cutoff)
  .collect(toList());
cache.invalidateAll(keys);

一种行不通但值得一提的方法是变量过期,expireAfter(expiry)。您可以根据先前的设置为每次阅读设置新的持续时间。这在条目返回给调用者后生效,因此虽然您可以立即过期,但它将服务 K1(至少)一次。

否则,您可以在缓存外的检索时间进行验证并依赖于大小逐出。这种方法的缺陷是它确实会污染缓存中的死条目。

V value = cache.get(key);
if (value.timestamp() < cutoff) {
  cache.asMap().remove(key, value);
  return cache.get(key); // load a new value
}
return value;

或者您可以维护自己的写入顺序队列等。所有这些都会随着您的喜好而变得混乱。对于您的情况,完整迭代可能是最简单且最不容易出错的方法。