-
Notifications
You must be signed in to change notification settings - Fork 6
[NAE-2182] Clearing actions cache #348
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: release/7.0.0-rev9
Are you sure you want to change the base?
Changes from all commits
dd58002
5b98ca4
e917f76
bd719b5
e976081
8323adb
f9796d6
a002636
e6e8dac
d2227d0
6e09ba1
790659b
dd80913
7dc7947
eb56f99
93921f9
cf3dc8c
cb1505f
fc76808
b5bd5b5
9059bec
dfd7afd
e8441cb
0c1c914
53fb4e6
1cdfbc4
47ba662
7e0c9b8
4670f33
cf0651a
48e1411
b30c884
d7705b2
2654b7d
d457145
61f9b2e
289de0f
e9ef494
2274d62
39da22c
d82fc67
6f57b74
174c7ee
faa99d7
44c6ed7
fc637ee
6d84f5b
c18561f
f7b61be
c039509
df89aac
3241eed
b92ba07
eb377cc
4ca7fd4
8028b98
1d7d175
9cdd0b9
d614cf9
e82c400
f7c8583
5d72517
a1e93de
5ce552c
59299c5
f2cf540
75b903d
749db25
94724c5
0f7bb9b
ebaa5a9
d573cf2
4c1cf75
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package com.netgrif.application.engine.configuration; | ||
|
|
||
| public final class CacheMapKeys { | ||
| private CacheMapKeys() {} | ||
| public static final String ACTIONS = "actions"; | ||
| public static final String FUNCTIONS = "functions"; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| package com.netgrif.application.engine.configuration; | ||
|
|
||
| import lombok.extern.slf4j.Slf4j; | ||
| import org.jetbrains.annotations.NotNull; | ||
| import org.springframework.cache.Cache; | ||
| import org.springframework.cache.support.SimpleValueWrapper; | ||
|
|
||
| import java.util.Map; | ||
| import java.util.concurrent.Callable; | ||
| import java.util.concurrent.ConcurrentHashMap; | ||
|
|
||
| @Slf4j | ||
| public class GenericMapCache<V> implements Cache { | ||
| private final String name; | ||
| private final Class<V> valueType; | ||
| private final ConcurrentHashMap<String, V> map; | ||
|
|
||
| public GenericMapCache(String name, Class<V> valueType, int cacheSize) { | ||
| this.name = name; | ||
| this.valueType = valueType; | ||
| this.map = new ConcurrentHashMap<>(cacheSize); | ||
| } | ||
|
Comment on lines
+18
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cache is unbounded despite The Consider using a bounded cache implementation like Caffeine or implementing LRU eviction: Option 1: Use Caffeine for bounded cachingimport com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
// In constructor:
this.map = Caffeine.newBuilder()
.maximumSize(cacheSize)
.build();Option 2: Use LinkedHashMap with access-order evictionprivate final Map<String, V> map;
public GenericMapCache(String name, Class<V> valueType, int cacheSize) {
this.name = name;
this.valueType = valueType;
this.map = Collections.synchronizedMap(new LinkedHashMap<>(cacheSize, 0.75f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry<String, V> eldest) {
return size() > cacheSize;
}
});
}🤖 Prompt for AI Agents |
||
|
|
||
| @Override public @NotNull String getName() { return name; } | ||
|
|
||
| @Override public @NotNull Object getNativeCache() { return Map.copyOf(map); } | ||
|
|
||
| @Override | ||
| public <T> T get(Object key, Callable<T> loader) { | ||
| final String stringKey = String.valueOf(key); | ||
| try { | ||
| V value = map.computeIfAbsent(stringKey, cacheValue -> { | ||
| try { | ||
| T computed = loader.call(); | ||
| if (computed == null) return null; | ||
| return safeCast(computed); | ||
| } | ||
| catch (Exception e) { | ||
| throw new RuntimeException(e); | ||
| } | ||
| }); | ||
| return (T) value; | ||
| } catch (RuntimeException e) { | ||
| Throwable cause = (e.getCause() != null) ? e.getCause() : e; | ||
| throw new Cache.ValueRetrievalException(stringKey, loader, cause); | ||
| } | ||
| } | ||
|
Comment on lines
+29
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Null values are not cached, causing repeated loader invocations. When If caching null results is intentional behavior, document it. Otherwise, consider using a sentinel value or Additionally, line 42 has an unchecked cast from |
||
|
|
||
| @Override | ||
| public ValueWrapper get(Object key) { | ||
| String stringKey = String.valueOf(key); | ||
| Object valueObject = map.get(stringKey); | ||
| return valueObject != null ? new SimpleValueWrapper(valueObject) : null; | ||
| } | ||
|
|
||
| @Override | ||
| public <T> T get(Object key, Class<T> type) { | ||
| String stringKey = String.valueOf(key); | ||
| Object valueObject = map.get(stringKey); | ||
| return valueObject != null ? type.cast(valueObject) : null; | ||
| } | ||
|
|
||
| @Override | ||
| public void put(Object key, Object value) { | ||
| map.put(String.valueOf(key), safeCast(value)); | ||
| } | ||
|
|
||
| @Override | ||
| public void evict(Object key) { | ||
| map.remove(String.valueOf(key)); | ||
| } | ||
|
|
||
| @Override | ||
| public void clear() { | ||
| map.clear(); | ||
| } | ||
|
|
||
| @SuppressWarnings("unchecked") | ||
| private V safeCast(Object object) { | ||
| if (object == null) { | ||
| return null; | ||
| } | ||
|
|
||
| if (!valueType.isInstance(object)) { | ||
| throw new ClassCastException("Expected " + valueType.getName() + " but was " + object.getClass().getName()); | ||
| } | ||
|
|
||
| return (V) object; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,9 +27,14 @@ public class CacheConfigurationProperties { | |
| private String petriNetByIdentifier = "petriNetByIdentifier"; | ||
|
|
||
| /** | ||
| * Default cache name for caching the newest versions of Petri nets. | ||
| * Default cache name for caching the default versions of Petri nets. | ||
| */ | ||
| private String petriNetNewest = "petriNetNewest"; | ||
| private String petriNetDefault = "petriNetDefault"; | ||
|
|
||
| /** | ||
| * Default cache name for caching the latest versions of Petri nets. | ||
| */ | ||
| private String petriNetLatest = "petriNetLatest"; | ||
|
|
||
| /** | ||
| * Default cache name for general Petri net caching. | ||
|
|
@@ -41,20 +46,33 @@ public class CacheConfigurationProperties { | |
| */ | ||
| private String loadedModules = "loadedModules"; | ||
|
|
||
| /** | ||
| * Default cache name for caching global functions of PetriNet global scoped functions. | ||
| */ | ||
| private String globalFunctions = "globalFunctions"; | ||
|
Comment on lines
+49
to
+52
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Clarify the documentation wording. The phrase "caching global functions of PetriNet global scoped functions" is redundant. Consider simplifying to:
📝 Suggested documentation improvement /**
- * Default cache name for caching global functions of PetriNet global scoped functions.
+ * Default cache name for caching PetriNet global-scoped functions.
*/
private String globalFunctions = "globalFunctions";Based on learnings, the property name 🤖 Prompt for AI Agents |
||
|
|
||
| /** | ||
| * A list of additional custom cache names. | ||
| * Allows users to define their own cache names for specific use cases. | ||
| */ | ||
| private List<String> additional = new ArrayList<>(); | ||
|
|
||
| /** | ||
| * The size of pages used for caching functions when processing large sets of data. | ||
| * This property determines the maximum number of functions to include in a single page during caching operations. | ||
| * Default value is 500. | ||
| */ | ||
| private int functionCachingPageSize = 500; | ||
|
|
||
| /** | ||
| * Retrieves a set of all configured cache names. | ||
| * Includes the default caches and any additional user-defined cache names. | ||
| * | ||
| * @return a {@link Set} of all cache names. | ||
| */ | ||
| public Set<String> getAllCaches() { | ||
| Set<String> caches = new LinkedHashSet<>(Arrays.asList(petriNetById, petriNetByIdentifier, petriNetNewest, petriNetCache, loadedModules)); | ||
| Set<String> caches = new LinkedHashSet<>(Arrays.asList(petriNetById, petriNetByIdentifier, petriNetDefault, | ||
| petriNetLatest, petriNetCache, loadedModules, globalFunctions)); | ||
| caches.addAll(additional); | ||
| return caches; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -54,9 +54,9 @@ public static class FieldRunnerProperties { | |
| private int functionsCacheSize = 500; | ||
|
|
||
| /** | ||
| * The size of the cache used for maintaining field runner namespaces. | ||
| * The size of the cache used for managing global Petri net functions. | ||
| */ | ||
| private int namespaceCacheSize = 500; | ||
| private int globalFunctionsCacheSize = 500; | ||
|
Comment on lines
+57
to
+59
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Search for references to the old namespaceCacheSize property name
echo "=== Searching for Java references to namespaceCacheSize ==="
rg -n --type=java 'namespaceCacheSize|getNamespaceCacheSize|setNamespaceCacheSize'
echo -e "\n=== Searching for property file references ==="
rg -n --type=yaml --type=properties 'namespaceCacheSize|namespace-cache-size|namespace_cache_size'
echo -e "\n=== Searching for test file references ==="
rg -n --type=java 'namespaceCacheSize' -- '**/*.java'
echo -e "\n=== Checking for migration guides or deprecation notes ==="
rg -n -i 'migration|deprecat|namespace.*cache|namespaceCacheSize'Repository: netgrif/application-engine Length of output: 50486 🏁 Script executed: #!/bin/bash
# Verify the current state of RunnerConfigurationProperties.java around lines 57-59
echo "=== Reading RunnerConfigurationProperties.java lines 50-65 ==="
sed -n '50,65p' application-engine/src/main/java/com/netgrif/application/engine/configuration/properties/RunnerConfigurationProperties.java
echo -e "\n=== Checking for getter/setter methods for globalFunctionsCacheSize ==="
rg -n -A5 -B5 'globalFunctionsCacheSize' application-engine/src/main/java/com/netgrif/application/engine/configuration/properties/RunnerConfigurationProperties.javaRepository: netgrif/application-engine Length of output: 932 🏁 Script executed: #!/bin/bash
# Search for all property definitions in CacheConfigurationProperties and FieldRunnerProperties
echo "=== Checking CacheConfigurationProperties for related properties ==="
find . -name 'CacheConfigurationProperties.java' -exec cat -n {} \;
echo -e "\n=== Searching for uses of globalFunctionsCacheSize in codebase ==="
rg -n 'globalFunctionsCacheSize' --type=javaRepository: netgrif/application-engine Length of output: 3469 🏁 Script executed: #!/bin/bash
# Search for usage of cache size properties in implementation code
echo "=== Searching for functionsCacheSize usage ==="
rg -n 'functionsCacheSize' --type=java | head -20
echo -e "\n=== Searching for globalFunctionsCacheSize usage outside property definition ==="
rg -n 'globalFunctionsCacheSize' --type=java
echo -e "\n=== Searching for references to FieldRunnerProperties or cache configuration ==="
rg -n 'FieldRunnerProperties|getGlobalFunctionsCacheSize|getFunctionsCacheSize' --type=java | head -30
echo -e "\n=== Checking if property is actually wired/injected ==="
rg -n 'RunnerConfigurationProperties|FieldRunnerProperties' --type=java -B2 -A2 | head -50Repository: netgrif/application-engine Length of output: 8490 🏁 Script executed: #!/bin/bash
# Check where the cache sizes are actually used
echo "=== Searching for cache configuration usage in runner/function classes ==="
fd -t f -name '*.java' -path '*runner*' -o -path '*function*' | xargs rg -l 'cache|Cache' 2>/dev/null | head -10
echo -e "\n=== Check FunctionValidator for cache usage ==="
rg -n 'FunctionValidator' --type=java -A5 -B5 | head -40
echo -e "\n=== Search for any property getter usage pattern ==="
rg -n '\.get[A-Z]' application-engine/src/main/java/com/netgrif/application/engine/configuration/properties/RunnerConfigurationProperties.javaRepository: netgrif/application-engine Length of output: 5343 🏁 Script executed: #!/bin/bash
# Verify the cache configuration wiring to understand the integration gap
echo "=== Reading CacheConfiguration.java around line 52 ==="
sed -n '20,65p' application-engine/src/main/java/com/netgrif/application/engine/configuration/CacheConfiguration.java
echo -e "\n=== Search for any cache setup for global functions ==="
rg -n 'globalFunctions|GlobalFunctions' --type=java -B3 -A3
echo -e "\n=== Check if there are TODOs or incomplete implementation markers ==="
rg -n 'TODO|FIXME|XXX' application-engine/src/main/java/com/netgrif/application/engine/configuration/CacheConfiguration.javaRepository: netgrif/application-engine Length of output: 11223 Wire the The Update 🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| /** | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| package com.netgrif.application.engine.importer.service; | ||
|
|
||
| import com.netgrif.application.engine.objects.importer.model.Function; | ||
| import com.netgrif.application.engine.objects.importer.model.Scope; | ||
| import lombok.extern.slf4j.Slf4j; | ||
| import org.springframework.stereotype.Component; | ||
|
|
||
| @Component | ||
| @Slf4j | ||
| public class FunctionValidator implements IFunctionValidator { | ||
|
|
||
| private static final String NAMESPACE = "namespace"; | ||
|
|
||
| /** | ||
| * Validates and updates deprecated function attributes. | ||
| * <p> | ||
| * This method mutates the input function by replacing deprecated scope values. | ||
| * Specifically, it replaces the deprecated NAMESPACE scope with GLOBAL scope. | ||
| * | ||
| * @param function the function to validate and update (mutated in-place) | ||
| */ | ||
| @Override | ||
| public void checkDeprecatedAttributes(Function function) { | ||
| if (function.getScope() != null && function.getScope().value().equals(NAMESPACE)) { | ||
| log.warn("Function scope [NAMESPACE] is deprecated. Replacing with [GLOBAL]."); | ||
| function.setScope(Scope.GLOBAL); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package com.netgrif.application.engine.importer.service; | ||
|
|
||
| import com.netgrif.application.engine.objects.importer.model.Function; | ||
|
|
||
| public interface IFunctionValidator extends IModelValidator { | ||
| /** | ||
| * Validates and updates deprecated function attributes. | ||
| * <p> | ||
| * This method mutates the input function by replacing deprecated scope values. | ||
| * Specifically, it replaces the deprecated NAMESPACE scope with GLOBAL scope. | ||
| * | ||
| * @param function the function to validate and update (mutated in-place) | ||
| */ | ||
| void checkDeprecatedAttributes(Function function); | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.