cache per le chiamate IS

This commit is contained in:
Alfredo Oliviero 2024-06-03 17:18:38 +02:00
parent 7020180804
commit 7abf8eac7a
7 changed files with 298 additions and 13 deletions

View File

@ -0,0 +1,22 @@
package org.gcube.portlets.user.cloudcomputing;
import java.io.IOException;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import com.liferay.portal.kernel.log.LogFactoryUtil;
public class CC_MethodsListPortlet extends CC_Portlet {
private static com.liferay.portal.kernel.log.Log _log = LogFactoryUtil
.getLog(CC_MethodsListPortlet.class);
public void render(RenderRequest renderRequest, RenderResponse renderResponse)
throws PortletException, IOException {
super.render(renderRequest, renderResponse);
}
}

View File

@ -17,5 +17,4 @@ public class CC_MethodsMonitorPortlet extends CC_Portlet {
throws PortletException, IOException {
super.render(renderRequest, renderResponse);
}
}

View File

@ -13,6 +13,7 @@ import javax.servlet.http.HttpServletRequest;
import org.gcube.common.portal.PortalContext;
import org.gcube.portlets.user.cloudcomputing.config.CC_Config;
import org.gcube.portlets.user.cloudcomputing.is.IsClient;
import org.gcube.portlets.user.cloudcomputing.is.IsClientFactory;
import org.gcube.portlets.user.cloudcomputing.is.IsServerConfig;
import com.liferay.portal.kernel.log.LogFactoryUtil;
@ -22,7 +23,7 @@ import com.liferay.util.bridges.mvc.MVCPortlet;
public class CC_Portlet extends MVCPortlet {
private static com.liferay.portal.kernel.log.Log _log = LogFactoryUtil.getLog(CC_Portlet.class);
private static CC_Config configuration = null;
private CC_Config configuration = null;
public final static String IS_AUTH_RESOURCE_NAME = "IAM";
public final static String IS_AUTH_CATEGORY = "Service";
@ -59,15 +60,17 @@ public class CC_Portlet extends MVCPortlet {
String host = base_url.getHost();
config.gateway = host;
IsServerConfig auth_config = IsClient.serviceConfigFromIS(IS_AUTH_RESOURCE_NAME,
IsClient isclient = IsClientFactory.getSingleton();
IsServerConfig auth_config = isclient.serviceConfigFromIS(IS_AUTH_RESOURCE_NAME,
IS_AUTH_CATEGORY, IS_AUTH_ENTRYPOINT);
config.auth_url = auth_config.getServerUrl();
IsServerConfig ccp_config = IsClient.serviceConfigFromIS(IS_CCP_RESOURCE_NAME,
IsServerConfig ccp_config = isclient.serviceConfigFromIS(IS_CCP_RESOURCE_NAME,
IS_CCP_CATEGORY, IS_CCP_ENTRYPOINT);
config.ccp_url = ccp_config.getServerUrl();
IsServerConfig cdn_config = IsClient.serviceConfigFromIS(IS_CCP_RESOURCE_NAME,
IsServerConfig cdn_config = isclient.serviceConfigFromIS(IS_CCP_RESOURCE_NAME,
IS_CCP_CATEGORY, IS_CDN_ENTRYPOINT);
config.cdn_url = cdn_config.getServerUrl();

View File

@ -0,0 +1,103 @@
package org.gcube.portlets.user.cloudcomputing.is;
import java.io.Serializable;
import java.rmi.ServerException;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.gcube.common.resources.gcore.ServiceEndpoint;
import com.liferay.portal.kernel.cache.MultiVMPoolUtil;
import com.liferay.portal.kernel.cache.PortalCache;
import com.liferay.portal.kernel.log.LogFactoryUtil;
/**
* Utility class to query EndPoints and search for AccessPoints from IS
*
* @author Alfredo Oliviero (ISTI - CNR)
*/
public class CacheIsClient extends IsClient {
private static com.liferay.portal.kernel.log.Log logger = LogFactoryUtil.getLog(CacheIsClient.class);
private static CacheIsClient _singleInstance;
// Class to represent a cache entry
static CacheIsClient getSingleton() {
if (_singleInstance == null) {
_singleInstance = new CacheIsClient();
}
return _singleInstance;
}
private static class CacheEntry implements Serializable {
List<ServiceEndpoint> endpoints;
long timestamp;
CacheEntry(List<ServiceEndpoint> endpoints, long timestamp) {
this.endpoints = endpoints;
this.timestamp = timestamp;
}
}
// Define the cache name
private static final String CACHE_NAME = "my-cache";
private PortalCache<Serializable, Serializable> portalCache = MultiVMPoolUtil.getCache(CACHE_NAME);
// Method to get the cache key
private String getCacheKey(String resourceName, String category) {
return resourceName + ":" + category;
}
// Main method with caching and locking
public synchronized List<ServiceEndpoint> getEndpointsFromISWithCache(String resource_name, String category) throws ServerException {
String key = getCacheKey(resource_name, category);
long currentTime = System.currentTimeMillis();
logger.info("Request received for resource: " + resource_name + ", category: " + category);
synchronized (key.intern()) {
logger.info("Acquired lock for key: " + key);
// Check if the entry is present in the cache and is valid
CacheEntry cacheEntry = (CacheEntry)portalCache.get(key);
if (cacheEntry != null) {
if (currentTime - cacheEntry.timestamp <= TimeUnit.MINUTES.toMillis(10)) {
// If the cache value is still valid, return it
logger.info("Cache hit for key: " + key);
return cacheEntry.endpoints;
} else {
// Otherwise, remove the expired entry
logger.info("Cache expired for key: " + key);
portalCache.remove(key);
}
}
// If not present in the cache or is expired, make the request
logger.info("Cache miss for key: " + key + ". Making request to external service.");
List<ServiceEndpoint> endpoints;
try {
endpoints = super.getEndpointsFromIS(resource_name, category);
} catch (ServerException e) {
logger.error("Error fetching data from external service for key: " + key, e);
throw e;
}
// Update the cache with the new result and timestamp
logger.info("Updating cache for key: " + key);
portalCache.put(key, new CacheEntry(endpoints, currentTime));
return endpoints;
}
}
// Metodo principale con caching e locking
public List<ServiceEndpoint> getEndpointsFromIS(String resource_name, String category) throws ServerException {
logger.info("@@@ cached getEndpointsFromIS: " + resource_name + ":" + category);
return getEndpointsFromISWithCache(resource_name, category);
}
}

View File

@ -0,0 +1,114 @@
package org.gcube.portlets.user.cloudcomputing.is;
import java.rmi.ServerException;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.gcube.common.resources.gcore.ServiceEndpoint;
import com.liferay.portal.kernel.log.LogFactoryUtil;
/**
* Utility class to query EndPoints and search for AccessPoints from IS
*
* @author Alfredo Oliviero (ISTI - CNR)
*/
public class CacheIsClient extends IsClient {
private static com.liferay.portal.kernel.log.Log logger = LogFactoryUtil.getLog(CacheIsClient.class);
private static CacheIsClient _singleInstance = null;
public int CACHE_DURATION_SECONDS = 1 * 10;
static CacheIsClient getSingleton() {
if (_singleInstance == null) {
_singleInstance = new CacheIsClient();
}
return _singleInstance;
}
private static class CacheEntry {
List<ServiceEndpoint> endpoints;
long timestamp;
CacheEntry(List<ServiceEndpoint> endpoints, long timestamp) {
this.endpoints = endpoints;
this.timestamp = timestamp;
}
}
// Mappa per mantenere la cache
private ConcurrentHashMap<String, CacheEntry> cache = new ConcurrentHashMap<>();
// Mappa per mantenere i lock
private ConcurrentHashMap<String, Lock> locks = new ConcurrentHashMap<>();
// Metodo per ottenere la chiave della cache
private String getCacheKey(String resourceName, String category) {
return resourceName + ":" + category;
}
// Metodo principale con caching e locking
public List<ServiceEndpoint> getEndpointsFromIS(String resource_name, String category) throws ServerException {
return getEndpointsFromISWithCache(resource_name, category);
}
// Main method with caching and locking
public List<ServiceEndpoint> getEndpointsFromISWithCache(String resource_name, String category) throws ServerException {
String key = getCacheKey(resource_name, category);
long currentTime = System.currentTimeMillis();
logger.info("Request received for resource: " + resource_name + ", category: " + category);
// Get or create a lock for the specific key
Lock lock = locks.computeIfAbsent(key, k -> new ReentrantLock());
logger.info("Lock object created/retrieved for key: " + key);
// Acquire the lock
logger.info("### Acquiring lock for key: " + key);
lock.lock();
try {
logger.info("### Lock acquired for key: " + key);
// Check if the entry is present in the cache and is valid
if (cache.containsKey(key)) {
CacheEntry cacheEntry = cache.get(key);
if (currentTime - cacheEntry.timestamp <= TimeUnit.MINUTES.toMillis(10)) {
// If the cache value is still valid, return it
logger.info(">>> Cache hit for key: " + key);
return cacheEntry.endpoints;
} else {
// Otherwise, remove the expired entry
logger.info(">>> Cache expired for key: " + key);
cache.remove(key);
}
}
// If not present in the cache or is expired, make the request
logger.info(">>> Cache miss for key: " + key + ". Making request to external service.");
List<ServiceEndpoint> endpoints;
try {
endpoints = getEndpointsFromIS(resource_name, category);
} catch (ServerException e) {
logger.error( "Error fetching data from external service for key: " + key, e);
throw e;
}
// Update the cache with the new result and timestamp
logger.info("Updating cache for key: " + key);
cache.put(key, new CacheEntry(endpoints, currentTime));
return endpoints;
} finally {
// Release the lock
logger.info("### Releasing lock for key: " + key);
lock.unlock();
// Remove the lock from the map to avoid memory leaks
logger.info("### Removing lock from map for key: " + key);
locks.remove(key);
}
}
}

View File

@ -29,6 +29,15 @@ import com.liferay.portal.kernel.log.LogFactoryUtil;
public class IsClient {
private static com.liferay.portal.kernel.log.Log logger = LogFactoryUtil.getLog(IsClient.class);
private static IsClient _singleInstance = null;
static IsClient getSingleton() {
if (_singleInstance == null) {
_singleInstance = new IsClient();
}
return _singleInstance;
}
/**
* obatins from IS the list of ServiceEndpoint matching the parameters
*
@ -42,10 +51,10 @@ public class IsClient {
* @throws Exception
*/
public static ServiceEndpoint getFirstEndopintsFromIS(String resource_name, String category)
public ServiceEndpoint getFirstEndopintsFromIS(String resource_name, String category)
throws ServerException {
List<ServiceEndpoint> endpoints = getEndopintsFromIS(resource_name, category);
List<ServiceEndpoint> endpoints = getEndpointsFromIS(resource_name, category);
if (endpoints == null || endpoints.size() == 0) {
logger.error("Unable to retrieve service endpoint " + resource_name);
return null;
@ -55,8 +64,10 @@ public class IsClient {
}
public static List<ServiceEndpoint> getEndopintsFromIS(String resource_name, String category
/* , boolean root_service, Secret secret */) throws ServerException {
public List<ServiceEndpoint> getEndpointsFromIS(String resource_name, String category
) throws ServerException {
logger.info("@@@ not cached getEndpointsFromIS: " + resource_name + ":" + category);
SimpleQuery query = queryFor(ServiceEndpoint.class);
if (resource_name != null) {
@ -74,6 +85,7 @@ public class IsClient {
ScopeProvider.instance.set(infrastructure);
try {
logger.info (" IS CLIENT Requiring " + resource_name + ":"+ category);
// if (root_service) {
// endpoints = AuthorizedTasks.executeSafely(() -> {
@ -107,10 +119,10 @@ public class IsClient {
* @throws ServerException
* @throws Exception
*/
public static List<ServiceEndpoint.AccessPoint> getAccessPointsFromIS(String resource_name, String category,
public List<ServiceEndpoint.AccessPoint> getAccessPointsFromIS(String resource_name, String category,
String endPointName/* , boolean is_root_service, Secret secret */) throws ServerException {
List<ServiceEndpoint> resources = getEndopintsFromIS(resource_name, category/* , is_root_service, secret */);
List<ServiceEndpoint> resources = getEndpointsFromIS(resource_name, category/* , is_root_service, secret */);
if (resources.size() == 0) {
logger.error("There is no Runtime Resource having name " + resource_name + " and Category "
@ -142,7 +154,7 @@ public class IsClient {
* @throws ServerException
* @throws Exception
*/
public static ServiceEndpoint.AccessPoint getFirstAccessPointFromIS(String resource_name, String category,
public ServiceEndpoint.AccessPoint getFirstAccessPointFromIS(String resource_name, String category,
String entryPointName/* , boolean root_service, Secret secret */) throws ServerException {
List<ServiceEndpoint.AccessPoint> access_points = getAccessPointsFromIS(resource_name, category,
@ -175,7 +187,7 @@ public class IsClient {
* @return
* @throws Exception
*/
public static IsServerConfig serviceConfigFromIS(String resourceName, String category, String endPointName
public IsServerConfig serviceConfigFromIS(String resourceName, String category, String endPointName
/* , boolean is_root_service, Secret secret */)
throws ServerException {

View File

@ -0,0 +1,32 @@
package org.gcube.portlets.user.cloudcomputing.is;
import com.liferay.portal.kernel.log.LogFactoryUtil;
// import org.gcube.common.security.AuthorizedTasks;
// import org.gcube.common.security.secrets.Secret;
/**
* Utility class to query EndPoints and search for AccessPoints from IS
*
* @author Alfredo Oliviero (ISTI - CNR)
*/
public class IsClientFactory {
private static com.liferay.portal.kernel.log.Log logger = LogFactoryUtil.getLog(IsClientFactory.class);
static boolean cache_enabled = true;
public static IsClient getSingleton(){
return getSingleton(cache_enabled);
}
public static IsClient getSingleton(boolean use_cache){
if (use_cache) {
logger.info("@@@ IsClientFactory cache enabled");
return CacheIsClient.getSingleton();
} else {
logger.info("@@@ IsClientFactory cache not enabled");
return IsClient.getSingleton();
}
}
}