leizhiyuan opened a new issue, #1436: URL: https://github.com/apache/rocketmq-clients/issues/1436
### 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 The timestamps of a received `MessageView` differ from the Java client in two ways. **1. `born_timestamp()` and `delivery_timestamp()` are in seconds.** `MessageView::from_pb_message` keeps only `Timestamp.seconds`. Java returns milliseconds (`MessageViewImpl#fromProtobuf` uses `Timestamps.toMillis`), and so do the other RocketMQ clients and the broker (`MessageExt#getBornTimestamp`). The producer also sends `born_timestamp` with `nanos: 0`, so the born time of a message sent by the Rust producer loses its milliseconds even for a Java consumer. **2. A normal message gets a `delivery_timestamp()`.** `ReceiveMessageResponse` can carry a `delivery_timestamp` entry: the time the proxy delivered the batch. `Client::receive_message_inner` copies it into the `delivery_timestamp` system property of every received message. As a result, a normal message reports `Some(<transport time>)` and looks like a delay message. For a real delay message, the configured delivery time is overwritten. Java keeps this value apart (`ConsumerImpl#receiveMessage` passes it as `transportDeliveryTimestamp`, used only for the consume-latency metric), and `getDeliveryTimestamp()` is empty for a normal message. **Scenario.** An application logs or checks the message age (`now - born_timestamp()`), or decides whether a message is a delay message from `delivery_timestamp()`. With Rust the age is off by a factor of 1000. Every message looks like a delay message, and a delay message reports the proxy's delivery time rather than the time it was scheduled for. ### Steps to Reproduce Same program against `master`, normal topic and group (SimpleConsumer): 1. Send a normal message, receive it, print `born_timestamp()` and `delivery_timestamp()`. 2. Send a delay message with `set_delivery_timestamp(now_secs + 12)`, receive it, print both again. ### What Did You Expect to See? As in Java 5.2.2 (checked against the same server): | | Java | |---|---| | normal message `getBornTimestamp()` | `1792562125833` (ms) | | normal message `getDeliveryTimestamp()` | `Optional.empty` | | delay message `getDeliveryTimestamp()` | the configured time, in ms | ### What Did You See Instead? | | Rust `master` | |---|---| | normal message `born_timestamp()` | `1792575801` (s) | | normal message `delivery_timestamp()` | `Some(1792575801)`: the proxy's delivery time | | delay message `delivery_timestamp()` | `Some(1792575841)`: the proxy's delivery time, 8 s after the configured `1792575833` | | delay message `born_timestamp()` | `1792575821` (s) | ### Additional Context **Maintainers, please confirm this behavior change before merging.** `MessageView::born_timestamp()` and `delivery_timestamp()` are public. Switching them to milliseconds changes the unit of values that applications may already use, and they would keep compiling. The proposed fix: 1. `born_timestamp()` / `delivery_timestamp()` return milliseconds since the Unix epoch, as in Java. 2. The response-level delivery timestamp is no longer copied into the messages, so `delivery_timestamp()` is `None` for a normal message and the configured time for a delay message. The Rust client has no consume-latency metric yet, so I do not keep the value. If you prefer, it can be exposed separately (Java: `transportDeliveryTimestamp`). 3. The producer sends `born_timestamp` with millisecond precision, as Java `PublishingMessageImpl` (`Timestamps.fromMillis`). Open question: `MessageBuilder::set_delivery_timestamp` / `delay_message_builder` take **seconds**, while Java `setDeliveryTimestamp` takes milliseconds. With the fix, the getter on the consumer side is in milliseconds and the setter on the producer side stays in seconds. I left the setter unchanged and documented the unit. If it changed silently, a seconds value would be read as a time in January 1970 and the message delivered immediately. Should it move to milliseconds as well, maybe with a new method name? --- 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]
