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

   ## Motivation
   
   `TransactionalMessageServiceImpl.check` iterates the half topic and, for an 
offset whose message cannot be fetched, inspects the pull status:
   
   ```java
   if (getResult.getPullResult().getPullStatus() == PullStatus.NO_NEW_MSG) {
   ```
   
   But `getHalfMsg` only fills `getResult.pullResult` when 
`TransactionalMessageBridge.getMessage` returns non-null, and that method 
**returns null** whenever `store.getMessage` does ("Get message from store 
return null" — e.g. the store is shutting down or not readable). In that case 
`getPullResult()` is null and this line throws an NPE.
   
   The NPE is swallowed by the outermost `catch (Throwable)` of `check`, which 
means the entire check cycle is aborted: the offset update for the 
already-processed messages of the current queue is skipped and every remaining 
queue of the half topic is not checked at all, for as long as the store keeps 
failing to serve reads.
   
   Notably the tail of the very same method already guards the same lookup for 
null (`getResult.getPullResult() == null ? newOffset : ...`); the guard is just 
missing here.
   
   ## Modification
   
   Treat a null pull result like the other unread-offset cases: log a warning 
and `break` out of this queue's loop, so the consume offset of the messages 
that were already checked is still committed and the unread offset is retried 
on the next check round.
   
   ## Test Evidence
   
   New test `testCheck_whenHalfMessagePullFails`: offset 0 returns a 
discardable half message, offset 1 hits the store read failure (bridge returns 
null). It asserts the discard listener fired and that 
`updateConsumeOffset(queue, 1)` was called.
   
   ```
   docker exec rmq-build mvn -q -pl broker test 
-Dtest='TransactionalMessageServiceImplTest#testCheck_whenHalfMessagePullFails' 
-Dsurefire.failIfNoSpecifiedTests=true
   ```
   
   Before the fix:
   
   ```
   java.lang.NullPointerException: Cannot invoke "PullResult.getPullStatus()" 
because the return value of "GetResult.getPullResult()" is null
   Wanted but not invoked: bridge.updateConsumeOffset(...)   (Tests run: 1, 
Failures: 1)
   ```
   
   After the fix:
   
   ```
   docker exec rmq-build mvn -q -pl broker test 
-Dtest='TransactionalMessageServiceImplTest' 
-Dsurefire.failIfNoSpecifiedTests=true
   Tests run: 9, Failures: 0, Errors: 0, Skipped: 0
   ```
   
   No associated issue (self-discovered during a broker self-audit).


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