aboutsummaryrefslogtreecommitdiffstats
path: root/vid-app-common/src/main/java/org/onap/vid/aai/util/CacheProviderWithLoadingCache.java
diff options
context:
space:
mode:
Diffstat (limited to 'vid-app-common/src/main/java/org/onap/vid/aai/util/CacheProviderWithLoadingCache.java')
-rw-r--r--vid-app-common/src/main/java/org/onap/vid/aai/util/CacheProviderWithLoadingCache.java100
1 files changed, 100 insertions, 0 deletions
diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/util/CacheProviderWithLoadingCache.java b/vid-app-common/src/main/java/org/onap/vid/aai/util/CacheProviderWithLoadingCache.java
new file mode 100644
index 000000000..26a3ebf25
--- /dev/null
+++ b/vid-app-common/src/main/java/org/onap/vid/aai/util/CacheProviderWithLoadingCache.java
@@ -0,0 +1,100 @@
+package org.onap.vid.aai.util;
+
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.util.concurrent.UncheckedExecutionException;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.jetbrains.annotations.NotNull;
+import org.onap.vid.properties.Features;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.togglz.core.manager.FeatureManager;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
+
+import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
+
+@Component
+public class CacheProviderWithLoadingCache implements CacheProvider {
+
+ private final ExecutorService cacheReloadPool;
+ private final FeatureManager featureManager;
+ private final CacheConfigProvider cacheConfigProvider;
+ private final ConcurrentHashMap<String, Cache> caches;
+
+
+ @Autowired
+ public CacheProviderWithLoadingCache(FeatureManager featureManager, CacheConfigProvider cacheConfigProvider) {
+ this.featureManager = featureManager;
+ this.cacheConfigProvider = cacheConfigProvider;
+ this.cacheReloadPool = Executors.newFixedThreadPool(3);
+ this.caches = new ConcurrentHashMap<>();
+ }
+
+ /*
+ Returns the cache associated with given name; creates one if wasn't any
+ */
+ @Override
+ public <K, V> Cache<K, V> aaiClientCacheFor(String name, Function<K, V> loader) {
+ return (Cache<K, V>) caches.computeIfAbsent(name, s -> buildAaiClientCacheFrom(loader, name));
+ }
+
+ @Override
+ public void resetCache(String name) {
+ caches.remove(name);
+ }
+
+ /*
+ Creates and returns a Cache that use provided `loader` to fetch values for
+ search keys, and stores the result for reuse over a certain time.
+ The cache will not use any stored key if FLAG_1810_AAI_LOCAL_CACHE is turned off.
+ In that case, `loader` will be invoked for any `get()` request from the cache. The
+ cache adheres the flag in real-time; so no restart is required.
+ */
+ protected <K, V> Cache<K, V> buildAaiClientCacheFrom(Function<K, V> loader, String name) {
+ final LoadingCache<K, V> activeCache = buildAaiClientActiveCacheFrom(loader, name);
+
+ // this works because Cache interface has only a single method: "get()"
+ // can be replaced with new anonimous class; e.g.:
+ // return new Cache() { ... }
+ return key -> {
+ if (featureManager.isActive(Features.FLAG_1810_AAI_LOCAL_CACHE) &&
+ defaultIfNull(cacheConfigProvider.getCacheConfig(name).isActive(), true)) {
+ try {
+ return activeCache.getUnchecked(key);
+ }
+ catch (UncheckedExecutionException exception) {
+ return ExceptionUtils.rethrow(exception.getCause());
+ }
+ } else {
+ activeCache.invalidateAll();
+ activeCache.cleanUp();
+ return loader.apply(key);
+ }
+ };
+ }
+
+ private <K, V> LoadingCache<K, V> buildAaiClientActiveCacheFrom(Function<K, V> loader, String name) {
+ return createCacheBuilder(name).build(createAsyncReloadingCacheLoaderFrom(loader));
+
+ }
+
+ @NotNull
+ protected CacheBuilder<Object, Object> createCacheBuilder(String name) {
+ CacheConfig cacheConfig = cacheConfigProvider.getCacheConfig(name);
+ return CacheBuilder.newBuilder()
+ .maximumSize(1000)
+ .expireAfterWrite(cacheConfig.getExpireAfterWriteHours(), TimeUnit.HOURS)
+ .refreshAfterWrite(cacheConfig.getRefreshAfterWriteSeconds(), TimeUnit.SECONDS);
+ }
+
+ private <K, V> CacheLoader<K, V> createAsyncReloadingCacheLoaderFrom(Function<K, V> loader) {
+ return CacheLoader.asyncReloading(CacheLoader.from(loader::apply), cacheReloadPool);
+ }
+
+}