27 Ağustos 2020 Perşembe

Beta Anotasyonu

Giriş
@Beta anotasyonuna sahip kod kalitesi kod anlamına gelmez. Açıklaması şöyle
That said, @Beta APIs are fully tested and supported, and treated with all the care and affection that the rest of Guava receives.
Sadece arayüzleri sabitlenmemiş, değişime açık kod anlamına gelir.

7 Ağustos 2020 Cuma

Cache Arayüzü

Giriş
Açıklaması şöyle.
Guava is missing a feature that other caches provide, which is a variable expiry based on the cached value.
1. Population - Cache'i Doldurma
Yöntemler şöyle.
1. cache.get(...) metodunu kullanarak bir Callable kullanmak
2. cache.put(...) veya cache.putAll() metodları ile değeri direkt vermek
Cache aynı zamanda asMap() metodu ile bir ConcurrentMap döndürüyor. asMap() metodunu kullanarak doldurmak doğru değil. Açıklaması şöyle.
Values may be inserted into the cache directly with cache.put(key, value). This overwrites any previous entry in the cache for the specified key. Changes can also be made to a cache using any of the ConcurrentMap methods exposed by the Cache.asMap() view. Note that no method on the asMap view will ever cause entries to be automatically loaded into the cache. Further, the atomic operations on that view operate outside the scope of automatic cache loading, so Cache.get(K, Callable) should always be preferred over Cache.asMap().putIfAbsent in caches which load values using either CacheLoader or Callable.
3. CacheBuilder + CacheLoader kullanarak LoadingCache elde etmek. Eğer LoadingCache Kullanıyorsak Bulk Load veya Single Load yapabiliriz.

3.1. Bulk Load için LoadingCache.getAll(Iterable<? extends K>) metodu çağrılır. Bu çağrı CacheLoader.loadAll() metodunu tetikler. Açıklaması şöyle.
Bulk lookups can be performed with the method getAll(Iterable<? extends K>). By default, getAll will issue a a separate call to CacheLoader.load for each key which is absent from the cache. When bulk retrieval is more efficient than many individual lookups, you can override CacheLoader.loadAll to exploit this. The performance of getAll(Iterable) will improve accordingly.
3.2. LoadingCache.get() metodu çağrılır. Bu çağrı CacheLoader.get() metodunu tetikler. Açıklaması şöyle.
The canonical way to query a LoadingCache is with the method get(K). This will either return an already cached value, or else use the cache's CacheLoader to atomically load a new value into the cache.
2. Eviction - Cache'ten Silme
Yöntemler şöyle.
1. Size-based yöntem. CacheBuilder.maximumSize(), CacheBuilder.weigher() gibi bir yöntem kullanmak
2. Time based yöntem. CacheBuilder.expireAfterAccess(), CacheBuilder.expireAfterWrite() gibi bir yöntem kullanmak
3. Reference-based Eviction. CacheBuilder.weakKeys(), CacheBuilder.weakValues() , CacheBuilder.softValues()  gibi bir yöntem kullanmak
4. Cache.invalidate(key),Cache.invalidateAll(keys),Cache.invalidateAll() metodlarını kullanmak

3. Cleanup
 cleanUp() metoduna bakabilirsiniz.

4. Removal Listener
 CacheBuilder.removalListener(RemovalListener) ile bir listener takılabilir. RemovalListener yazısına bakabilirsiniz.

5. Refresh
Yöntemler şöyle.
1.  LoadingCache.refresh(K) ile belirli bir key yenilenebilir. Bu çağrı CacheLoader.reload() metodunu tetikler. CacheLoader.reload(K, V) ile eski value değer ile tetiklenir.

6. Metodlar
asMap metodu
java.util.ConcurrentMap döndürür. Açıklaması şöyle.
Returns a view of the entries stored in this cache as a thread-safe map. Modifications made to the map directly affect the cache.
Örnek
Şöyle yaparız.
cache.asMap().compute(key, ...);
Örnek
Şöyle yaparız.
private static final ConcurrentMap<String, Buffered> IMAGE_MAP =
    CacheBuilder.newBuilder()
        .softValues()
        .<String, Buffered>build()
        .asMap();
Örnek
Şöyle yaparız.
String someValueFromCache = myCache.asMap().get("someString");
cleanUp metodu
Açıklaması şöyle. Cache evict işlemini yapmak için bu metod çağrılır.
Caches built with CacheBuilder do not perform cleanup and evict values "automatically," or instantly after a value expires, or anything of the sort. Instead, it performs small amounts of maintenance during write operations, or during occasional read operations if writes are rare.
The reason for this is as follows: if we wanted to perform Cache maintenance continuously, we would need to create a thread, and its operations would be competing with user operations for shared locks. Additionally, some environments restrict the creation of threads, which would make CacheBuilder unusable in that environment.
Instead, we put the choice in your hands. If your cache is high-throughput, then you don't have to worry about performing cache maintenance to clean up expired entries and the like. If your cache does writes only rarely and you don't want cleanup to block cache reads, you may wish to create your own maintenance thread that calls Cache.cleanUp() at regular intervals.
If you want to schedule regular cache maintenance for a cache which only rarely has writes, just schedule the maintenance using ScheduledExecutorService.
get metodu - Key
Açıklaması şöyle.
There's no way to prevent caching an object if you obtain it via Cache.get.
Örnek
Şöyle yaparız.
cache.get(key, new Callable() {...});
Örnek
Şöyle yaparız.
LoadingCache<String, List<Profile>> loadingCache = ...;

public List<Profile> getProfileByFields(String id, String name) throws Exception {
  String key = id.toLowerCase() + "|" + name.toLowerCase()
  return loadingCache.get(key);
}
getIfPresent metodu - Key
null dönebilir.
Örnek
Şöyle yaparız.
MyObject o = cache.getIfPresent(key);
if (o == null) {
    o = getExternal(key);
    if (o.isActive()) {
        cache.put(key, o);
    }
}
Örnek
Elimizde şöyle bir kod olsun.
Cache<String, Integer> forgetPasswordCache = CacheBuilder.newBuilder()
  .expireAfterAccess(24, TimeUnit.HOURS)
  .build();
Eğer değer üst sınırı aşarsa konrolü yapmak için şöyle yaparız.
final String email = ...;
Integer currentCount = forgetPasswordCache.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) {
  forgetPasswordCache.put(email, new Integer(1));
} else {
  forgetPassworCache.put(email, new Integer(currentCount + 1));
}
invalidate metodu
Belirtilen key değerine sahip cache nesnesini siler. Şöyle yaparız.
MyObject o = cache.get(key, () -> getExternal(key));
if (!o.isActive()) {
    cache.invalidate(key);
}
invalidateAll metodu
Tüm cache'i siler. Şöyle yaparız.
cache.invalidateAll();
maximumSize metodu - Size Based Cache Temizleme
Açıklaması şöyle.
If your cache should not grow beyond a certain size, just use CacheBuilder.maximumSize(long). The cache will try to evict entries that haven't been used recently or very often. Warning: the cache may evict entries before this limit is exceeded -- typically when the cache size is approaching the limit.
put metodu
Örnek
Şöyle yaparız
Cache<String, RateLimiter> cache = ...

public boolean tryAcquire(String key, double secondsBeforeNextOperation) {
  RateLimiter rateLimiter = cache.getIfPresent(key);
  if (rateLimiter == null) {
    rateLimiter = getNewRateLimiter(secondsBeforeNextOperation);
    cache.put(key, rateLimiter); 
  }
  return rateLimiter.tryAcquire();
}
Örnek
Şöyle yaparız.
myCache.put("someString", "someString");
String someValueFromCache = myCache.get("someString");
putAll metodu
İmzası şöyle
void putAll(Map<? extends K, ? extends V> map);
size metodu
İmzası şöyle.
long size()
Açıklaması şöyle.
Returns the approximate number of entries in this cache.