Skip to content

Conversation

@mxsm
Copy link
Owner

@mxsm mxsm commented Jan 7, 2026

Which Issue(s) This PR Fixes(Closes)

Fixes #5525

Brief Description

How Did You Test This Change?

Summary by CodeRabbit

  • Refactor
    • Updated controller initialization to use configuration-based approach instead of runtime-based initialization, improving the abstraction layer and internal architecture.

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

@rocketmq-rust-bot
Copy link
Collaborator

🔊@mxsm 🚀Thanks for your contribution🎉!

💡CodeRabbit(AI) will review your code first🔥!

Note

🚨The code review suggestions from CodeRabbit are to be used as a reference only, and the PR submitter can decide whether to make changes based on their own judgment. Ultimately, the project management personnel will conduct the final code review💥.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 7, 2026

Walkthrough

This pull request refactors the controller architecture to replace the RocketMQRuntime dependency with ControllerConfig. The changes remove the get_runtime public method from the Controller trait and its implementations, update constructor signatures to accept config instead of runtime, and adjust initialization logic across multiple controller components to use configuration-driven setup.

Changes

Cohort / File(s) Summary
Controller trait and mock
rocketmq-controller/src/controller.rs
Removes get_runtime(&self) -> Arc<RocketMQRuntime> method from Controller trait; removes corresponding MockController implementation and RocketMQRuntime import.
OpenRaftController refactoring
rocketmq-controller/src/controller/open_raft_controller.rs
Replaces runtime: Arc<RocketMQRuntime> field with config: Arc<ControllerConfig>; constructor signature changed to new(config: Arc<ControllerConfig>); startup now initializes RaftNodeManager with config and starts gRPC server asynchronously; removes get_runtime method.
RaftController and factory method
rocketmq-controller/src/controller/raft_controller.rs
Updates new_open_raft signature from new_open_raft(runtime: Arc<RocketMQRuntime>) to new_open_raft(config: Arc<ControllerConfig>); adds ControllerConfig import; removes get_runtime helper method.
RaftRsController implementation
rocketmq-controller/src/controller/raft_rs_controller.rs
Removes get_runtime(&self) -> Arc<RocketMQRuntime> method from Controller implementation.
ControllerManager initialization
rocketmq-controller/src/controller/controller_manager.rs
Removes RocketMQRuntime initialization; updates new_open_raft call to pass Arc::clone(&config) instead of runtime instance.
Test updates
rocketmq-controller/tests/raft_controller_test.rs
Updates tests to use ControllerConfig::test_config() instead of runtime construction; adjusts new_open_raft calls to pass config; removes runtime lifecycle management from test flows.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 The runtime once ruled our code with might,
But config brings structure, clear and bright,
We hop toward simplicity, clean and lean,
Where dependencies vanish—a refactored dream! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: refactoring the controller to remove RocketMQRuntime dependency and use ControllerConfig instead, which aligns with all file modifications.
Linked Issues check ✅ Passed The pull request successfully implements the objective from issue #5525: removing RocketMQRuntime dependency throughout the controller codebase and replacing it with ControllerConfig.
Out of Scope Changes check ✅ Passed All changes are directly related to the stated objective of refactoring the controller to remove RocketMQRuntime dependency and use ControllerConfig; no unrelated modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom Pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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
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: 1

🤖 Fix all issues with AI agents
In @rocketmq-controller/src/controller/open_raft_controller.rs:
- Around line 50-64: The startup() function creates a RaftNodeManager and spawns
the gRPC server but never stores the RaftNodeManager or a shutdown handle,
preventing later access and graceful shutdown; modify the struct backing this
controller to hold an Option<Arc<RaftNodeManager>> (or a field like node_mgr)
and a oneshot or watch sender for shutdown (e.g., shutdown_tx), then in
startup() assign the created Arc<RaftNodeManager> into that field instead of
letting it drop, and replace Server::builder().serve(...) with
Server::builder().serve_with_shutdown(self.config.listen_addr, async move {
shutdown_rx.await.ok(); }) (or store the JoinHandle/abort handle) so shutdown()
can signal the stored sender (or abort the handle) to stop the server and
preserve access to RaftNodeManager via the stored node_mgr.
🧹 Nitpick comments (3)
rocketmq-controller/src/controller/controller_manager.rs (1)

145-150: Consider removing the commented-out runtime initialization.

The commented-out runtime line is dead code after the refactoring. Leaving it in place adds noise and may cause confusion for future maintainers. Since the refactoring is intentional, the commented code should be removed entirely.

🔎 Proposed fix
-        // Initialize RocketMQ runtime for Raft controller
-        //let runtime = Arc::new(RocketMQRuntime::new_multi(2, "controller-runtime"));
-
         // Initialize Raft controller for leader election
         // This MUST succeed before proceeding
         // Using OpenRaft implementation by default
         let raft_arc = Arc::new(RaftController::new_open_raft(Arc::clone(&config)));
rocketmq-controller/src/controller.rs (1)

600-603: Remove commented-out get_runtime method.

This commented-out code is now obsolete after the refactoring. Remove it to keep the codebase clean.

🔎 Proposed fix
     fn register_broker_lifecycle_listener(&self, _listener: Arc<dyn BrokerLifecycleListener>) {
         // No-op
     }
-
-    /*    fn get_runtime(&self) -> Arc<RocketMQRuntime> {
-        unimplemented!("MockController does not provide runtime in tests")
-    }*/
 }
rocketmq-controller/src/controller/open_raft_controller.rs (1)

58-62: Use tracing::error! instead of eprintln! for consistency.

The rest of the codebase uses tracing for logging. Using eprintln! here is inconsistent and won't integrate with the logging infrastructure.

🔎 Proposed fix
+use tracing::error;
+
         tokio::spawn(async move {
             if let Err(e) = server.await {
-                eprintln!("gRPC server error for node {}: {}", node_id_for_error, e);
+                error!("gRPC server error for node {}: {}", node_id_for_error, e);
             }
         });
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 74cc28c and 8163132.

📒 Files selected for processing (6)
  • rocketmq-controller/src/controller.rs
  • rocketmq-controller/src/controller/controller_manager.rs
  • rocketmq-controller/src/controller/open_raft_controller.rs
  • rocketmq-controller/src/controller/raft_controller.rs
  • rocketmq-controller/src/controller/raft_rs_controller.rs
  • rocketmq-controller/tests/raft_controller_test.rs
💤 Files with no reviewable changes (1)
  • rocketmq-controller/src/controller/raft_rs_controller.rs
🧰 Additional context used
🧬 Code graph analysis (3)
rocketmq-controller/src/controller/controller_manager.rs (4)
rocketmq-controller/src/controller/open_raft_controller.rs (1)
  • new (44-46)
rocketmq-controller/src/controller/raft_rs_controller.rs (1)
  • new (41-43)
rocketmq-common/src/common/controller/controller_config.rs (1)
  • new (257-259)
rocketmq-controller/src/controller/raft_controller.rs (1)
  • new_open_raft (51-53)
rocketmq-controller/src/controller/open_raft_controller.rs (2)
rocketmq-controller/src/controller/controller_manager.rs (2)
  • controller (620-622)
  • config (575-577)
rocketmq-controller/src/controller/raft_controller.rs (1)
  • startup (62-67)
rocketmq-controller/src/controller/raft_controller.rs (3)
rocketmq-controller/src/controller/controller_manager.rs (3)
  • controller (620-622)
  • config (575-577)
  • new (139-211)
rocketmq-controller/src/controller/open_raft_controller.rs (1)
  • new (44-46)
rocketmq-controller/src/controller/raft_rs_controller.rs (1)
  • new (41-43)
⏰ 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). (5)
  • GitHub Check: Build & Test (ubuntu-latest)
  • GitHub Check: Build & Test (macos-latest)
  • GitHub Check: Build & Test (windows-latest)
  • GitHub Check: Code Coverage
  • GitHub Check: auto-approve
🔇 Additional comments (4)
rocketmq-controller/tests/raft_controller_test.rs (2)

22-30: LGTM!

The test correctly uses ControllerConfig::test_config() for OpenRaft initialization, aligning with the config-driven approach. The lifecycle test properly verifies startup, leadership status, and shutdown.


52-78: LGTM!

The wrapper test correctly differentiates between OpenRaft (config-based) and RaftRs (runtime-based) initialization, properly testing both controller variants with their respective dependencies.

rocketmq-controller/src/controller/raft_controller.rs (1)

49-58: LGTM!

The new_open_raft constructor signature change from Arc<RocketMQRuntime> to Arc<ControllerConfig> properly implements the config-driven initialization. The asymmetric design is correct: OpenRaft uses config while RaftRs continues to use runtime, allowing flexibility in implementation approaches.

rocketmq-controller/src/controller/open_raft_controller.rs (1)

38-47: LGTM on the config-driven initialization.

The struct and constructor correctly implement the config-based approach as intended by the refactoring. The Arc<ControllerConfig> is properly stored and cloned where needed.

Comment on lines 50 to 64
async fn startup(&self) -> RocketMQResult<()> {
// TODO: Initialize OpenRaft node
let node = Arc::new(RaftNodeManager::new(Arc::clone(&self.config)).await?);
let service = GrpcRaftService::new(node.raft());
let server = Server::builder()
.add_service(OpenRaftServiceServer::new(service))
.serve(self.config.listen_addr);

let node_id_for_error = self.config.node_id;
tokio::spawn(async move {
if let Err(e) = server.await {
eprintln!("gRPC server error for node {}: {}", node_id_for_error, e);
}
});
Ok(())
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Missing storage of RaftNodeManager and shutdown handle.

The node and gRPC server handle are not stored, which creates two issues:

  1. RaftNodeManager lifecycle: The node is created but only passed to the service. If the manager holds important state beyond the Raft handle, it may not be accessible later.

  2. No graceful shutdown: The spawned gRPC server has no shutdown mechanism. The shutdown() method (line 66-68) cannot stop the server because there's no handle stored.

Consider storing the RaftNodeManager and using tonic's Server::serve_with_shutdown or storing a shutdown signal sender.

🔎 Proposed approach
 pub struct OpenRaftController {
     config: Arc<ControllerConfig>,
+    node: Option<Arc<RaftNodeManager>>,
+    shutdown_tx: Option<tokio::sync::oneshot::Sender<()>>,
 }

 impl OpenRaftController {
     pub fn new(config: Arc<ControllerConfig>) -> Self {
-        Self { config }
+        Self { config, node: None, shutdown_tx: None }
     }
 }

Then in startup(), store the node and use serve_with_shutdown for graceful termination.

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

🤖 Prompt for AI Agents
In @rocketmq-controller/src/controller/open_raft_controller.rs around lines 50 -
64, The startup() function creates a RaftNodeManager and spawns the gRPC server
but never stores the RaftNodeManager or a shutdown handle, preventing later
access and graceful shutdown; modify the struct backing this controller to hold
an Option<Arc<RaftNodeManager>> (or a field like node_mgr) and a oneshot or
watch sender for shutdown (e.g., shutdown_tx), then in startup() assign the
created Arc<RaftNodeManager> into that field instead of letting it drop, and
replace Server::builder().serve(...) with
Server::builder().serve_with_shutdown(self.config.listen_addr, async move {
shutdown_rx.await.ok(); }) (or store the JoinHandle/abort handle) so shutdown()
can signal the stored sender (or abort the handle) to stop the server and
preserve access to RaftNodeManager via the stored node_mgr.

@codecov
Copy link

codecov bot commented Jan 7, 2026

Codecov Report

❌ Patch coverage is 81.25000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 38.41%. Comparing base (74cc28c) to head (8163132).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...-controller/src/controller/open_raft_controller.rs 76.92% 3 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #5526   +/-   ##
=======================================
  Coverage   38.40%   38.41%           
=======================================
  Files         815      815           
  Lines      110515   110512    -3     
=======================================
+ Hits        42443    42452    +9     
+ Misses      68072    68060   -12     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Collaborator

@rocketmq-rust-bot rocketmq-rust-bot left a comment

Choose a reason for hiding this comment

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

LGTM - All CI checks passed ✅

@rocketmq-rust-bot rocketmq-rust-bot merged commit d37420f into main Jan 7, 2026
20 checks passed
@rocketmq-rust-bot rocketmq-rust-bot added approved PR has approved and removed ready to review waiting-review waiting review this PR labels Jan 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI review first Ai review pr first approved PR has approved auto merge refactor♻️ refactor code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Refactor♻️] Refactor controller to remove RocketMQRuntime dependency and use ControllerConfig instead

4 participants