Skip to content

Conversation

@dominikvozr
Copy link

@dominikvozr dominikvozr commented Sep 24, 2025

Description

This PR introduces a function that caches all petriNets namespace functions in cache.

Implements NAE-2212

How Has Been This Tested?

The functionality was tested in local cluster with admin and 1 worker.

Name Tested on
OS Windows 11
Runtime Java 21
Dependency Manager Apache Maven 3.9.9
Framework version Spring Boot 3.2.5, NAE 7.0.0-rev7
Run parameters mvn clean install
Other configuration

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • My changes have been checked, personally or remotely, with @...
  • I have commented my code, particularly in hard-to-understand areas
  • I have resolved all conflicts with the target branch of the PR
  • I have updated and synced my code with the target branch
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing tests pass locally with my changes:
    • Lint test
    • Unit tests
    • Integration tests
  • I have checked my contribution with code analysis tools:
  • I have made corresponding changes to the documentation:
    • Developer documentation
    • User Guides
    • Migration Guides

Summary by CodeRabbit

  • New Features

    • Added bulk cache warm-up across all process definitions to speed up initial usage.
    • Introduced read-only caches to prevent accidental eviction and improve stability.
    • Added a dedicated cache for namespace-level functions to accelerate lookups.
  • Chores

    • Updated CI storage service image for reliability.
    • Adjusted Docker Compose to run the storage console on port 9001 for easier local management.

@coderabbitai
Copy link

coderabbitai bot commented Sep 24, 2025

Walkthrough

Adds bulk caching of Petri net functions with pagination, extends the cache configuration to support a read-only cache set via a new WorkerConcurrentCacheManager and a new cache name property (namespaceFunctions), introduces a ReadOnlyCache wrapper, updates Spring Cache configuration to use the new manager, and adjusts MinIO settings in CI and docker-compose.

Changes

Cohort / File(s) Summary of changes
Field actions bulk caching
application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FieldActionsCacheService.java, application-engine/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IFieldActionsCacheService.java
Added cacheAllPetriNetsFunctions() with pagination (PageRequest size 500) to iterate PetriNets and call cachePetriNetFunctions(petriNet) with per-item warning on failure; exposed the method in the interface.
Cache manager and read-only wrapper
application-engine/src/main/java/com/netgrif/application/engine/configuration/CacheConfiguration.java, application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/WorkerConcurrentCacheManager.java, application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/ReadOnlyCache.java
Replaced ConcurrentMapCacheManager with WorkerConcurrentCacheManager and passed a read-only set containing namespaceFunctions. Added WorkerConcurrentCacheManager that wraps specified caches in ReadOnlyCache; added ReadOnlyCache that delegates reads/writes except blocks evict() and clear() via UnsupportedOperationException.
Cache properties
application-engine/src/main/java/com/netgrif/application/engine/configuration/properties/CacheConfigurationProperties.java
Added namespaceFunctions property (default "namespaceFunctions") and included it in getAllCaches().
CI MinIO image
.github/workflows/pr-build.yml
Switched MinIO image from minio/minio:RELEASE.2022-12-12T19-27-27Z to docker.io/bawix/minio:2022.
Docker Compose MinIO command
application-engine/docker-compose.yml
Added command: server /data --console-address ":9001" to MinIO service.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Caller as Caller
  participant Service as FieldActionsCacheService
  participant Repo as PetriNetRepository
  participant Cache as FunctionCache

  Caller->>Service: cacheAllPetriNetsFunctions()
  loop Paginate (size=500) until no more pages
    Service->>Repo: findAll(PageRequest)
    Repo-->>Service: Page<PetriNet>
    loop For each PetriNet
      Service->>Service: cachePetriNetFunctions(petriNet)
      Service->>Cache: put(functions for petriNet)
      alt error while caching
        Service->>Service: log warn
      end
    end
  end
Loading
sequenceDiagram
  autonumber
  participant Spring as Spring Context
  participant Config as CacheConfiguration
  participant Manager as WorkerConcurrentCacheManager
  participant Cache as ConcurrentMapCache
  participant RO as ReadOnlyCache

  Spring->>Config: cacheManager()
  Config-->>Manager: new WorkerConcurrentCacheManager(Set{ "namespaceFunctions" }, caches...)
  Spring->>Manager: getCache("namespaceFunctions")
  Manager->>Manager: createConcurrentMapCache("namespaceFunctions")
  Manager->>Cache: new ConcurrentMapCache
  Manager->>RO: wrap Cache in ReadOnlyCache
  Manager-->>Spring: ReadOnlyCache
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Pre-merge checks

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "NAE-2212 Cluster scope process function caches" concisely and accurately summarizes the primary enhancement of introducing cluster-wide caching for process (Petri net) functions, aligns with the linked Jira issue, and omits extraneous details or noise.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🧪 Early access (Sonnet 4.5): enabled

We are currently testing the Sonnet 4.5 model, which is expected to improve code review quality. However, this model may lead to increased noise levels in the review comments. Please disable the early access features if the noise level causes any inconvenience.

Note:

  • Public repositories are always opted into early access features.
  • You can enable or disable early access features from the CodeRabbit UI or by updating the CodeRabbit configuration file.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1364bc7 and a002636.

📒 Files selected for processing (2)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FieldActionsCacheService.java (3 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IFieldActionsCacheService.java (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (1)
application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FieldActionsCacheService.java (1)

42-45: Constructor change is safe — no manual instantiations found

rg output shows only the class declaration; no new FieldActionsCacheService(...) or other constructor references. The class is annotated @Service, so Spring will inject MongoTemplate.

Comment on lines +30 to +31
void cacheAllPetriNetsFunctions();

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Define the contract (scope, version, and cache semantics) for the new bulk method.

Please document whether this:

  • processes only newest PetriNet versions or all historical ones,
  • clears stale entries for deleted PetriNets before rebuilding,
  • is intended to be long‑running and should be invoked off the request thread.

Consider a tighter name for consistency with the singular: cacheAllPetriNetFunctions().

Apply this diff to add Javadoc:

-    void cacheAllPetriNetsFunctions();
+    /**
+     * Pre-populates the namespace function cache for all PetriNets.
+     * Contract:
+     * - Only newest version per PetriNet identifier SHOULD be cached.
+     * - Stale cache entries for non-existing PetriNets SHOULD be cleared or overwritten.
+     * - This operation MAY be long-running; invoke off request threads.
+     */
+    void cacheAllPetriNetsFunctions();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
void cacheAllPetriNetsFunctions();
/**
* Pre-populates the namespace function cache for all PetriNets.
* Contract:
* - Only newest version per PetriNet identifier SHOULD be cached.
* - Stale cache entries for non-existing PetriNets SHOULD be cleared or overwritten.
* - This operation MAY be long-running; invoke off request threads.
*/
void cacheAllPetriNetsFunctions();
🤖 Prompt for AI Agents
In
application-engine/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IFieldActionsCacheService.java
around lines 30-31, add Javadoc for the bulk caching method that defines its
contract: clarify whether it processes only the newest PetriNet versions or all
historical versions, state whether it clears stale entries for deleted PetriNets
before rebuilding the cache, and indicate that it is long-running and should be
called off the request thread (or provide async variant). Also rename the method
to cacheAllPetriNetFunctions() for consistency with the singular form and
reflect the chosen semantics (scope, version policy, cache eviction strategy,
and threading expectations) in the Javadoc summary and
parameter/return/exception notes.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a002636 and e6e8dac.

📒 Files selected for processing (5)
  • application-engine/src/main/java/com/netgrif/application/engine/configuration/CacheConfiguration.java (2 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/CacheMapKeys.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/ReadOnlyCache.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/WorkerConcurrentCacheManager.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/configuration/properties/CacheConfigurationProperties.java (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
application-engine/src/main/java/com/netgrif/application/engine/configuration/CacheConfiguration.java (1)
application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/WorkerConcurrentCacheManager.java (1)
  • WorkerConcurrentCacheManager (6-23)
application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/WorkerConcurrentCacheManager.java (1)
application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/CacheMapKeys.java (1)
  • CacheMapKeys (3-5)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Test
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
🔇 Additional comments (3)
application-engine/src/main/java/com/netgrif/application/engine/configuration/properties/CacheConfigurationProperties.java (1)

44-48: Configurable name vs hard‑coded constant: ensure they stay in sync

Since this name is configurable, hard-coding a different literal in WorkerConcurrentCacheManager/CacheMapKeys breaks the intended read‑only behavior. Either keep the constant aligned (see prior comment) or have the manager read this value.

application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/ReadOnlyCache.java (1)

30-41: Enforce consistent immutability or update naming
ReadOnlyCache permits put(...) but throws on evict/clear, which conflicts with “read-only.” Decide whether to block put (and override Spring 6.x defaults like putIfAbsent and evictIfPresent) for true immutability, or rename to NoEvictCache if only invalidation should be disallowed. Confirm intended behavior.

application-engine/src/main/java/com/netgrif/application/engine/configuration/CacheConfiguration.java (1)

27-27: Incorrect suggestion—missing constructor: WorkerConcurrentCacheManager only defines WorkerConcurrentCacheManager() and WorkerConcurrentCacheManager(String… ), so calling new WorkerConcurrentCacheManager(Set<String>, String… ) won’t compile.

Likely an incorrect or invalid review comment.

Comment on lines 3 to 5
public class CacheMapKeys {
public static final String NAMESPACE_FUNCTIONS = "namespaceFunctionsCache";
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Make constants holder non-instantiable and final

Prevents accidental instantiation and clarifies intent.

-public class CacheMapKeys {
+public final class CacheMapKeys {
+        private CacheMapKeys() {}
         public static final String NAMESPACE_FUNCTIONS = "namespaceFunctions";
 }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/CacheMapKeys.java
around lines 3 to 5, the constants holder class should be made non-instantiable
and final; change the class declaration to final and add a private no-argument
constructor (preferably throwing an AssertionError) to prevent instantiation and
clarify intent while leaving the existing public static constant unchanged.

Comment on lines 61 to 63
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, petriNetNewest, petriNetCache, loadedModules, namespaceFunctions));
caches.addAll(additional);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Guard against future drift and blank values

If users override namespaceFunctions in config, the read‑only wrapping must follow that value. Recommend passing this property into the CacheManager instead of relying on a constant. Also consider ignoring blank entries to avoid empty‑named caches.

Possible follow-up (see proposed constructor in WorkerConcurrentCacheManager and bean wiring in CacheConfiguration).

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e6e8dac and 6e09ba1.

📒 Files selected for processing (4)
  • application-engine/src/main/java/com/netgrif/application/engine/configuration/CacheConfiguration.java (2 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/CacheMapKeys.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/WorkerConcurrentCacheManager.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FieldActionsCacheService.java (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
application-engine/src/main/java/com/netgrif/application/engine/configuration/CacheConfiguration.java (2)
application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/CacheMapKeys.java (1)
  • CacheMapKeys (3-6)
application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/WorkerConcurrentCacheManager.java (1)
  • WorkerConcurrentCacheManager (9-35)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Test
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
🔇 Additional comments (4)
application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FieldActionsCacheService.java (1)

103-120: Prevent caching stale PetriNet revisions

petriNetService.getAll(pageable) returns every stored revision. Visiting them with cachePetriNetFunctions means the last revision encountered wins, so if an older version shows up later in the page order the namespace cache ends up serving obsolete code. We also never evict entries for PetriNets that were deleted, so their namespace functions linger indefinitely. Clear the cache before the rebuild and resolve each identifier to its newest revision before caching.

Apply a fix along these lines:

-        Pageable pageable = PageRequest.of(0, 500);
-        Page<PetriNet> page = petriNetService.getAll(pageable);
+        clearNamespaceFunctionCache();
+        Pageable pageable = PageRequest.of(0, 500);
+        Page<PetriNet> page = petriNetService.getAll(pageable);
@@
-                    cachePetriNetFunctions(petriNet);
+                    reloadCachedFunctions(petriNet);
application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/CacheMapKeys.java (1)

3-6: LGTM: constants holder is final with a private ctor and aligned cache key

Matches naming in configuration and prevents instantiation. No further action.

application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/WorkerConcurrentCacheManager.java (1)

27-34: LGTM: read-only wrapping at creation point

Wrapping via ReadOnlyCache on cache creation is correct and sufficient.

application-engine/src/main/java/com/netgrif/application/engine/configuration/CacheConfiguration.java (1)

30-31: Namespace functions cache exposed Lombok @DaTa generates getNamespaceFunctions(), and getAllCaches() includes namespaceFunctions. No code change needed; verify each environment’s netgrif.engine.cache.namespace-functions property is set correctly or relies on the default.

@machacjozef machacjozef changed the title NAE-2212 - added method that will cache all petriNets functions [NAE-2212] Added method that will cache all petriNets functions Sep 29, 2025
@machacjozef machacjozef changed the title [NAE-2212] Added method that will cache all petriNets functions [NAE-2212] Cluster scope process function caches Sep 29, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6e09ba1 and 790659b.

📒 Files selected for processing (2)
  • application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/WorkerConcurrentCacheManager.java (1 hunks)
  • nae-object-library/src/main/resources/petriflow_schema.xsd (1 hunks)
🧰 Additional context used
🪛 GitHub Actions: Pull Request
nae-object-library/src/main/resources/petriflow_schema.xsd

[error] 2-35: XJC error: SAXParseException: s4s-elt-character: Non-whitespace characters are not allowed in schema elements other than 'xs:appinfo' and 'xs:documentation'. Saw '301 Moved Permanently'.


[error] 4-36: XJC error: SAXParseException: s4s-elt-character: Non-whitespace characters are not allowed in schema elements other than 'xs:appinfo' and 'xs:documentation'. Saw '301 Moved Permanently'.


[error] 5-20: XJC error: SAXParseException: s4s-elt-character: Non-whitespace characters are not allowed in schema elements other than 'xs:appinfo' and 'xs:documentation'. Saw 'nginx'.


[error] 6-3: XJC error: The element type "hr" must be terminated by the matching end-tag "".

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: task-list-completed
🔇 Additional comments (4)
application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/WorkerConcurrentCacheManager.java (4)

6-8: Use immutable Set and null-safety imports (Objects, Set) instead of List/ArrayList

Switching to Set enables O(1) membership checks and, with defensive copying, removes thread-safety risks from external mutation.

-import java.util.ArrayList;
-import java.util.List;
+import java.util.Objects;
+import java.util.Set;

9-15: Make readOnlyCacheNames final and non-null with an immutable default

Current mutable List can be altered after construction, causing racy behavior. Make it final and default to Set.of().

-public class WorkerConcurrentCacheManager extends ConcurrentMapCacheManager {
-    private List<String> readOnlyCacheNames;
+public class WorkerConcurrentCacheManager extends ConcurrentMapCacheManager {
+    private final Set<String> readOnlyCacheNames;
@@
     public WorkerConcurrentCacheManager() {
         super();
-        this.readOnlyCacheNames = new ArrayList<>();
+        this.readOnlyCacheNames = Set.of();
     }

17-25: Defensively copy constructor args and accept Set; add null checks

The constructors leak internal state and allow null. Copy into an immutable Set and enforce non-null.

-    public WorkerConcurrentCacheManager(List<String> readOnlyCacheNames) {
+    public WorkerConcurrentCacheManager(Set<String> readOnlyCacheNames) {
         super();
-        this.readOnlyCacheNames = readOnlyCacheNames;
+        this.readOnlyCacheNames = Set.copyOf(Objects.requireNonNull(readOnlyCacheNames, "readOnlyCacheNames"));
     }
@@
-    public WorkerConcurrentCacheManager(List<String> readOnlyCacheNames, String... cacheNames) {
+    public WorkerConcurrentCacheManager(Set<String> readOnlyCacheNames, String... cacheNames) {
         super(cacheNames);
-        this.readOnlyCacheNames = readOnlyCacheNames;
+        this.readOnlyCacheNames = Set.copyOf(Objects.requireNonNull(readOnlyCacheNames, "readOnlyCacheNames"));
     }

27-34: Read-only cache names include namespace‐functions constant. WorkerConcurrentCacheManager is constructed with List.of(CacheMapKeys.NAMESPACE_FUNCTIONS), covering the Petri-net namespace-functions cache used by FieldActionsCacheService; no naming drift detected.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/WorkerConcurrentCacheManager.java (3)

34-34: Remove unnecessary null check on non-null final field.

Since readOnlyCacheNames is final and always initialized to a non-null Set in all constructors, the null check is redundant.

Apply this diff:

-        if (readOnlyCacheNames != null && readOnlyCacheNames.contains(name)) {
+        if (readOnlyCacheNames.contains(name)) {

34-34: Remove unnecessary null check on non-null final field.

The readOnlyCacheNames field is final and initialized to a non-null value in all constructors. The null check at line 34 is redundant and adds unnecessary complexity.

Apply this diff:

     @Override
     protected Cache createConcurrentMapCache(String name) {
         Cache base = super.createConcurrentMapCache(name);
-        if (readOnlyCacheNames != null && readOnlyCacheNames.contains(name)) {
+        if (readOnlyCacheNames.contains(name)) {
             return new ReadOnlyCache(base);
         }
         return base;
     }

31-38: Remove redundant null check on readOnlyCacheNames.

The field readOnlyCacheNames is final and guaranteed non-null by all constructors, so the null check on line 34 is redundant and can be simplified.

Apply this diff to simplify the logic:

     @Override
     protected Cache createConcurrentMapCache(String name) {
         Cache base = super.createConcurrentMapCache(name);
-        if (readOnlyCacheNames != null && readOnlyCacheNames.contains(name)) {
+        if (readOnlyCacheNames.contains(name)) {
             return new ReadOnlyCache(base);
         }
         return base;
     }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 790659b and 7dc7947.

📒 Files selected for processing (2)
  • application-engine/src/main/java/com/netgrif/application/engine/configuration/CacheConfiguration.java (2 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/WorkerConcurrentCacheManager.java (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
application-engine/src/main/java/com/netgrif/application/engine/configuration/CacheConfiguration.java (1)
application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/WorkerConcurrentCacheManager.java (1)
  • WorkerConcurrentCacheManager (9-39)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
🔇 Additional comments (11)
application-engine/src/main/java/com/netgrif/application/engine/configuration/CacheConfiguration.java (3)

30-30: LGTM! Past review feedback has been addressed.

The cache manager instantiation correctly uses the configured namespace functions cache name from properties instead of a hard-coded constant, and properly passes a Set as the first argument to WorkerConcurrentCacheManager.


30-30: No null guard required for namespaceFunctions
CacheConfigurationProperties defines

private String namespaceFunctions = "namespaceFunctions";

so getNamespaceFunctions() always returns this non-null default.


30-30: No null check needed for namespaceFunctions

CacheConfigurationProperties initializes namespaceFunctions with a non-null default value ("namespaceFunctions"), so Set.of(properties.getNamespaceFunctions()) cannot receive null.

application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/WorkerConcurrentCacheManager.java (8)

10-29: LGTM! Constructors follow immutability and defensive copying best practices.

The readOnlyCacheNames field is properly declared final, constructors use Set.copyOf() for defensive immutability, and null checks with descriptive messages prevent NPEs. This addresses the past review feedback about making the field immutable and thread-safe.


10-10: Excellent: immutable, thread-safe field design.

The final Set<String> field with defensive copying in constructors correctly addresses the past refactor suggestion and ensures thread-safe, immutable state.


12-15: LGTM: Default constructor correctly initializes empty set.

Using Set.of() for the default case is clean and efficient.


17-22: LGTM: Proper defensive copying with null safety.

The constructor correctly uses Set.copyOf() with Objects.requireNonNull() to ensure immutability and prevent null values.


24-29: LGTM: Varargs constructor maintains consistency.

The constructor properly delegates to the parent and applies the same defensive copying pattern for read-only cache names.


12-15: LGTM!

The default constructor correctly initializes readOnlyCacheNames to an empty immutable set, ensuring the field is always non-null.


17-22: LGTM!

The constructor correctly performs null validation and creates a defensive immutable copy of the provided set, ensuring thread-safety and immutability.


24-29: LGTM!

The constructor correctly validates input, creates a defensive copy, and delegates cache name registration to the superclass. Immutability and null-safety are guaranteed.

Comment on lines +31 to +38
@Override
protected Cache createConcurrentMapCache(String name) {
Cache base = super.createConcurrentMapCache(name);
if (readOnlyCacheNames != null && readOnlyCacheNames.contains(name)) {
return new ReadOnlyCache(base);
}
return base;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify ReadOnlyCache correctly prevents all write operations.

The wrapper logic correctly delegates wrapping to ReadOnlyCache for caches in the read-only set. Ensure that ReadOnlyCache properly blocks all mutating operations (put, evict, clear, etc.) to maintain the read-only guarantee.

Run the following script to examine the ReadOnlyCache implementation:


🏁 Script executed:

#!/bin/bash
# Description: Verify ReadOnlyCache blocks all write operations.

# Search for ReadOnlyCache class and its method implementations
ast-grep --pattern $'class ReadOnlyCache {
  $$$
}'

# Check for methods that throw UnsupportedOperationException
rg -nP -A3 'class ReadOnlyCache' --type=java
rg -nP 'UnsupportedOperationException' --type=java -g '**/ReadOnlyCache.java'

Length of output: 913


🏁 Script executed:

#!/bin/bash
# Display the full ReadOnlyCache implementation to verify write-blocking methods
sed -n '1,200p' application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/ReadOnlyCache.java

Length of output: 1198


🏁 Script executed:

#!/bin/bash
rg -n 'putIfAbsent' -g 'application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/ReadOnlyCache.java'

Length of output: 0


Enforce read-only behavior by blocking all mutating cache operations in ReadOnlyCache
ReadOnlyCache currently delegates put(Object,Object) and inherits default putIfAbsent(Object,Object), so write operations still succeed. Override both methods to throw UnsupportedOperationException to uphold the read-only guarantee.
File: application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/ReadOnlyCache.java

🤖 Prompt for AI Agents
In
application-engine/src/main/java/com/netgrif/application/engine/configuration/cache/ReadOnlyCache.java
(around the class definition), the ReadOnlyCache currently delegates
put(Object,Object) and inherits putIfAbsent(Object,Object) which allows writes;
override both put(K,V) and putIfAbsent(K,V) to throw
UnsupportedOperationException to enforce true read-only behavior (ensure
signatures match the Cache interface used and include clear exception messages),
and run tests to confirm write attempts now fail.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7dc7947 and 93921f9.

📒 Files selected for processing (2)
  • .github/workflows/pr-build.yml (1 hunks)
  • application-engine/docker-compose.yml (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Test
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
🔇 Additional comments (1)
application-engine/docker-compose.yml (1)

46-46: Command addition looks good, but verify image consistency with CI.

The addition of the MinIO startup command with the console address is valid and aligns with the exposed port 9001.

However, note an inconsistency: this docker-compose file uses the official minio/minio:RELEASE.2022-12-12T19-27-27Z image, while the CI workflow (.github/workflows/pr-build.yml line 55) uses docker.io/bawix/minio:2022. Consider standardizing on the same image across both environments to ensure consistent behavior and avoid configuration drift.

Additionally, verify whether these MinIO changes are actually required for the stated PR objective (cluster-scoped function caching), as the connection is not immediately apparent.

@netgrif netgrif deleted a comment from coderabbitai bot Sep 30, 2025
@netgrif netgrif deleted a comment from coderabbitai bot Sep 30, 2025
@netgrif netgrif deleted a comment from coderabbitai bot Sep 30, 2025
@netgrif netgrif deleted a comment from coderabbitai bot Sep 30, 2025
@netgrif netgrif deleted a comment from coderabbitai bot Sep 30, 2025
@netgrif netgrif deleted a comment from coderabbitai bot Sep 30, 2025
@machacjozef machacjozef changed the base branch from release/7.0.0-rev8 to release/7.0.0-rev9 November 9, 2025 11:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants