Search before asking
I checked open and closed issues/PRs for queryMessage, ListMessage, begin_timestamp, delivery timestamp and ProxyAdminGrpcService. #10826 added this RPC. I found no existing fix for the query time window. Nearby open work (#11105, #11117, #10686, #11228, #11232) is a different path.
What happened?
ListMessageRequest.begin_timestamp and end_timestamp are google.protobuf.Timestamp values. admin.proto says the range is inclusive. ProxyAdminGrpcService.queryMessage converts each bound with only getSeconds():
long begin = request.hasBeginTimestamp()
? TimeUnit.SECONDS.toMillis(request.getBeginTimestamp().getSeconds()) : 0L;
long end = request.hasEndTimestamp()
? TimeUnit.SECONDS.toMillis(request.getEndTimestamp().getSeconds()) : Long.MAX_VALUE;
The fractional second is stored in nanos and is dropped. Timestamps.fromMillis puts that fraction in nanos, so any window that is not an exact second is shifted down by up to 999ms. The same class already keeps nanos for ResetGroupOffset.
The broker treats the resulting longs as inclusive millisecond store timestamps (IndexFile.selectPhyOffset: timeRead >= begin && timeRead <= end, and isTimeMatched skips an index file whose range misses the window). A truncated begin pulls in messages from the previous partial second. A truncated end drops messages that are still inside the requested end, and can skip an index file whose first store timestamp sits in that partial second.
Unset bounds stay 0 and Long.MAX_VALUE. This is not the unimplemented subscription / lite_topic search, and it is not page or scroll pagination.
Runtime
Ubuntu 24.04, x86_64. Reproduced with the existing ProxyAdminGrpcServiceTest mocks (route stub plus AdminService). No running broker is required: the wrong bounds are visible on the queryMessage call the proxy makes.
develop at 78b96bc5e21216cd7896efae08f90c5cde4cae53, including the pinned rocketmq-apis submodule at 3e60073c6dab3430feaec443824802e23ecda681.
Temurin 8u504-b01, Maven 3.8.7. JDK 21 cannot run this test class: the pinned Mockito/Byte Buddy rejects class-file major version 65.
Reproduction
- Call
QueryMessage with message_key set and a begin/end built by Timestamps.fromMillis, for example begin 1700000000500 and end 1700000001250.
- Observe the
beginTimestamp / endTimestamp passed to the broker admin query.
On the unpatched proxy the test fails:
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
Argument(s) are different! Wanted:
adminService.queryMessage(
"127.0.0.1:10911", "topicA", "key-1", <any integer>,
1700000000500L, 1700000001250L, false, true, <any long>);
Actual invocations have different arguments:
adminService.queryMessage(
"127.0.0.1:10911", "topicA", "key-1", 32,
1700000000000L, 1700000001000L, false, true, 3000L);
The RPC itself still returns OK. The window is wrong.
Expected behavior
Pass 1700000000500 and 1700000001250 through to AdminService.queryMessage. An omitted timestamp should still mean begin 0 and end Long.MAX_VALUE. ResetGroupOffset should keep its current millisecond value (seconds * 1000 + nanos / 1_000_000).
Do not change GrpcConverter. Receive-path delivery timestamps, including the TIMER_DELAY_SEC "now + delay" behavior covered by open PR #10686, stay as they are.
Search before asking
I checked open and closed issues/PRs for
queryMessage,ListMessage,begin_timestamp, delivery timestamp andProxyAdminGrpcService. #10826 added this RPC. I found no existing fix for the query time window. Nearby open work (#11105, #11117, #10686, #11228, #11232) is a different path.What happened?
ListMessageRequest.begin_timestampandend_timestamparegoogle.protobuf.Timestampvalues.admin.protosays the range is inclusive.ProxyAdminGrpcService.queryMessageconverts each bound with onlygetSeconds():The fractional second is stored in
nanosand is dropped.Timestamps.fromMillisputs that fraction innanos, so any window that is not an exact second is shifted down by up to 999ms. The same class already keeps nanos forResetGroupOffset.The broker treats the resulting longs as inclusive millisecond store timestamps (
IndexFile.selectPhyOffset:timeRead >= begin && timeRead <= end, andisTimeMatchedskips an index file whose range misses the window). A truncated begin pulls in messages from the previous partial second. A truncated end drops messages that are still inside the requested end, and can skip an index file whose first store timestamp sits in that partial second.Unset bounds stay
0andLong.MAX_VALUE. This is not the unimplementedsubscription/lite_topicsearch, and it is not page or scroll pagination.Runtime
Ubuntu 24.04, x86_64. Reproduced with the existing
ProxyAdminGrpcServiceTestmocks (route stub plusAdminService). No running broker is required: the wrong bounds are visible on thequeryMessagecall the proxy makes.developat78b96bc5e21216cd7896efae08f90c5cde4cae53, including the pinnedrocketmq-apissubmodule at3e60073c6dab3430feaec443824802e23ecda681.Temurin 8u504-b01, Maven 3.8.7. JDK 21 cannot run this test class: the pinned Mockito/Byte Buddy rejects class-file major version 65.
Reproduction
QueryMessagewithmessage_keyset and a begin/end built byTimestamps.fromMillis, for example begin1700000000500and end1700000001250.beginTimestamp/endTimestamppassed to the broker admin query.On the unpatched proxy the test fails:
The RPC itself still returns
OK. The window is wrong.Expected behavior
Pass
1700000000500and1700000001250through toAdminService.queryMessage. An omitted timestamp should still mean begin0and endLong.MAX_VALUE.ResetGroupOffsetshould keep its current millisecond value (seconds * 1000 + nanos / 1_000_000).Do not change
GrpcConverter. Receive-path delivery timestamps, including theTIMER_DELAY_SEC"now + delay" behavior covered by open PR #10686, stay as they are.