You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rocketmq.apache.org by "zjncs (via GitHub)" <gi...@apache.org> on 2026/09/10 11:58:01 UTC

[PR] [ISSUE #D19] Tolerate null pull result when checking half messages [rocketmq]

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: commits-unsubscribe@rocketmq.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org