iloveeyjafjalla opened a new issue, #11367:
URL: https://github.com/apache/rocketmq/issues/11367

   ### 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/discussions).
   - [x] I have searched the [GitHub 
Issues](https://github.com/apache/rocketmq/issues) and [GitHub 
Discussions](https://github.com/apache/rocketmq/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.
   
   ### Runtime platform environment
   
   OS: any (proxy module, admin gRPC surface; needs a group whose queues live 
on more than one broker)
   
   ### RocketMQ version
   
   branch: develop
   Git commit id: 9ea2ccdc2b41445aee5e177e14e501d606f5a1ed (2026-10-08)
   
   ### JDK Version
   
   Compiler: Temurin 1.8.0_504 (target 1.8, same as CI)
   
   ### Describe the Bug
   
   `ResetGroupOffset` answers `OK` after resetting only the brokers that 
happened to answer.
   
   `resetGroupOffset` fans the reset out through the shared best-effort helper 
and discards the per-broker outcome:
   
   ```java
   queryAllBrokers(brokerAddrs, (addr, timeout) ->
           admin().resetOffset(addr, topic, group, resetTimestamp, true, 
timeout))
       .whenComplete((ignored, throwable) -> {
           if (throwable != null) {
               respond(responseObserver, 
ResetGroupOffsetResponse.newBuilder().setStatus(err(throwable)).build());
           } else {
               respond(responseObserver, 
ResetGroupOffsetResponse.newBuilder().setStatus(ok()).build());
           }
       });
   ```
   
   `queryAllBrokers` only fails when **every** hop fails — a hop that failed is 
collected into a separate `failures` list and the
   surviving results are returned:
   
   ```java
   return CompletableFuture.allOf(...)
       .handle(...)                     // keeps the successes, drops the 
failed hops
       .thenCompose(succeeded -> {
           if (succeeded.isEmpty() && !failures.isEmpty()) { ...fail... }
           return CompletableFuture.completedFuture(succeeded);
       });
   ```
   
   Tolerating a partial fan-out is documented for the *reads* ("a partially 
available cluster should still return the data it
   has", `docs/proxy-admin.md` §D4), but a mutation has no equivalent 
statement, and the response carries nothing but the status:
   the caller cannot tell a full reset from a partial one.
   
   ### Steps to Reproduce
   
   1. Run a proxy with `grpcAdminServerEnable=true` and a topic whose queues 
live on two brokers.
   2. Make one broker unresponsive for the admin hop (stopped, or slower than 
the per-hop deadline
      `grpcAdminServerRequestTimeoutMillis + 1000`, default 4000 ms).
   3. Call `ResetGroupOffset` for a group on that topic.
   4. The RPC answers `OK` although only one of the two brokers applied the new 
offsets; the group's queues on the other broker
      keep consuming from the old offsets (duplicate or skipped messages after 
the reset).
   
   ### Expected behavior
   
   A reset that did not reach every broker is not reported as a plain success: 
the caller is told which brokers were not reset (or
   that the reset was partial), so the operation can be re-run or verified.
   
   ### Actual behavior
   
   `OK` with no indication that part of the group was left on the old offsets.
   
   ### Additional context
   
   Fix: make the mutation path require every broker hop to succeed (naming the 
failing broker addresses in the status message),
   while the read paths keep their documented best-effort semantics.
   


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