leizhiyuan opened a new issue, #1430: URL: https://github.com/apache/rocketmq-clients/issues/1430
### Before Creating the Bug Report - [x] I found a bug, not just asking a question, which should be created in [GitHub Discussions](https://github.com/apache/rocketmq-clients/discussions). - [x] I have searched the [GitHub Issues](https://github.com/apache/rocketmq-clients/issues) and [GitHub Discussions](https://github.com/apache/rocketmq-clients/discussions) of this repository and believe that this is not a duplicate. - [x] I have confirmed that this bug belongs to the current repository, not other repositories of RocketMQ. ### Programming Language of the Client Rust ### Runtime Platform Environment macOS 27 (arm64) ### RocketMQ Version of the Client/Server Client: Rust `rocketmq` 5.0.0, master `a3d1de8b` Server: a managed RocketMQ 5.x service (Tencent Cloud TDMQ for RocketMQ 5), gRPC proxy endpoint ### Run or Compiler Version rustc 1.98.0 ### Describe the Bug After `SimpleConsumer::change_invisible_duration(&message, ..)`, the `MessageView` keeps its old receipt handle. The server invalidates that handle when it issues the new one, so: - `ack(&message)` afterwards returns `Ok(())`, but **has no effect**: the message is delivered again later. The message is processed twice and the application has no error to react to. - A second `change_invisible_duration(&message, ..)` on the same view also uses the old handle. The new handle is only available as the `String` returned by `change_invisible_duration`, and the public API has no way to ack with it: `ack` takes an `AckMessageEntry`, and `MessageView` can not be built or modified outside the crate. **Scenario.** The usual pattern for slow processing: receive with a short invisible duration, extend it with `change_invisible_duration` while the work is still running, then ack the same `MessageView` when done. With the Rust client this pattern silently redelivers every message that was extended. Observed on a real server with a normal topic and group (receive with a 60 s invisible duration, then `change_invisible_duration(10s)`): | step | Rust today | Java 5.2.2 | |---|---|---| | `change_invisible_duration(&view, 10s)` | `Ok(new_handle)`; `view.receipt_handle()` unchanged | ok; the view now holds the new handle | | `ack(&view)` | `Ok(())` | ok | | after the ack, observed for 50 s | **redelivered** after ~40 s, `delivery_attempt = 2` | not redelivered | | change twice, then `ack(&view)` | both `Ok`, ack `Ok`, **redelivered** after ~40 s | not redelivered | **Java behavior.** `SimpleConsumerImpl#changeInvisibleDuration0` writes the handle from the response back into the view: ```java return Futures.transformAsync(future, response -> { // Refresh receipt handle manually. impl.setReceiptHandle(response.getReceiptHandle()); ... ``` ### Steps to Reproduce ```rust let message = consumer.receive_with(topic, &expr, 1, Duration::from_secs(60)).await?.remove(0); consumer.change_invisible_duration(&message, Duration::from_secs(10)).await?; consumer.ack(&message).await?; // Ok(()) // The same message is received again about 40 s later. ``` ### What Did You Expect to See? The same as Java: `change_invisible_duration` refreshes the receipt handle of the `MessageView`, so the following `ack` or `change_invisible_duration` of the same view takes effect. ### What Did You See Instead? The ack returns `Ok` but is ignored by the server, and the message is redelivered. ### Additional Context Found while comparing the Rust and Java SimpleConsumer end to end on the same server. --- Tracked in #1412. -- 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]
