zhaohai666 opened a new pull request, #1381:
URL: https://github.com/apache/rocketmq-clients/pull/1381

   # feat(rust): implement LiteSimpleConsumer
   
   ## Summary
   
   This PR ports the **LiteSimpleConsumer** from the reference Java client to 
the Rust client
   (RocketMQ 5.x gRPC protocol), branch `feat/rust-lite-simple-consumer` based 
on `master`
   (`fc088d4a`). It lands **1 commit** touching **12 files (+1,283 / −32)**.
   
   The lite consumer model lets one consumer group consume many short-lived 
"lite topics" that all map
   onto a single parent topic. The consumer binds to the parent topic, then 
dynamically subscribes /
   unsubscribes individual lite topics through the `SyncLiteSubscription` RPC, 
and pulls their messages
   explicitly with `receive` + `ack`.
   
   **What is included**
   
   - `src/lite_simple_consumer.rs`: `LiteSimpleConsumer` + 
`LiteSimpleConsumerTrait` with
     `subscribe_lite`, `subscribe_lite_with_offset`, `unsubscribe_lite`, 
`get_lite_topic_set`,
     `get_consumer_group`, `get_bind_topic`, `receive(max_message_num, 
invisible_duration)`, `ack`,
     `change_invisible_duration` and `shutdown`. It reuses the existing 
dual-client design of
     `LitePushConsumer`: the owning `SimpleConsumer` plus a lightweight cloned 
`Client` shared with
     `LiteSubscriptionManager`, so both talk over the same telemetry session.
   - Telemetry: `NotifyUnsubscribeLiteCommand` and `Settings` are forwarded to
     `LiteSubscriptionManager` (the lite push consumer's handler loop was wired 
to a channel that never
     received anything; the new consumer uses the channel that `Client::start` 
actually feeds).
   - `ClientType::LiteSimpleConsumer` (=6) plus 
`Client::clone_for_lite_simple_consumer()`.
   - `util::build_lite_simple_consumer_settings`: simple-consumer settings 
reporting
     `LITE_SIMPLE_CONSUMER` with the bind topic subscribed as `SUB_ALL`.
   - `util::prune_lite_route`: keeps only the first readable master queue of a 
route, mirroring
     `LiteSimpleConsumerImpl#updateSubscriptionLoadBalancer` in Java (a lite 
consumer only needs a
     route to *a* broker of the parent topic; the server resolves the lite 
queues).
   - `SimpleConsumer`: adds `new_with_client`, `start_with_telemetry`, 
`check_started`,
     `shutdown_ref` and `receive_lite` so the lite consumer can reuse the 
simple-consumer plumbing
     without duplicating it.
   - Two defect fixes on the lite path (see below).
   
   ---
   
   ## Defect fix 1: missing `lite_topic` in ack / change-invisible-duration 
requests
   
   `Client::ack_message` and `Client::change_invisible_duration` always sent 
`lite_topic: None`. The
   proxy resolves LMQ receipt handles through that field, so acking a lite 
message fails with
   `50001 INTERNAL_SERVER_ERROR`.
   
   `AckMessageEntry` now exposes `lite_topic()` (default `None`, implemented by 
`MessageView` from the
   message system properties), the entry construction is factored into 
`util::build_ack_message_entry`,
   and both requests carry it. Since the fix lives in `Client`, it benefits 
every consumer that
   receives lite messages, not only the new one.
   
   ---
   
   ## Defect fix 2: `unsubscribe_lite` always failed with "client is not 
started"
   
   `LiteSubscriptionManager::unsubscribe_lite` validated the running state on 
the client it holds,
   which is the lightweight clone created by `clone_for_lite_consumer()`. That 
clone intentionally has
   `shutdown_tx = None` (only the owning client may trigger shutdown), so 
`check_started` always
   reported "client is not started" and every unsubscribe failed — for the push 
consumer as well.
   
   The state check is now the responsibility of the public API of the owning 
consumer, exactly like
   `subscribe_lite` already did. This was found by the real-cluster test, not 
by unit tests.
   
   ---
   
   ## Tests
   
   **Offline tests**
   
   - `cargo test --lib`: 93 passed (4 of them added by this PR): settings carry
     `LITE_SIMPLE_CONSUMER` with the bind topic subscribed as `SUB_ALL`; route 
pruning keeps the first
     readable master queue and errors on an empty/unreadable route; the ack 
entry carries `lite_topic`
     for lite messages and `None` for regular ones.
   - `tests/lite_simple_consumer_test.rs`: 4 passed — consumer group / bind 
topic validation,
     `get_consumer_group` / `get_bind_topic` / `get_lite_topic_set`, and
     `subscribe_lite` / `unsubscribe_lite` before `start` returning 
`ClientIsNotRunning`.
   
   **Real-cluster integration tests** — 2/2 passing against a local RocketMQ 
5.5.1 deployment
   (namesrv + broker with `enableLmq=true` and `enableMultiDispatch=true`, 
standalone **proxy in
   CLUSTER mode**, parent topic created with `message.type=LITE`, consumer 
group pre-created with
   `+lite.bind.topic=<parentTopic>`):
   
   - `test_receive_and_ack`: send 5 lite messages → 
`subscribe_lite_with_offset` with
     `OffsetPolicy::Min` → receive → assert `lite_topic` on every message → ack 
all →
     `unsubscribe_lite` removes it from the local set → shutdown.
   - `test_receive_after_subscribe`: messages produced after the subscription 
are delivered and acked.
   
   The suite is gated by `ROCKETMQ_RUST_LITE_ENDPOINTS`; without it the tests 
print a skip message and
   pass, so CI without a cluster stays green.
   
   **Example verified end to end**
   
   `examples/lite_simple_consumer.rs` was run against the same cluster: 
subscribe → receive 3 lite
   messages (`lite_topic=Some("example-lite-topic")`) → ack (no errors) → 
unsubscribe → clean
   shutdown, with the broker logging the consumer as `CONSUME_ACTIVELY 
LITE_SELECTIVE`.
   
   ---
   
   ## Notes
   
   - Like `lite_push_consumer`, the new module is compiled under 
`#[cfg(not(test))]`: in test builds
     `Client` resolves to `MockClient` (via `mockall_double`), so lite 
consumers cannot be constructed
     in unit tests. Its assertions therefore live in `tests/`, while pure 
helpers (settings, route
     pruning, ack entry) are unit tested in `src/util.rs`.
   - `cargo fmt --check` and `cargo clippy --all-features -- -D warnings` (the 
CI commands) are clean.
   
   ---
   
   ## Checklist
   
   - [x] Reference implementation (`java/client/.../LiteSimpleConsumerImpl`) 
reviewed and mirrored
   - [x] `cargo build` / `cargo clippy --all-features -- -D warnings` / `cargo 
fmt --check` clean
   - [x] Offline tests pass (`cargo test --lib` 93, `lite_simple_consumer_test` 
4)
   - [x] Real-cluster integration tests pass (2/2)
   - [x] Example added, executed end to end against a local cluster, and 
documented in `rust/README.md`
   - [x] No changes to generated protobuf bindings required
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to