Skip to content

[ISSUE #6391]🚀Implement ExportMetadataInRocksDB Command in rocketmq-admin-core#6516

Merged
mxsm merged 1 commit intomxsm:mainfrom
WaterWhisperer:feat-6391
Feb 27, 2026
Merged

[ISSUE #6391]🚀Implement ExportMetadataInRocksDB Command in rocketmq-admin-core#6516
mxsm merged 1 commit intomxsm:mainfrom
WaterWhisperer:feat-6391

Conversation

@WaterWhisperer
Copy link
Contributor

@WaterWhisperer WaterWhisperer commented Feb 25, 2026

Which Issue(s) This PR Fixes(Closes)

Brief Description

How Did You Test This Change?

Summary by CodeRabbit

  • New Features
    • Added an exportMetadataInRocksDB command to export topic and subscription-group configurations directly from RocksDB.
    • Export supports JSON (structured) and plain-text formats, targets either topics or subscriptionGroups, and accepts a path plus an optional JSON output flag with input validation.

@rocketmq-rust-bot
Copy link
Collaborator

🔊@WaterWhisperer 🚀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💥.

@rocketmq-rust-robot rocketmq-rust-robot added the feature🚀 Suggest an idea for this project. label Feb 25, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 25, 2026

Walkthrough

Adds a new RocksDB-backed export command exportMetadataInRocksDB: dependency added, command registered, and a subcommand implemented to read a RocksDB path and export topic or subscriptionGroup entries in JSON or plain-text formats.

Changes

Cohort / File(s) Summary
Dependency
rocketmq-tools/rocketmq-admin/rocketmq-admin-core/Cargo.toml
Added rocksdb = "0.24" dependency.
Command Registration
rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands.rs, rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands/export.rs
Registered exportMetadataInRocksDB in command list; added ExportMetadataInRocksDB enum variant and execution match arm; module import wired.
RocksDB Export Subcommand
rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands/export/export_metadata_in_rocks_db_sub_command.rs
New ExportMetadataInRocksDBSubCommand: CLI args (path, config_type, json_enable), opens RocksDB read-only, iterates KV entries, supports JSON pretty output or plain-text listing, adds iteration and handler helpers, and implements CommandExecute.

Sequence Diagram

sequenceDiagram
    participant User as User
    participant CLI as CLI Parser
    participant Cmd as ExportCmd
    participant DB as RocksDB
    participant Formatter as OutputFormatter

    User->>CLI: invoke exportMetadataInRocksDB(path, type, json)
    CLI->>Cmd: execute(subcommand)
    Cmd->>Cmd: validate(path, config_type)
    Cmd->>DB: open(path, read-only)
    DB-->>Cmd: db_handle
    Cmd->>DB: iterate_kv_store()
    loop for each KV
        DB-->>Cmd: (key, value)
        Cmd->>Cmd: parse/collect entry
    end
    Cmd->>Formatter: handle_export_metadata(entries, json_enable)
    Formatter-->>CLI: formatted output (JSON or plain text)
    CLI-->>User: display output
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • TeslaRustor
  • SpaceXCN
  • rocketmq-rust-bot

Poem

🐰 I nibble through RocksDB lanes,

Keys and values caught in my paws,
JSON or plain, I print the gains,
Topics and groups — no hidden laws,
Hoppy exports, applause! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main change: implementing the ExportMetadataInRocksDB command in rocketmq-admin-core, which matches the primary objective of this PR.
Linked Issues check ✅ Passed The PR implements the core ExportMetadataInRocksDB command with required parameters (path, config_type, json_enable), RocksDB integration, and both plain and JSON output formats as specified in issue #6391.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the ExportMetadataInRocksDB command: dependency addition, command registration, subcommand routing, and core implementation.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

🧹 Nitpick comments (3)
rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands/export/export_metadata_in_rocks_db_sub_command.rs (2)

119-140: Validate config_type before constructing the full path.

Currently, the full path is built at line 126 before config_type is validated at line 132. Reordering to validate first is cleaner fail-fast logic and avoids constructing a path that will never be used for invalid input.

Proposed reorder
         let path = self.path.trim();
         if path.is_empty() || !std::path::Path::new(path).exists() {
             println!("RocksDB path is invalid.");
             return Ok(());
         }

         let config_type = self.config_type.trim();
+        if !config_type.eq_ignore_ascii_case(TOPICS_JSON_CONFIG)
+            && !config_type.eq_ignore_ascii_case(SUBSCRIPTION_GROUP_JSON_CONFIG)
+        {
+            println!(
+                "Invalid config type={}, Options: topics,subscriptionGroups",
+                config_type
+            );
+            return Ok(());
+        }
+
         let full_path = if path.ends_with('/') {
             format!("{}{}", path, config_type)
         } else {
             format!("{}/{}", path, config_type)
         };

-        if !config_type.eq_ignore_ascii_case(TOPICS_JSON_CONFIG)
-            && !config_type.eq_ignore_ascii_case(SUBSCRIPTION_GROUP_JSON_CONFIG)
-        {
-            println!(
-                "Invalid config type={}, Options: topics,subscriptionGroups",
-                config_type
-            );
-            return Ok(());
-        }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands/export/export_metadata_in_rocks_db_sub_command.rs`
around lines 119 - 140, Validate config_type (the trimmed self.config_type
against TOPICS_JSON_CONFIG and SUBSCRIPTION_GROUP_JSON_CONFIG) before building
full_path; keep the existing path trimming and existence check for self.path,
then perform the config_type eq_ignore_ascii_case checks and early return on
invalid type, and only after passing validation construct full_path (using the
current path.ends_with('/') logic) so you avoid creating a path for invalid
config types.

119-123: Validation errors return Ok(()) — callers cannot distinguish success from failure.

When the path is invalid (line 121) or the config type is unrecognized (line 136), the command prints a message but returns Ok(()). If this CLI is ever invoked programmatically or in scripts checking exit codes, these silent failures will be indistinguishable from a successful export. Consider returning an Err(...) for these cases instead, similar to the RocksDB open failure on line 145-148.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands/export/export_metadata_in_rocks_db_sub_command.rs`
around lines 119 - 123, The validation branch that checks the RocksDB path using
self.path.trim() currently prints "RocksDB path is invalid." and returns Ok(()),
and similarly an unrecognized config type path prints a message then returns
Ok(()); change both branches to return an Err(...) instead so callers can detect
failure (mirror the existing RocksDB open failure behavior used around the
rocksdb::DB::open call). Locate the path validation and the config-type match in
export_metadata_in_rocks_db_sub_command (the blocks around self.path.trim() and
the config-type branch) and replace the silent Ok(()) returns with an
appropriate Err using the command’s error type (the same error/format used for
the RocksDB open failure) and include a clear error message describing the
invalid path or unknown config type.
rocketmq-tools/rocketmq-admin/rocketmq-admin-core/Cargo.toml (1)

52-52: Consider feature-gating the rocksdb dependency.

rocksdb is a heavy native dependency (requires C++ compilation via librocksdb-sys), significantly increasing build times and binary size. Since the export functionality is incomplete (unimplemented in several methods), feature-gating it behind a Cargo feature (e.g., rocksdb-export) would avoid imposing the build cost on users who don't need it. This approach aligns with how rocksdb is already feature-gated in other crates within the project (rocketmq-store and rocketmq-controller).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rocketmq-tools/rocketmq-admin/rocketmq-admin-core/Cargo.toml` at line 52, The
Cargo.toml currently lists rocksdb = "0.24" unconditionally; make it optional
and behind a new feature (e.g., "rocksdb-export") by changing the dependency to
rocksdb = { version = "0.24", optional = true } and adding a [features] section
with rocksdb-export = ["rocksdb"]; then gate the code that references RocksDB
(export-related modules/functions) with #[cfg(feature = "rocksdb-export")] or
#[cfg_attr(not(feature = "rocksdb-export"), allow(dead_code))] and #[cfg(feature
= "rocksdb-export")] on functions/classes that call into RocksDB so the crate
builds without rocksdb unless the feature is enabled; ensure any downstream
crates that need it enable the feature explicitly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands.rs`:
- Around line 362-367: The remark string for the Command with command
"exportMetadataInRocksDB" currently uses a backslash line-continuation which
preserves leading whitespace from the next line and produces extra gap; edit the
Command initializer so the remark is a single logical string without the
backslash-induced leading spaces (e.g., put the entire remark on one line or use
explicit string concatenation/formatting) so the rendered table cell reads
"...use [mqadmin rocksDBConfigToJson]" correctly; update the remark field in
that Command entry accordingly.

In
`@rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands/export/export_metadata_in_rocks_db_sub_command.rs`:
- Around line 126-130: The code builds full_path by manually concatenating path
and config_type (variables full_path, path, config_type) which is fragile;
replace this logic with PathBuf usage: convert path into a PathBuf, call
.join(config_type) to produce the combined path, and then use .to_string_lossy()
or .into_os_string() as needed for downstream uses to preserve cross-platform
correctness and avoid manual slash handling.

---

Nitpick comments:
In `@rocketmq-tools/rocketmq-admin/rocketmq-admin-core/Cargo.toml`:
- Line 52: The Cargo.toml currently lists rocksdb = "0.24" unconditionally; make
it optional and behind a new feature (e.g., "rocksdb-export") by changing the
dependency to rocksdb = { version = "0.24", optional = true } and adding a
[features] section with rocksdb-export = ["rocksdb"]; then gate the code that
references RocksDB (export-related modules/functions) with #[cfg(feature =
"rocksdb-export")] or #[cfg_attr(not(feature = "rocksdb-export"),
allow(dead_code))] and #[cfg(feature = "rocksdb-export")] on functions/classes
that call into RocksDB so the crate builds without rocksdb unless the feature is
enabled; ensure any downstream crates that need it enable the feature
explicitly.

In
`@rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands/export/export_metadata_in_rocks_db_sub_command.rs`:
- Around line 119-140: Validate config_type (the trimmed self.config_type
against TOPICS_JSON_CONFIG and SUBSCRIPTION_GROUP_JSON_CONFIG) before building
full_path; keep the existing path trimming and existence check for self.path,
then perform the config_type eq_ignore_ascii_case checks and early return on
invalid type, and only after passing validation construct full_path (using the
current path.ends_with('/') logic) so you avoid creating a path for invalid
config types.
- Around line 119-123: The validation branch that checks the RocksDB path using
self.path.trim() currently prints "RocksDB path is invalid." and returns Ok(()),
and similarly an unrecognized config type path prints a message then returns
Ok(()); change both branches to return an Err(...) instead so callers can detect
failure (mirror the existing RocksDB open failure behavior used around the
rocksdb::DB::open call). Locate the path validation and the config-type match in
export_metadata_in_rocks_db_sub_command (the blocks around self.path.trim() and
the config-type branch) and replace the silent Ok(()) returns with an
appropriate Err using the command’s error type (the same error/format used for
the RocksDB open failure) and include a clear error message describing the
invalid path or unknown config type.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7616f22 and 031a50e.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • rocketmq-tools/rocketmq-admin/rocketmq-admin-core/Cargo.toml
  • rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands.rs
  • rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands/export.rs
  • rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands/export/export_metadata_in_rocks_db_sub_command.rs

@codecov
Copy link

codecov bot commented Feb 25, 2026

Codecov Report

❌ Patch coverage is 0% with 74 lines in your changes missing coverage. Please review.
✅ Project coverage is 42.06%. Comparing base (25d5c5b) to head (f3dc6c6).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
.../export/export_metadata_in_rocks_db_sub_command.rs 0.00% 67 Missing ⚠️
...rocketmq-admin/rocketmq-admin-core/src/commands.rs 0.00% 6 Missing ⚠️
...q-admin/rocketmq-admin-core/src/commands/export.rs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6516      +/-   ##
==========================================
- Coverage   42.08%   42.06%   -0.03%     
==========================================
  Files         947      948       +1     
  Lines      132264   132338      +74     
==========================================
  Hits        55666    55666              
- Misses      76598    76672      +74     

☔ 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
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: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands/export/export_metadata_in_rocks_db_sub_command.rs`:
- Around line 59-95: The code only counts entries in non-JSON mode; update both
branches to track total entries by declaring a mutable counter (e.g., let mut
count: u64 = 0) outside the json_enable conditional and increment it inside the
iterate_kv_store closure used in both branches (the closure passed to
Self::iterate_kv_store), then after iteration print a final summary line such as
"Total entries: {}" (ensure the JSON branch still builds the json_config and
prints json_config_str before or after printing the total). Use the existing
symbols json_enable, Self::iterate_kv_store, count, table_key/TOPICS_JSON_CONFIG
and json_config_str to locate where to add the counter increment and final
print.
- Around line 32-54: Update the CLI long option names to match the required
contract: change the #[arg(... long = "...")] values for the struct fields path,
config_type, and json_enable in export_metadata_in_rocks_db_sub_command.rs so
they are "config-path", "config-type", and "json-enable" respectively (leave
help text and other attributes unchanged) to ensure the flags exposed by the CLI
match the expected names.
- Around line 121-137: Validate and normalize the config_type before joining
paths and fail fast on invalid input: first trim and normalize the user input
(e.g., let config_type_raw = self.config_type.trim(); let config_type_norm =
config_type_raw.to_ascii_lowercase()) and check against TOPICS_JSON_CONFIG and
SUBSCRIPTION_GROUP_JSON_CONFIG; if it does not match return an Err (not Ok(()))
to signal failure; only after validation map the normalized value to the correct
canonical config name and then canonicalize the provided path (e.g.,
std::fs::canonicalize(path) or Path::new(path).canonicalize()) and join that
canonical path with the normalized config_type to produce full_path so you never
join with the raw user value.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 031a50e and 53524d4.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • rocketmq-tools/rocketmq-admin/rocketmq-admin-core/Cargo.toml
  • rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands.rs
  • rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands/export.rs
  • rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands/export/export_metadata_in_rocks_db_sub_command.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands.rs

Copy link
Owner

@mxsm mxsm left a comment

Choose a reason for hiding this comment

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

@WaterWhisperer please fix ci error, I will merge this pr first.

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

♻️ Duplicate comments (4)
rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands/export/export_metadata_in_rocks_db_sub_command.rs (3)

120-137: ⚠️ Potential issue | 🟠 Major

Fail fast on invalid input and normalize config_type before joining paths.

Line 123 and Line 136 return success for invalid input, and Line 127 joins with raw user input before validation.

Suggested patch
         let path = self.path.trim();
         if path.is_empty() || !std::path::Path::new(path).exists() {
-            println!("RocksDB path is invalid.");
-            return Ok(());
+            return Err(RocketMQError::Internal(format!("RocksDB path is invalid: {path}")));
         }

-        let config_type = self.config_type.trim();
-        let full_path = PathBuf::from(path).join(config_type);
-
-        if !config_type.eq_ignore_ascii_case(TOPICS_JSON_CONFIG)
-            && !config_type.eq_ignore_ascii_case(SUBSCRIPTION_GROUP_JSON_CONFIG)
-        {
-            println!(
-                "Invalid config type={}, Options: topics,subscriptionGroups",
-                config_type
-            );
-            return Ok(());
-        }
+        let config_type_raw = self.config_type.trim();
+        let config_type = if config_type_raw.eq_ignore_ascii_case(TOPICS_JSON_CONFIG) {
+            TOPICS_JSON_CONFIG
+        } else if config_type_raw.eq_ignore_ascii_case(SUBSCRIPTION_GROUP_JSON_CONFIG) {
+            SUBSCRIPTION_GROUP_JSON_CONFIG
+        } else {
+            return Err(RocketMQError::Internal(format!(
+                "Invalid config type={}, options: topics,subscriptionGroups",
+                config_type_raw
+            )));
+        };
+        let full_path = PathBuf::from(path).join(config_type);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands/export/export_metadata_in_rocks_db_sub_command.rs`
around lines 120 - 137, The input validation currently returns Ok(()) on invalid
path or config_type and joins PathBuf with the raw unvalidated config_type;
update the logic in the export_metadata_in_rocks_db_sub_command (variables:
path, config_type, full_path) to fail fast by returning an Err on invalid input
instead of Ok(()), trim and normalize config_type (e.g., to a
canonical/lowercase or mapped string matching
TOPICS_JSON_CONFIG/SUBSCRIPTION_GROUP_JSON_CONFIG) before constructing
full_path, and perform the exists/valid-type checks using the normalized value
so PathBuf::from(path).join(normalized_config_type) only uses validated data.
Ensure you reference TOPICS_JSON_CONFIG and SUBSCRIPTION_GROUP_JSON_CONFIG when
validating and return an appropriate error result rather than silently
succeeding.

59-95: ⚠️ Potential issue | 🟠 Major

Track and print total entries in both output modes.

Counting currently happens only in plain-text mode, and no final total is emitted for JSON mode.

Suggested patch
-        if json_enable {
+        let mut count: u64 = 0;
+        if json_enable {
             let mut config_table = serde_json::Map::new();

             Self::iterate_kv_store(db, |key, value| {
+                count += 1;
                 let config_key = String::from_utf8_lossy(key).to_string();
                 let config_value = String::from_utf8_lossy(value).to_string();
@@
             let json_config_str = serde_json::to_string_pretty(&json_config)
                 .map_err(|e| RocketMQError::Internal(format!("Failed to serialize JSON: {}", e)))?;
             println!("{}", json_config_str);
         } else {
-            let mut count: u64 = 0;
             Self::iterate_kv_store(db, |key, value| {
                 count += 1;
                 let config_key = String::from_utf8_lossy(key);
                 let config_value = String::from_utf8_lossy(value);
                 println!("{}, Key: {}, Value: {}", count, config_key, config_value);
             })?;
         }
+        println!("Total entries: {}", count);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands/export/export_metadata_in_rocks_db_sub_command.rs`
around lines 59 - 95, The JSON branch only builds and prints the JSON map but
doesn't track or print the total entry count; only the plain-text branch
increments and prints a running count but doesn't emit a final total. Fix by
introducing a mutable counter (u64) and incrementing it inside the closure
passed to Self::iterate_kv_store in both branches (referencing iterate_kv_store
and json_enable), then after printing the JSON (json_config_str) or finishing
the plain-text iteration print a final summary line like "Total entries: X" so
both modes output the total count; ensure the counter is in scope for both
branches or duplicated per-branch as needed and closures capture it mutably.

32-54: ⚠️ Potential issue | 🟠 Major

Align long option names with the required CLI contract.

The exposed long flags still do not match the specified interface (--config-path, --config-type, --json-enable).

Suggested patch
     #[arg(
         short = 'p',
-        long = "path",
+        long = "config-path",
         required = true,
         help = "Absolute path for the metadata directory"
     )]
@@
     #[arg(
         short = 't',
-        long = "configType",
+        long = "config-type",
         required = true,
         help = "Name of kv config, e.g. topics/subscriptionGroups"
     )]
@@
     #[arg(
         short = 'j',
-        long = "jsonEnable",
+        long = "json-enable",
         required = false,
         help = "Json format enable, Default: false"
     )]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands/export/export_metadata_in_rocks_db_sub_command.rs`
around lines 32 - 54, Update the CLI long option names to match the required
contract by changing the arg attributes on the struct fields: for the `path`
field (symbol: path) set long to "config-path", for `config_type` (symbol:
config_type) set long to "config-type", and for `json_enable` (symbol:
json_enable) set long to "json-enable"; leave other attributes (short
flags/help/required) unchanged so the exposed flags become --config-path,
--config-type, and --json-enable.
rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands.rs (1)

370-371: ⚠️ Potential issue | 🟡 Minor

Remove indentation artifacts from the command remark string.

Line 370 and Line 371 split the string with \, which injects extra spaces in rendered output.

Proposed fix
-                remark: "Export RocksDB kv config (topics/subscriptionGroups). Recommend to use [mqadmin \
-                         rocksDBConfigToJson]",
+                remark: "Export RocksDB kv config (topics/subscriptionGroups). Recommend to use [mqadmin rocksDBConfigToJson]",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands.rs` around
lines 370 - 371, The remark string assigned to the `remark` field currently uses
a backslash and newline which injects extra spaces in the rendered output;
replace the broken two-line string in the `remark` assignment with a single-line
literal (e.g., "Export RocksDB kv config (topics/subscriptionGroups). Recommend
to use [mqadmin rocksDBConfigToJson]") so there are no `\` line-continuations or
inserted spaces—update the `remark` value where it's defined to be a normal
one-line string.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands/export/export_metadata_in_rocks_db_sub_command.rs`:
- Around line 60-83: The current implementation builds a full serde_json::Map
(config_table -> json_config) which loads all RocksDB entries into memory;
change to streaming JSON output by writing the root object/field and then
iterating entries with Self::iterate_kv_store, emitting each key/value pair
directly to a serde_json::Serializer (or serde_json::ser::Formatter) attached to
the output writer instead of inserting into config_table; use the same table_key
logic (TOPICS_JSON_CONFIG branch) to open the object field (e.g., write start
object, write table_key name, start inner object), then for each callback
invocation convert value to serde_json::Value (fallback to string on parse
error) and serialize that single entry immediately, and after iteration close
the inner and outer objects so you never materialize config_table or json_config
in memory.

---

Duplicate comments:
In `@rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands.rs`:
- Around line 370-371: The remark string assigned to the `remark` field
currently uses a backslash and newline which injects extra spaces in the
rendered output; replace the broken two-line string in the `remark` assignment
with a single-line literal (e.g., "Export RocksDB kv config
(topics/subscriptionGroups). Recommend to use [mqadmin rocksDBConfigToJson]") so
there are no `\` line-continuations or inserted spaces—update the `remark` value
where it's defined to be a normal one-line string.

In
`@rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands/export/export_metadata_in_rocks_db_sub_command.rs`:
- Around line 120-137: The input validation currently returns Ok(()) on invalid
path or config_type and joins PathBuf with the raw unvalidated config_type;
update the logic in the export_metadata_in_rocks_db_sub_command (variables:
path, config_type, full_path) to fail fast by returning an Err on invalid input
instead of Ok(()), trim and normalize config_type (e.g., to a
canonical/lowercase or mapped string matching
TOPICS_JSON_CONFIG/SUBSCRIPTION_GROUP_JSON_CONFIG) before constructing
full_path, and perform the exists/valid-type checks using the normalized value
so PathBuf::from(path).join(normalized_config_type) only uses validated data.
Ensure you reference TOPICS_JSON_CONFIG and SUBSCRIPTION_GROUP_JSON_CONFIG when
validating and return an appropriate error result rather than silently
succeeding.
- Around line 59-95: The JSON branch only builds and prints the JSON map but
doesn't track or print the total entry count; only the plain-text branch
increments and prints a running count but doesn't emit a final total. Fix by
introducing a mutable counter (u64) and incrementing it inside the closure
passed to Self::iterate_kv_store in both branches (referencing iterate_kv_store
and json_enable), then after printing the JSON (json_config_str) or finishing
the plain-text iteration print a final summary line like "Total entries: X" so
both modes output the total count; ensure the counter is in scope for both
branches or duplicated per-branch as needed and closures capture it mutably.
- Around line 32-54: Update the CLI long option names to match the required
contract by changing the arg attributes on the struct fields: for the `path`
field (symbol: path) set long to "config-path", for `config_type` (symbol:
config_type) set long to "config-type", and for `json_enable` (symbol:
json_enable) set long to "json-enable"; leave other attributes (short
flags/help/required) unchanged so the exposed flags become --config-path,
--config-type, and --json-enable.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 53524d4 and f3dc6c6.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • rocketmq-tools/rocketmq-admin/rocketmq-admin-core/Cargo.toml
  • rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands.rs
  • rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands/export.rs
  • rocketmq-tools/rocketmq-admin/rocketmq-admin-core/src/commands/export/export_metadata_in_rocks_db_sub_command.rs

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 ✅

Copy link
Owner

@mxsm mxsm left a comment

Choose a reason for hiding this comment

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

LGMT

@mxsm mxsm merged commit c426b64 into mxsm:main Feb 27, 2026
8 of 14 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 Feb 27, 2026
@WaterWhisperer WaterWhisperer deleted the feat-6391 branch February 27, 2026 10:54
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 feature🚀 Suggest an idea for this project.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature🚀] Implement ExportMetadataInRocksDB Command in rocketmq-admin-core

4 participants