Skip to content

split BeanRegistry interface#2488

Merged
christiangoerdes merged 4 commits into
masterfrom
split-beanregistry-interface
Dec 23, 2025
Merged

split BeanRegistry interface#2488
christiangoerdes merged 4 commits into
masterfrom
split-beanregistry-interface

Conversation

@rrayst
Copy link
Copy Markdown
Member

@rrayst rrayst commented Dec 21, 2025

Summary by CodeRabbit

  • Chores

    • Added SpotBugs annotations to improve static analysis and code quality checks.
  • Refactor

    • Reworked bean/registry internals to support asynchronous event processing and clearer lifecycle handling.
    • Simplified YAML parsing and Kubernetes integration for decoupled configuration processing.
  • Tests

    • Updated tests to match the refactored registry, parsing, and event flow.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 21, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Refactors the bean/YAML subsystem: moves types into a new beanregistry package, introduces an event-driven BeanCollector/ChangeEvent model with BeanDefinitionChanged, adds AsyncBeanCollector, provides a new BeanRegistryImplementation (concurrent activation/caching), and updates parsing to return bean definitions.

Changes

Cohort / File(s) Change Summary
New beanregistry API
annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanCollector.java, annot/src/main/java/com/predic8/membrane/annot/beanregistry/ChangeEvent.java, annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanDefinitionChanged.java
Adds BeanCollector (default parseYamls + abstract handle/start), makes ChangeEvent public sealed, and adds BeanDefinitionChanged record (WatchAction + BeanDefinition).
Bean model & container
annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanDefinition.java, annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanContainer.java
Moves/refactors BeanDefinition to be node-centric and immutable (factory returns BeanDefinitionChanged for k8s), and adds BeanContainer to hold definition + singleton.
Async event dispatcher
annot/src/main/java/com/predic8/membrane/annot/beanregistry/AsyncBeanCollector.java
Adds AsyncBeanCollector that enqueues ChangeEvents and dispatches them to a delegate on a single background (virtual) thread.
Registry implementation (new)
annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistryImplementation.java
New BeanRegistryImplementation implementing BeanRegistry and BeanCollector: concurrent container map, activation queue, singleton/prototype resolution, observer notifications, handle/start lifecycle.
Registry implementation (removed)
annot/src/main/java/com/predic8/membrane/annot/yaml/BeanRegistryImplementation.java
Deletes old yaml-package BeanRegistryImplementation (responsibilities moved to new beanregistry implementation).
Parsing API & flow
annot/src/main/java/com/predic8/membrane/annot/yaml/GenericYamlParser.java, annot/src/test/java/.../YamlParser.java
parseMembraneResources now returns List<BeanDefinition>; test utility updated to use BeanCollector.parseYamls(...); observer callbacks adapted to BeanDefinitionChanged.
Observer & action helpers
annot/src/main/java/com/predic8/membrane/annot/yaml/BeanCacheObserver.java, annot/src/main/java/com/predic8/membrane/annot/yaml/WatchAction.java
BeanCacheObserver.handleBeanEvent now accepts BeanDefinitionChanged; WatchAction gains isAdded/isModified/isDeleted predicates.
Call-site adaptations
core/src/main/java/com/predic8/membrane/core/Router.java, core/src/main/java/com/predic8/membrane/core/cli/RouterCLI.java, core/src/main/java/com/predic8/membrane/core/kubernetes/KubernetesWatcher.java, core/src/main/java/com/predic8/membrane/core/config/spring/k8s/Envelope.java
Updated imports and call sites to beanregistry types; Router.handleBeanEvent now consumes BeanDefinitionChanged and uses bdc.bd() and bdc.action().is*(); CLI/Kubernetes use BeanCollector/AsyncBeanCollector.
Tests & test utils
annot/src/test/java/com/predic8/membrane/annot/*, annot/src/test/java/com/predic8/membrane/annot/util/*, core/src/test/.../*
Updated imports to annot.beanregistry, adjusted InMemoryClassLoader root-delegation, and adapted tests to new parse/observer/event types.
Build / imports
annot/pom.xml, annot/src/main/java/com/predic8/membrane/annot/bean/BeanFactory.java
Adds SpotBugs annotations dependency and tightens imports (replaces yaml wildcard imports with beanregistry-specific imports).

Sequence Diagram(s)

sequenceDiagram
    participant K8s as KubernetesWatcher
    participant Async as AsyncBeanCollector
    participant Registry as BeanRegistryImplementation
    participant Observer as BeanCacheObserver

    K8s->>Async: create4Kubernetes(event) + isLast flag
    Async->>Async: enqueue ChangeEvent
    Note right of Async `#DDDDFF`: background virtual thread processes queue
    Async->>Registry: handle(ChangeEvent, isLast)
    Registry->>Registry: update BeanContainer map / activation queue
    Registry->>Observer: handleBeanEvent(BeanDefinitionChanged, bean, oldBean)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45–60 minutes

Possibly related PRs

Suggested reviewers

  • christiangoerdes
  • predic8

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'split BeanRegistry interface' accurately reflects the main architectural change: the BeanRegistry interface is refactored into multiple focused responsibilities (BeanCollector for parsing/handling, BeanRegistry for access, BeanContainer for storage, and AsyncBeanCollector for async processing).

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4e4b340 and c11091c.

📒 Files selected for processing (3)
  • annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistryImplementation.java
  • annot/src/test/java/com/predic8/membrane/annot/YAMLBeanParsingTest.java
  • annot/src/test/java/com/predic8/membrane/annot/YAMLComponentsParsingTest.java

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

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

Copy link
Copy Markdown
Contributor

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanDefinition.java (1)

37-40: Null check for kind2 is unnecessary.

JsonNode.asText() never returns null - it returns an empty string "" if the node is missing or null. The check if (kind2 == null) will never be true.

🔎 Proposed fix
-        var kind2 = node.get("kind").asText();
-        if (kind2 == null)
-            kind2 = "api";
-        kind = kind2;
+        var kind2 = node.get("kind");
+        kind = (kind2 == null || kind2.isNull()) ? "api" : kind2.asText();

Alternatively, if "kind" node is always expected to exist:

-        var kind2 = node.get("kind").asText();
-        if (kind2 == null)
-            kind2 = "api";
-        kind = kind2;
+        kind = node.path("kind").asText("api");
🧹 Nitpick comments (6)
annot/src/main/java/com/predic8/membrane/annot/yaml/BeanCacheObserver.java (1)

41-47: Method signature correctly updated to use BeanDefinitionChanged.

The signature change aligns with the new event-driven architecture.

Optional: Consider renaming parameter for clarity

The parameter name bd traditionally suggests "bean definition" but now holds a BeanDefinitionChanged event. Consider event or change for clarity:

-    void handleBeanEvent(BeanDefinitionChanged bd, Object bean, Object oldBean) throws IOException;
+    void handleBeanEvent(BeanDefinitionChanged event, Object bean, Object oldBean) throws IOException;

However, if bd is an established convention in the codebase, keeping it is fine.

annot/src/main/java/com/predic8/membrane/annot/beanregistry/ChangeEvent.java (1)

17-19: Unused import of WatchAction.

The WatchAction import and static import are not used in this file. They may be needed by BeanDefinitionChanged (defined in a separate file), but these imports should be removed from ChangeEvent.java.

🔎 Proposed fix
 package com.predic8.membrane.annot.beanregistry;
 
-import com.predic8.membrane.annot.yaml.WatchAction;
-
-import static com.predic8.membrane.annot.yaml.WatchAction.*;
-
 public sealed interface ChangeEvent permits BeanDefinitionChanged, StaticConfigurationLoaded {
 }
annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistryImplementation.java (3)

140-142: getFirstByName searches by name but bcs is keyed by UID.

This method iterates over all values to find a bean by name, which is O(n). If resolveReference is called frequently, consider maintaining an additional index (e.g., Map<String, BeanContainer> by name) for O(1) lookups.


64-66: Empty start() method - verify if intentional.

The start() method is empty. If this is intentional (lifecycle handled elsewhere), consider adding a brief comment explaining why, or remove the override if not needed by the interface contract.


68-86: Document or enforce single-threaded access to handle() method

The handle() method modifies uidsToActivate (a LinkedHashSet) without synchronization. While bcs and singletonBeans use ConcurrentHashMap, this inconsistency creates a race condition risk if handle() is called concurrently. In production (Kubernetes pattern), AsyncBeanCollector provides protection by serializing calls through a single worker thread. However, direct usage of BeanRegistryImplementation with concurrent event sources would be unsafe. Either synchronize access to uidsToActivate, convert it to a thread-safe collection, or document that this class must be used either through AsyncBeanCollector or with guaranteed single-threaded access to handle().

annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanDefinition.java (1)

19-19: Unused static import.

The static import import static com.predic8.membrane.annot.yaml.WatchAction.*; is not used in this file. The WatchAction type import on line 17 is sufficient for the create4Kubernetes method signature.

🔎 Proposed fix
 import com.predic8.membrane.annot.yaml.WatchAction;
 
-import static com.predic8.membrane.annot.yaml.WatchAction.*;
-
 public class BeanDefinition {
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a42af59 and a85f573.

📒 Files selected for processing (27)
  • annot/pom.xml (1 hunks)
  • annot/src/main/java/com/predic8/membrane/annot/bean/BeanFactory.java (1 hunks)
  • annot/src/main/java/com/predic8/membrane/annot/beanregistry/AsyncBeanCollector.java (1 hunks)
  • annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanCollector.java (1 hunks)
  • annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanContainer.java (1 hunks)
  • annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanDefinition.java (3 hunks)
  • annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanDefinitionChanged.java (1 hunks)
  • annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistry.java (1 hunks)
  • annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistryImplementation.java (1 hunks)
  • annot/src/main/java/com/predic8/membrane/annot/beanregistry/ChangeEvent.java (1 hunks)
  • annot/src/main/java/com/predic8/membrane/annot/yaml/BeanCacheObserver.java (2 hunks)
  • annot/src/main/java/com/predic8/membrane/annot/yaml/BeanRegistryImplementation.java (0 hunks)
  • annot/src/main/java/com/predic8/membrane/annot/yaml/GenericYamlParser.java (2 hunks)
  • annot/src/main/java/com/predic8/membrane/annot/yaml/ParsingContext.java (1 hunks)
  • annot/src/main/java/com/predic8/membrane/annot/yaml/WatchAction.java (1 hunks)
  • annot/src/test/java/com/predic8/membrane/annot/YAMLBeanParsingTest.java (1 hunks)
  • annot/src/test/java/com/predic8/membrane/annot/YAMLComponentsParsingTest.java (1 hunks)
  • annot/src/test/java/com/predic8/membrane/annot/util/CompilerHelper.java (1 hunks)
  • annot/src/test/java/com/predic8/membrane/annot/util/InMemoryClassLoader.java (1 hunks)
  • annot/src/test/java/com/predic8/membrane/annot/util/StructureAssertionUtil.java (1 hunks)
  • annot/src/test/java/com/predic8/membrane/annot/util/YamlParser.java (3 hunks)
  • core/src/main/java/com/predic8/membrane/core/Router.java (3 hunks)
  • core/src/main/java/com/predic8/membrane/core/cli/RouterCLI.java (2 hunks)
  • core/src/main/java/com/predic8/membrane/core/config/spring/k8s/Envelope.java (1 hunks)
  • core/src/main/java/com/predic8/membrane/core/kubernetes/KubernetesWatcher.java (4 hunks)
  • core/src/test/java/com/predic8/membrane/core/config/spring/k8s/EnvelopeTest.java (1 hunks)
  • core/src/test/java/com/predic8/membrane/core/kubernetes/GenericYamlParserTest.java (1 hunks)
💤 Files with no reviewable changes (1)
  • annot/src/main/java/com/predic8/membrane/annot/yaml/BeanRegistryImplementation.java
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-12-19T09:01:40.311Z
Learnt from: rrayst
Repo: membrane/api-gateway PR: 2441
File: annot/pom.xml:0-0
Timestamp: 2025-12-19T09:01:40.311Z
Learning: In annot/pom.xml, ensure log4j dependencies log4j-slf4j2-impl and log4j-core have <scope>test</scope>. In the distribution module (separate pom.xml), these dependencies should use the normal compile-scope. This guidance applies to all pom.xml files under the annot and distribution module structure where these dependencies appear; verify both modules are configured accordingly to reflect testing vs. runtime usage.

Applied to files:

  • annot/pom.xml
📚 Learning: 2025-09-22T19:49:29.473Z
Learnt from: predic8
Repo: membrane/api-gateway PR: 2156
File: pom.xml:0-0
Timestamp: 2025-09-22T19:49:29.473Z
Learning: In the Membrane API Gateway project, jackson-annotations is pinned to version "2.20" instead of using ${jackson.version} (2.20.0) because version 2.20.0 is not available in Maven repository yet for jackson-annotations, while it is available for jackson-core and jackson-databind. This version inconsistency is intentional and necessary due to different release schedules between Jackson modules.

Applied to files:

  • core/src/main/java/com/predic8/membrane/core/kubernetes/KubernetesWatcher.java
🧬 Code graph analysis (6)
core/src/test/java/com/predic8/membrane/core/kubernetes/GenericYamlParserTest.java (1)
annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanDefinition.java (1)
  • BeanDefinition (21-103)
annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistryImplementation.java (3)
annot/src/main/java/com/predic8/membrane/annot/bean/BeanFactory.java (1)
  • BeanFactory (31-252)
annot/src/main/java/com/predic8/membrane/annot/yaml/GenericYamlParser.java (1)
  • GenericYamlParser (40-299)
annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanContainer.java (1)
  • BeanContainer (5-28)
annot/src/main/java/com/predic8/membrane/annot/yaml/GenericYamlParser.java (2)
annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanDefinition.java (1)
  • BeanDefinition (21-103)
annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistryImplementation.java (1)
  • BeanRegistryImplementation (28-165)
annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanCollector.java (1)
annot/src/main/java/com/predic8/membrane/annot/yaml/GenericYamlParser.java (1)
  • GenericYamlParser (40-299)
core/src/main/java/com/predic8/membrane/core/Router.java (1)
annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanDefinition.java (1)
  • BeanDefinition (21-103)
core/src/main/java/com/predic8/membrane/core/cli/RouterCLI.java (1)
annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistryImplementation.java (1)
  • BeanRegistryImplementation (28-165)
⏰ 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). (2)
  • GitHub Check: Automated tests
  • GitHub Check: Analyze (java)
🔇 Additional comments (32)
annot/src/test/java/com/predic8/membrane/annot/util/InMemoryClassLoader.java (1)

114-114: LGTM! Package reference updated correctly.

The string literal correctly reflects the new package location for BeanRegistry.

annot/src/test/java/com/predic8/membrane/annot/util/StructureAssertionUtil.java (1)

17-17: LGTM! Import updated for package refactoring.

The import correctly reflects the relocated BeanRegistry interface.

annot/src/main/java/com/predic8/membrane/annot/yaml/ParsingContext.java (1)

18-18: LGTM! Import updated for package refactoring.

The import correctly reflects the relocated BeanRegistry interface.

core/src/test/java/com/predic8/membrane/core/config/spring/k8s/EnvelopeTest.java (1)

27-27: LGTM! Import updated for package refactoring.

The import correctly reflects the relocated BeanRegistry interface. Note that this test is currently disabled (Line 40) with a TODO to rewrite to new parsing.

annot/src/test/java/com/predic8/membrane/annot/YAMLBeanParsingTest.java (1)

17-17: LGTM! Import updated for package refactoring.

The import correctly reflects the relocated BeanRegistry interface.

annot/src/test/java/com/predic8/membrane/annot/util/CompilerHelper.java (1)

16-16: LGTM! Improved import specificity.

Replacing the wildcard import with a specific import for BeanRegistry is a good practice that improves code clarity and aligns with the package refactoring.

core/src/test/java/com/predic8/membrane/core/kubernetes/GenericYamlParserTest.java (1)

18-19: LGTM! Imports updated for package refactoring.

Both imports correctly reflect the new bean registry architecture:

  • BeanDefinition is now a separate class in the beanregistry package
  • BeanRegistry has been relocated to the beanregistry package

These changes align with the TestRegistry implementation (line 346) which uses BeanDefinition in its method signature.

annot/pom.xml (1)

59-63: SpotBugs annotations version 4.9.8 is current and has no known security vulnerabilities.

The version specified is the latest available release and is appropriate for use.

annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistry.java (1)

14-28: LGTM! Clean interface simplification.

The package relocation and API reduction align well with the PR objectives. The interface now has a focused contract with just the essential methods.

annot/src/main/java/com/predic8/membrane/annot/bean/BeanFactory.java (1)

18-18: LGTM! Import correctly updated.

The import path update aligns with the BeanRegistry relocation to the beanregistry package.

annot/src/main/java/com/predic8/membrane/annot/yaml/BeanCacheObserver.java (1)

17-20: LGTM! Imports correctly added.

The new imports support the updated event model using BeanDefinitionChanged.

core/src/main/java/com/predic8/membrane/core/config/spring/k8s/Envelope.java (1)

19-19: LGTM! Import correctly updated.

The import path reflects the BeanRegistry relocation to the beanregistry package.

annot/src/main/java/com/predic8/membrane/annot/yaml/WatchAction.java (1)

17-30: LGTM! Excellent addition of semantic predicates.

The predicate methods (isDeleted(), isModified(), isAdded()) improve code readability and provide a cleaner API compared to direct enum comparisons.

annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanDefinitionChanged.java (1)

1-11: LGTM! Clean event wrapper design.

The record-based implementation is appropriate for this immutable event type, and the design clearly separates the action from the definition data.

annot/src/test/java/com/predic8/membrane/annot/YAMLComponentsParsingTest.java (1)

18-18: LGTM! Import correctly updated.

The import update aligns with the BeanRegistry relocation, and the test logic remains unchanged.

annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanContainer.java (1)

5-28: LGTM! Simple container class with appropriate visibility guarantees.

The volatile modifier on singleton ensures proper visibility across threads. The class serves as a straightforward container for bean lifecycle management.

core/src/main/java/com/predic8/membrane/core/kubernetes/KubernetesWatcher.java (4)

17-21: LGTM!

The imports are correctly updated to use the new beanregistry package structure, reflecting the refactored architecture.


41-52: LGTM!

The refactoring properly separates grammar from the bean registry and introduces async event handling via AsyncBeanCollector. The initialization order is correct: grammar first, then the synchronous registry, then the async wrapper.


64-64: LGTM!

Direct access to grammar.getCrdSingularNames() is cleaner than the previous indirection through the bean registry.


107-117: Verify isLast=true for every Kubernetes event.

Each Kubernetes watch event passes isLast=true to handle(). This is likely intentional since K8s events arrive individually and should trigger immediate processing, but confirm this aligns with the expected batch semantics of AsyncBeanCollector.

annot/src/main/java/com/predic8/membrane/annot/yaml/GenericYamlParser.java (2)

94-116: LGTM!

The refactoring to return List<BeanDefinition> instead of a BeanRegistry cleanly separates parsing from registry management. This enables the new event-driven architecture where callers can emit change events for each definition.


23-25: Remove unused import BeanRegistryImplementation.

BeanRegistryImplementation (line 25) is not used in this file. While BeanRegistry (line 24) is used as a parameter type on line 147 and should be kept, BeanRegistryImplementation can be safely removed.

Likely an incorrect or invalid review comment.

core/src/main/java/com/predic8/membrane/core/Router.java (2)

18-19: LGTM!

Imports correctly added for the new event types from the beanregistry package.


654-677: LGTM!

The method correctly adapts to the new BeanDefinitionChanged event type. Access patterns via bdc.bd() for the bean definition and bdc.action().isAdded()/isDeleted()/isModified() for action predicates are clean and readable.

annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanCollector.java (2)

22-29: LGTM!

The parseYamls default method provides a clean convenience flow:

  1. Parse YAML to bean definitions
  2. Emit ADDED events with proper isLast tracking
  3. Emit StaticConfigurationLoaded as the final event
  4. Call start() to begin processing

The isLast flag correctly identifies the last BeanDefinitionChanged event in the loop, and StaticConfigurationLoaded is appropriately marked as the final event before starting.


31-40: LGTM!

The abstract method declarations establish a clear contract. The isLast parameter documentation is helpful for implementers to understand batch completion semantics.

annot/src/test/java/com/predic8/membrane/annot/util/YamlParser.java (2)

51-53: LGTM! Clean two-step initialization pattern.

The refactored initialization correctly creates the BeanRegistryImplementation, calls parseYamls on it, and then assigns it to the beanRegistry field. This aligns with the new collector-based architecture.


85-85: Callback signature correctly updated.

The handleBeanEvent method signature now accepts BeanDefinitionChanged instead of BeanDefinition, aligning with the new event-driven model.

annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistryImplementation.java (1)

49-62: LGTM! Clean bean instantiation logic.

The define method correctly distinguishes between "bean" kind (using BeanFactory) and other kinds (using GenericYamlParser), with proper exception handling.

annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanDefinition.java (1)

48-50: LGTM! Clean factory method for Kubernetes integration.

The create4Kubernetes factory method properly encapsulates the creation of a BeanDefinitionChanged event from a WatchAction and JsonNode, maintaining separation of concerns.

core/src/main/java/com/predic8/membrane/core/cli/RouterCLI.java (1)

172-173: The code is correctly implemented. The parseYamls method is a default method in the BeanCollector interface that handles the complete lifecycle internally: it parses the YAML, processes the bean definitions, and calls start() at the end (BeanCollector.java, lines 22-28). The variable does not need to be used after the call, and no explicit start() invocation is required—it's already handled by parseYamls.

annot/src/main/java/com/predic8/membrane/annot/beanregistry/ChangeEvent.java (1)

28-28: No changes needed. The package-private visibility of StaticConfigurationLoaded is correct and follows the sealed class design pattern, where permitted subclasses need not be public even when implementing a public sealed interface. The record is not used externally.

Copy link
Copy Markdown
Contributor

@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

🧹 Nitpick comments (3)
annot/src/main/java/com/predic8/membrane/annot/beanregistry/AsyncBeanCollector.java (2)

31-39: Consider while (!Thread.currentThread().isInterrupted()) and restoring interrupt flag.

The loop condition while (true) works but while (!Thread.currentThread().isInterrupted()) is more idiomatic. Also, when catching InterruptedException, best practice is to restore the interrupt flag before breaking.

🔎 Proposed improvement
         t = Thread.ofVirtual().start(() -> {
-            while (true) {
+            while (!Thread.currentThread().isInterrupted()) {
                 try {
                     ChangeEvent changeEvent = changeEvents.take();
                     delegate.handle(changeEvent, changeEvents.isEmpty());
                 } catch (InterruptedException e) {
+                    Thread.currentThread().interrupt();
                     break;
                 }
             }
         });

10-41: Missing stop() method for graceful shutdown.

There's no way to stop the background thread. Consider adding a stop() method to interrupt the thread and allow clean shutdown, especially important for testing and application lifecycle management.

🔎 Proposed addition
public synchronized void stop() {
    if (t != null) {
        t.interrupt();
        t = null;
    }
}
annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistryImplementation.java (1)

59-61: Generic exception catch loses context.

Catching Exception and wrapping in a bare RuntimeException discards the original exception type and any semantic meaning. Consider using a more specific exception or preserving context.

🔎 Proposed improvement
         } catch (Exception e) {
-            throw new RuntimeException(e);
+            throw new RuntimeException("Failed to define bean: " + bd.getUid(), e);
         }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a85f573 and 4e4b340.

📒 Files selected for processing (2)
  • annot/src/main/java/com/predic8/membrane/annot/beanregistry/AsyncBeanCollector.java
  • annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistryImplementation.java
🧰 Additional context used
🧬 Code graph analysis (1)
annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistryImplementation.java (4)
annot/src/main/java/com/predic8/membrane/annot/generator/kubernetes/Grammar.java (1)
  • Grammar (33-190)
annot/src/main/java/com/predic8/membrane/annot/bean/BeanFactory.java (1)
  • BeanFactory (31-252)
annot/src/main/java/com/predic8/membrane/annot/yaml/GenericYamlParser.java (1)
  • GenericYamlParser (40-299)
annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanContainer.java (1)
  • BeanContainer (5-28)
⏰ 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: Analyze (java)
🔇 Additional comments (3)
annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistryImplementation.java (3)

106-110: Exception during activation aborts remaining beans.

When one bean fails to activate, the exception is logged and re-thrown, which stops processing all remaining beans in uidsToActivate. Consider whether partial activation should be allowed, or at minimum ensure uidsToRemove is applied before rethrowing.

Currently, successfully processed beans (in uidsToRemove) are never removed from uidsToActivate if a later bean fails. This could lead to duplicate processing on retry.


64-66: Empty start() method - intentional placeholder?

The start() method is empty. If this is intentional (e.g., this implementation doesn't need startup logic), consider adding a brief comment explaining this. Otherwise, ensure any required initialization is added.


112-113: Previous type mismatch bug is fixed.

The removal loop now correctly iterates over UidAction objects and removes them from the Set<UidAction>, addressing the previous review concern about type mismatch.

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.

3 participants