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]

Reply via email to