zjncs opened a new pull request, #3310:
URL: https://github.com/apache/rocketmq-dashboard/pull/3310

   ## Problem
   
   `RocketMQAdminClientImpl.resetOffset` applied consumer-group offset resets 
with `admin.resetOffsetByTimestamp(cluster, topic, group, timestamp, false)` — 
the non-forcing variant. On the broker (RocketMQ 5.5.0 
`Broker2Client.resetOffset`, the default path while 
`useServerSideResetOffset=false`) that flag has two effects the Studio UI does 
not expect:
   
   1. **Offline groups cannot be reset at all.** The non-forcing path only 
pushes `RESET_CONSUMER_CLIENT_OFFSET` to consumers that are currently connected 
and answers `CONSUMER_NOT_ONLINE` otherwise (`invokeBrokerToResetOffset` turns 
that into an `MQClientException`), so the endpoint always fails for an offline 
group — yet offline groups are the primary scenario for timestamp-based resets, 
and Studio's own preview handles them fine: `examineConsumeStats` reads 
persisted broker-side offsets, so the preview computes real per-queue targets 
and returns `allowReset=true`, then the apply 500s with "Failed to reset 
offset: Consumer not online...".
   
   2. **Forward resets silently no-op.** Without `force` the broker caps each 
pushed offset at the group's current offset (`if (isForce || timeStampOffset < 
consumerOffset)`), so a timestamp ahead of the current position — which the 
preview explicitly supports, showing "Skips N unconsumed message(s)" and only a 
warning — is converted per queue into a reset to the *current* offset, i.e. 
nothing happens.
   
   ## Fix
   
   Route the apply through `admin.resetOffsetNew(name, topic, timestamp)` — the 
same API the classic rocketmq-console uses for this operation. 
`DefaultMQAdminExtImpl.resetOffsetNew` (5.5.0) forces the searched offset onto 
the reset request (`resetOffsetByTimestamp(topic, group, timestamp, true)`) and 
falls back to `resetOffsetByTimestampOld(group, topic, timestamp, true)` — 
direct `UPDATE_CONSUMER_OFFSET` writes per queue — when the broker answers 
`CONSUMER_NOT_ONLINE`, so both cases above now behave the way the preview 
promises. Both call sites (instance-scoped and legacy global) use it; no 
signature or controller changes.
   
   ## Verification
   
   Base SHA: 36126024 (rocketmq-studio)
   
   Fail-before / pass-after on the two new tests in 
`RocketMQAdminClientImplTest`:
   
   - `resetOffsetShouldApplyPreviewedTargetsAndSupportOfflineGroups` — failed 
showing the actual invocation `resetOffsetByTimestamp("DefaultCluster", 
"orders", "cg-orders", 1784246400000L, false)`; passes after the fix 
(`resetOffsetNew` invoked, non-forcing variant never called).
   - `resetOffsetWithoutInstanceShouldUseForceAndOfflineFallbackSemantics` — 
same for the legacy global path.
   
   Full run after the fix:
   
   - `RocketMQAdminClientImplTest`: 43/43 pass (41 pre-existing + 2 new)
   - whole `org.apache.rocketmq.studio.provider.apache` package: 256/256 pass
   
   Broker-side semantics quoted from the `rocketmq-all-5.5.0` sources of 
`AdminBrokerProcessor.resetOffset`, `Broker2Client.resetOffset`, 
`MQClientAPIImpl.invokeBrokerToResetOffset` and 
`DefaultMQAdminExtImpl.resetOffsetNew`.
   
   **AI disclosure:** This change was prepared with AI assistance (GitHub 
Copilot/Claude-style tooling guided by a human contributor).


-- 
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