gcube-cms-suite/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/providers/ucd/UCDManager.java

214 lines
8.2 KiB
Java
Raw Normal View History

2022-03-23 18:38:07 +01:00
package org.gcube.application.geoportal.service.engine.providers.ucd;
2022-03-04 18:28:45 +01:00
2022-10-18 15:09:28 +02:00
import com.mongodb.MongoServerException;
2022-03-04 18:28:45 +01:00
import lombok.extern.slf4j.Slf4j;
import org.gcube.application.cms.caches.AbstractScopedMap;
2022-04-27 19:36:10 +02:00
import org.gcube.application.cms.caches.Engine;
import org.gcube.application.cms.caches.ObjectManager;
2022-03-04 18:28:45 +01:00
import org.gcube.application.cms.implementations.ImplementationProvider;
2023-01-10 15:57:40 +01:00
import org.gcube.application.cms.implementations.utils.UserUtils;
2022-05-12 10:56:53 +02:00
import org.gcube.application.cms.serialization.Serialization;
2022-03-04 18:28:45 +01:00
import org.gcube.application.geoportal.common.model.rest.ConfigurationException;
import org.gcube.application.geoportal.common.model.rest.QueryRequest;
import org.gcube.application.geoportal.common.model.useCaseDescriptor.UseCaseDescriptor;
import org.gcube.application.geoportal.common.utils.ContextUtils;
import org.gcube.application.geoportal.service.engine.mongo.UCDManagerI;
import org.gcube.application.geoportal.service.engine.mongo.UCDMongoManager;
2022-10-27 16:03:38 +02:00
import org.gcube.application.cms.implementations.faults.RegistrationException;
2022-03-04 18:28:45 +01:00
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
2022-05-06 18:03:48 +02:00
import java.time.Duration;
import java.time.temporal.ChronoUnit;
2022-05-11 18:45:56 +02:00
import java.util.HashMap;
2022-03-04 18:28:45 +01:00
import java.util.Map;
2022-05-27 13:59:32 +02:00
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
2022-03-04 18:28:45 +01:00
2022-04-27 19:36:10 +02:00
import static java.lang.Thread.sleep;
2022-05-06 18:03:48 +02:00
/**
* Provider of UCDManagerI (this)
*
* - nb on get should check / trigger cache refresh TTL
* - uses UCDMongoManager for storing
* - profile live map engine is discovered
*
*
*
*/
2022-03-04 18:28:45 +01:00
@Slf4j
public class UCDManager extends AbstractScopedMap<UCDManagerI> implements UCDManagerI {
2022-05-11 18:45:56 +02:00
private Map<String,UseCaseDescriptor> memCache = new HashMap<>();
private final ReadWriteLock cacheLock = new ReentrantReadWriteLock();
2022-03-04 18:28:45 +01:00
public UCDManager() {
super("UCD MANAGER");
2022-05-12 10:56:53 +02:00
setTTL(Duration.of(2, ChronoUnit.MINUTES));
2022-03-04 18:28:45 +01:00
}
@Override
public Iterable<UseCaseDescriptor> query(QueryRequest queryRequest) throws ConfigurationException {
2022-05-11 18:45:56 +02:00
cacheLock.readLock().lock();
try{
return getMongoManager().query(queryRequest);
}finally {
cacheLock.readLock().unlock();
}
2022-03-04 18:28:45 +01:00
}
@Override
public void deleteById(String id, boolean force) throws RegistrationException, ConfigurationException {
// NB Check for existing ID
2022-05-11 18:45:56 +02:00
UseCaseDescriptor found = getByUCID(id,true);
cacheLock.writeLock().lock();
try{
if(found!=null) {
// TODO validate DELETE REQUEST
// TODO DELETE UCD
// forceUpdateCache();
throw new WebApplicationException("TO IMPLEMENT ", Response.Status.INTERNAL_SERVER_ERROR);
} else
throw new WebApplicationException("No Matching UCD with ID "+id, Response.Status.NOT_FOUND);
}finally{
cacheLock.writeLock().unlock();
}
2022-03-04 18:28:45 +01:00
}
@Override
public UseCaseDescriptor put(UseCaseDescriptor desc) throws ConfigurationException, RegistrationException {
2022-05-11 18:45:56 +02:00
log.info("Update UCD {} ",desc.getId());
log.debug("Mongo id is {} ",desc.getMongoId());
2022-03-04 18:28:45 +01:00
// NB Check for existing ID
2022-05-11 18:45:56 +02:00
UseCaseDescriptor found = getByUCID(desc.getId(),true);
if(found!=null) {
// TODO validate UPDATE
// TODO STORE UCD
// forceUpdateCache();
throw new WebApplicationException("Update Feature is yet TO IMPLEMENT ", Response.Status.INTERNAL_SERVER_ERROR);
} else {
// create new
registerNew(desc);
2022-04-27 19:36:10 +02:00
forceUpdateCache();
2022-05-11 18:45:56 +02:00
int attempt=0;
do{
found =getByUCID(desc.getId(),true);
log.info("Waiting for backend to update.. ");
try{sleep(4000);}catch (Throwable t){}
attempt++;
} while(found == null && attempt<=4);
return found;
}
}
2022-04-27 19:36:10 +02:00
2022-05-11 18:45:56 +02:00
@Override
protected UCDManagerI retrieveObject(String context) throws ConfigurationException {
// Called when TTL ends
forceUpdateCache();
return this;
2022-03-04 18:28:45 +01:00
}
@Override
public UseCaseDescriptor getById(String id) throws ConfigurationException, RegistrationException {
// GET from mongo cache
2022-05-11 18:45:56 +02:00
// UCDMongoManager mongo=getMongoManager();
// UseCaseDescriptor toReturn=mongo.getById(id);
// log.debug("UCD ID : {} from mongo is {} ",id,toReturn);
// if(toReturn == null) {
// // IF void try from ProfileEngine
// toReturn =getLiveMap().get(id);
// if(toReturn != null ){
// log.debug("Force update of live map {} from live map ",id);
// toReturn = mongo.put(toReturn);
// }
// }
// return toReturn;
return getByUCID(id,true);
}
private UseCaseDescriptor getByUCID(String ucid,boolean refreshOnMissing) throws ConfigurationException {
// Wait / check for cache loaded
log.debug("Trying to getById from memcache {} [refresh on missing : {}]",ucid,refreshOnMissing);
cacheLock.readLock().lock();
boolean releaseLock = true;
UseCaseDescriptor toReturn =null;
try{
if(memCache.containsKey(ucid)) toReturn = memCache.get(ucid);
else {
if(refreshOnMissing){
cacheLock.readLock().unlock();
releaseLock=false;
forceUpdateCache();
// pass false in order to trigger cache update only on first NOT FOUND event
toReturn = getByUCID(ucid,false);
}
2022-03-04 18:28:45 +01:00
}
2022-05-11 18:45:56 +02:00
}finally {
if(releaseLock) cacheLock.readLock().unlock();
2022-03-04 18:28:45 +01:00
}
return toReturn;
}
2022-05-11 18:45:56 +02:00
2022-03-04 18:28:45 +01:00
2022-04-27 19:36:10 +02:00
private void registerNew(UseCaseDescriptor ucd) throws ConfigurationException {
2022-05-11 18:45:56 +02:00
cacheLock.writeLock().lock();
try{
Engine<ProfileMap> engine=ImplementationProvider.get().getEngineByManagedClass(ProfileMap.class);
2022-04-27 19:36:10 +02:00
if(engine instanceof ObjectManager){
((ObjectManager<UseCaseDescriptor>)engine).insert(ucd);
} else throw new ConfigurationException("Profile Map Engine is not Object Manager. Actual implementation is "+engine.getClass());
2022-05-11 18:45:56 +02:00
}finally {
cacheLock.writeLock().unlock();
}
2022-04-27 19:36:10 +02:00
}
2022-03-04 18:28:45 +01:00
private UCDMongoManager getMongoManager() throws ConfigurationException {
return new UCDMongoManager();
}
private void forceUpdateCache() throws ConfigurationException {
2022-03-30 18:39:10 +02:00
log.info("UPDATING PROFILE CACHE..");
2022-05-11 18:45:56 +02:00
cacheLock.writeLock().lock();
2022-03-04 18:28:45 +01:00
final UCDMongoManager manager = getMongoManager();
2022-04-01 19:11:11 +02:00
manager.deleteAll();
2022-05-11 18:45:56 +02:00
memCache.clear();
2022-05-12 10:56:53 +02:00
Engine<ProfileMap> liveMapProvider =ImplementationProvider.get().getEngineByManagedClass(ProfileMap.class);
log.trace("LiveMap Provider class is {} ",liveMapProvider.getClass());
ProfileMap liveMap= liveMapProvider.getObject();
2022-03-30 18:39:10 +02:00
log.debug("LiveMap size is {} ",liveMap.size());
for (Map.Entry<String, UseCaseDescriptor> entry : liveMap.entrySet()) {
2022-05-12 10:56:53 +02:00
// Copying object so we don't alter live Map
UseCaseDescriptor useCaseDescriptor = Serialization.convert(entry.getValue(),UseCaseDescriptor.class);
2022-03-04 18:28:45 +01:00
try {
2022-10-18 15:09:28 +02:00
log.debug("Updating cache with {}, mongo id is {}", useCaseDescriptor.getId(),useCaseDescriptor.getMongoId());
2022-05-11 18:45:56 +02:00
if(useCaseDescriptor.getMongoId()!=null){
log.warn("Retrieved UCD {} from Live Map has a Mongo id [{}]. Removing it..",useCaseDescriptor.getId(),useCaseDescriptor.getMongoId());
useCaseDescriptor.setMongoId(null);
}
2022-03-04 18:28:45 +01:00
// insert/update into DB
2022-05-11 18:45:56 +02:00
manager.insert(useCaseDescriptor);
memCache.put(useCaseDescriptor.getId(), useCaseDescriptor);
2022-10-18 15:09:28 +02:00
} catch (RegistrationException | MongoServerException e) {
2022-03-04 18:28:45 +01:00
log.warn("Unable to cache UCD {}",entry.getKey(),e);
}
}
2023-01-10 15:57:40 +01:00
String context = UserUtils.getCurrent().getContext();
log.info("Cached {} UCDs in {} ",memCache.size(),context);
2022-05-11 18:45:56 +02:00
cacheLock.writeLock().unlock();
2022-03-04 18:28:45 +01:00
}
}