diff --git a/application-engine/src/main/java/com/netgrif/application/engine/configuration/CacheConfiguration.java b/application-engine/src/main/java/com/netgrif/application/engine/configuration/CacheConfiguration.java index 1e0ad25c87..7fed1391bb 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/configuration/CacheConfiguration.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/configuration/CacheConfiguration.java @@ -1,15 +1,18 @@ package com.netgrif.application.engine.configuration; +import com.netgrif.application.engine.configuration.cache.WorkerConcurrentCacheManager; import com.netgrif.application.engine.configuration.properties.CacheConfigurationProperties; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; -import org.springframework.cache.concurrent.ConcurrentMapCacheManager; import org.springframework.cache.interceptor.CacheResolver; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; +import java.util.Set; + + @Configuration @EnableCaching public class CacheConfiguration extends CachingConfigurerSupport { @@ -24,7 +27,7 @@ public CacheConfiguration(CacheConfigurationProperties properties) { @Primary @Override public CacheManager cacheManager() { - return new ConcurrentMapCacheManager(properties.getAllCaches().toArray(String[]::new)); + return new WorkerConcurrentCacheManager(Set.of(properties.getNamespaceFunctions()), properties.getAllCaches().toArray(String[]::new)); } @Bean diff --git a/application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/ReadOnlyCache.java b/application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/ReadOnlyCache.java new file mode 100644 index 0000000000..10fae378d6 --- /dev/null +++ b/application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/ReadOnlyCache.java @@ -0,0 +1,42 @@ +package com.netgrif.application.engine.configuration.cache; + +import org.springframework.cache.Cache; + +import java.util.concurrent.Callable; + +public class ReadOnlyCache implements Cache { + + private final Cache cacheDelegate; + + public ReadOnlyCache(Cache cacheDelegate) { + this.cacheDelegate = cacheDelegate; + } + + @Override + public String getName() { return cacheDelegate.getName(); } + + @Override + public Object getNativeCache() { return cacheDelegate.getNativeCache(); } + + @Override + public ValueWrapper get(Object key) { return cacheDelegate.get(key); } + + @Override + public T get(Object key, Class type) { return cacheDelegate.get(key, type); } + + @Override + public T get(Object key, Callable loader) { return cacheDelegate.get(key, loader); } + + @Override + public void put(Object key, Object value) { cacheDelegate.put(key, value); } + + @Override + public void evict(Object key) { + throw new UnsupportedOperationException("Evict not allowed on worker for " + getName()); + } + + @Override + public void clear() { + throw new UnsupportedOperationException("Clear not allowed on worker for " + getName()); + } +} diff --git a/application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/WorkerConcurrentCacheManager.java b/application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/WorkerConcurrentCacheManager.java new file mode 100644 index 0000000000..ffa8cd3c30 --- /dev/null +++ b/application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/WorkerConcurrentCacheManager.java @@ -0,0 +1,39 @@ +package com.netgrif.application.engine.configuration.cache; + +import org.springframework.cache.Cache; +import org.springframework.cache.concurrent.ConcurrentMapCacheManager; + +import java.util.Objects; +import java.util.Set; + +public class WorkerConcurrentCacheManager extends ConcurrentMapCacheManager { + private final Set readOnlyCacheNames; + + public WorkerConcurrentCacheManager() { + super(); + this.readOnlyCacheNames = Set.of(); + } + + public WorkerConcurrentCacheManager(Set readOnlyCacheNames) { + super(); + this.readOnlyCacheNames = Set.copyOf( + Objects.requireNonNull(readOnlyCacheNames, "readOnlyCacheNames must not be null.") + ); + } + + public WorkerConcurrentCacheManager(Set readOnlyCacheNames, String... cacheNames) { + super(cacheNames); + this.readOnlyCacheNames = Set.copyOf( + Objects.requireNonNull(readOnlyCacheNames, "readOnlyCacheNames must not be null.") + ); + } + + @Override + protected Cache createConcurrentMapCache(String name) { + Cache base = super.createConcurrentMapCache(name); + if (readOnlyCacheNames != null && readOnlyCacheNames.contains(name)) { + return new ReadOnlyCache(base); + } + return base; + } +} \ No newline at end of file diff --git a/application-engine/src/main/java/com/netgrif/application/engine/configuration/properties/CacheConfigurationProperties.java b/application-engine/src/main/java/com/netgrif/application/engine/configuration/properties/CacheConfigurationProperties.java index 8050c7ac37..755829b770 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/configuration/properties/CacheConfigurationProperties.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/configuration/properties/CacheConfigurationProperties.java @@ -41,6 +41,11 @@ public class CacheConfigurationProperties { */ private String loadedModules = "loadedModules"; + /** + * Default cache name for caching namespace functions. + */ + private String namespaceFunctions = "namespaceFunctions"; + /** * A list of additional custom cache names. * Allows users to define their own cache names for specific use cases. @@ -54,7 +59,7 @@ public class CacheConfigurationProperties { * @return a {@link Set} of all cache names. */ public Set getAllCaches() { - Set caches = new LinkedHashSet<>(Arrays.asList(petriNetById, petriNetByIdentifier, petriNetNewest, petriNetCache, loadedModules)); + Set caches = new LinkedHashSet<>(Arrays.asList(petriNetById, petriNetByIdentifier, petriNetNewest, petriNetCache, loadedModules, namespaceFunctions)); caches.addAll(additional); return caches; } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FieldActionsCacheService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FieldActionsCacheService.java index 1b996bc60d..51432b96c8 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FieldActionsCacheService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FieldActionsCacheService.java @@ -15,6 +15,9 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import java.util.ArrayList; @@ -30,7 +33,6 @@ public class FieldActionsCacheService implements IFieldActionsCacheService { private final RunnerConfigurationProperties.FieldRunnerProperties properties; private IPetriNetService petriNetService; - private Map actionsCache; private Map> namespaceFunctionsCache; private Map functionsCache; @@ -96,6 +98,28 @@ public List getCachedFunctions(List page = petriNetService.getAll(pageable); + + while (!page.isEmpty()) { + for (PetriNet petriNet : page) { + try { + cachePetriNetFunctions(petriNet); + } catch (Exception e) { + log.warn("Failed to cache functions for PetriNet id={}", petriNet.getStringId(), e); + } + } + + if (!page.hasNext()) { + break; + } + pageable = pageable.next(); + page = petriNetService.getAll(pageable); + } + } + @Override public void evaluateFunctions(List functions) { evaluateCachedFunctions(functions.stream().map(function -> CachedFunction.build(shell, function)).collect(Collectors.toList())); diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IFieldActionsCacheService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IFieldActionsCacheService.java index 6eb2580949..10eb67bc21 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IFieldActionsCacheService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IFieldActionsCacheService.java @@ -27,5 +27,7 @@ public interface IFieldActionsCacheService { void clearNamespaceFunctionCache(); + void cacheAllPetriNetsFunctions(); + void clearFunctionCache(); }