-
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 8 commits
dd58002
5b98ca4
e917f76
bd719b5
e976081
8323adb
f9796d6
d2227d0
cb1505f
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,110 @@ | ||
| package com.netgrif.application.engine.configuration; | ||
|
|
||
| import lombok.extern.slf4j.Slf4j; | ||
| 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; | ||
| import java.util.concurrent.atomic.AtomicReference; | ||
|
|
||
| @Slf4j | ||
| public class GenericMapCache<V> implements Cache { | ||
| private final String name; | ||
| private final Class<V> valueType; | ||
| private final java.util.function.Supplier<Map<String, V>> mapFactory; | ||
| private final AtomicReference<Map<String, V>> atomicMapRef; | ||
|
|
||
| private final ConcurrentHashMap<String, Object> locks = new ConcurrentHashMap<>(); | ||
|
|
||
| public GenericMapCache(String name, Class<V> valueType, java.util.function.Supplier<Map<String, V>> mapFactory) { | ||
| this.name = name; | ||
| this.valueType = valueType; | ||
| this.mapFactory = mapFactory; | ||
| this.atomicMapRef = new AtomicReference<>(mapFactory.get()); | ||
| } | ||
|
|
||
| @Override public String getName() { return name; } | ||
|
|
||
| @Override public Object getNativeCache() { return Map.copyOf(map()); } | ||
|
|
||
|
Comment on lines
+30
to
+31
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 Preserve native cache identity; clear in place. Apply this diff: - @Override public Object getNativeCache() { return Map.copyOf(map()); }
+ @Override public Object getNativeCache() { return map(); }
@@
- public synchronized void clear() {
- this.atomicMapRef.set(mapFactory.get());
- }
+ public synchronized void clear() {
+ map().clear();
+ log.debug("{} cache cleared", name);
+ }Also applies to: 95-98 🤖 Prompt for AI Agents |
||
| @Override | ||
| public <T> T get(Object key, Callable<T> loader) { | ||
| final String stringKey = String.valueOf(key); | ||
|
|
||
| Object mapValue = map().get(stringKey); | ||
| if (mapValue != null) { | ||
| return (T) mapValue; | ||
| } | ||
|
|
||
| Object lock = locks.computeIfAbsent(stringKey, lockKey -> new Object()); | ||
| try { | ||
| synchronized (lock) { | ||
| Object mapLockValue = map().get(stringKey); | ||
| if (mapLockValue != null) { | ||
| return (T) mapLockValue; | ||
| } | ||
|
|
||
| T computed = loader.call(); | ||
| if (computed == null) { | ||
| return null; | ||
| } | ||
|
|
||
| V value = safeCast(computed); | ||
| map().put(stringKey, value); | ||
| return (T) value; | ||
| } | ||
| } catch (Exception ex) { | ||
| throw new Cache.ValueRetrievalException(stringKey, loader, ex); | ||
| } finally { | ||
| locks.remove(stringKey, lock); | ||
| } | ||
| } | ||
|
|
||
| @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 synchronized <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 synchronized void put(Object key, Object value) { | ||
| map().put(String.valueOf(key), safeCast(value)); | ||
| } | ||
|
|
||
| @Override | ||
| public synchronized void evict(Object key) { | ||
| map().remove(String.valueOf(key)); | ||
| } | ||
|
|
||
| @Override | ||
| public synchronized void clear() { | ||
| this.atomicMapRef.set(mapFactory.get()); | ||
| } | ||
|
|
||
| private Map<String, V> map() { | ||
| return atomicMapRef.get(); | ||
| } | ||
|
|
||
| @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 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,10 +1,7 @@ | ||||||||||||
| package com.netgrif.application.engine.petrinet.service.interfaces; | ||||||||||||
|
|
||||||||||||
| import com.netgrif.application.engine.objects.auth.domain.LoggedUser; | ||||||||||||
| import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; | ||||||||||||
| import com.netgrif.application.engine.objects.petrinet.domain.PetriNetSearch; | ||||||||||||
| import com.netgrif.application.engine.objects.petrinet.domain.Transition; | ||||||||||||
| import com.netgrif.application.engine.objects.petrinet.domain.VersionType; | ||||||||||||
| import com.netgrif.application.engine.objects.petrinet.domain.*; | ||||||||||||
|
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 Avoid wildcard imports; restore explicit imports. Wildcard imports are against common style guides (and often blocked by Checkstyle), can hide accidental type collisions, and make IDE organize‑imports unstable. Please revert to explicit imports for the actually used types (PetriNet, PetriNetSearch, Transition, VersionType). Apply: -import com.netgrif.application.engine.objects.petrinet.domain.*;
+import com.netgrif.application.engine.objects.petrinet.domain.PetriNet;
+import com.netgrif.application.engine.objects.petrinet.domain.PetriNetSearch;
+import com.netgrif.application.engine.objects.petrinet.domain.Transition;
+import com.netgrif.application.engine.objects.petrinet.domain.VersionType;📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||
| import com.netgrif.application.engine.objects.petrinet.domain.dataset.Field; | ||||||||||||
| import com.netgrif.application.engine.objects.petrinet.domain.dataset.logic.action.Action; | ||||||||||||
| import com.netgrif.application.engine.objects.petrinet.domain.throwable.MissingIconKeyException; | ||||||||||||
|
|
||||||||||||
Uh oh!
There was an error while loading. Please reload this page.