Repository navigation
[ISSUE #11420] fix(store): report a failed retry append instead of reporting PUT_OK - #11422
iloveeyjafjalla wants to merge 1 commit into
Conversation
… of reporting PUT_OK
RockteMQ-AI
left a comment
There was a problem hiding this comment.
Review by github-manager-bot
Summary
This PR fixes a silent data-loss bug in CommitLog: when a message append hits end-of-file and the retry on a fresh mapped file also fails (e.g. message body exceeds mappedFileSizeCommitLog), the code fell through to return PUT_OK — causing the producer to receive SUCCESS for a message that was never persisted.
Findings
-
[Positive]
CommitLog.java:1130-1134— Theelsebranch correctly mirrors the existing first-append failure mapping (UNKNOWN_ERROR → UNKNOWN_ERROR, everything else →MESSAGE_ILLEGAL). Clean and consistent with the surrounding pattern. -
[Positive]
CommitLog.java:1292-1297— The batch path (asyncPutMessages) originally had no check at all after the retry append — it just broke unconditionally. Adding the guard here closes the same class of bug for batch sends. Well caught. -
[Positive] Both regression tests use a small
mappedFileSizeCommitLog(8 KB) with payloads that exceed it, directly reproducing the failure mode. The assertions (END_OF_FILEstatus, notPUT_OK) are precise. -
[Info]
CommitLog.java:1132— TheCompletableFuture.completedFuture(...)return is correct for the error path since no async I/O is needed. Consider whetherCompletableFuture.failedFuture()would be more semantically appropriate for callers that use.whenComplete()error handlers — though the current approach is consistent with how the rest of this method returns error results.
Suggestions
- The PR description is excellent — thorough disclosure of test limitations and environment details. This sets a good example for the project.
- No blocking concerns. The fix is minimal, correct, and well-tested.
Automated review by github-manager-bot
Which Issue(s) This PR Fixes
Brief Description
When the append hits the end of a commit log file,
CommitLogretries on a fresh file but only uses the retry result to decide whether to callonCommitLogAppend; a failing retry fell through to the unconditional success:A message larger than
mappedFileSizeCommitLogreturnsEND_OF_FILEfrom the first append and from the retry (a fresh file has no more room than the file size), so the store answeredPUT_OKfor a message that was never appended — and sinceincreaseOffsetis guarded byPUT_OKas well, no queue offset was advanced either.SendMessageProcessorturns that status intoResponseCode.SUCCESSand returns a msgId, i.e. the producer receives a successful send for a dropped message.This change maps a failed retry the same way the first-append branch already maps its failures (
UNKNOWN_ERROR→UNKNOWN_ERROR, everything else →MESSAGE_ILLEGAL) and returns it, in bothasyncPutMessageandasyncPutMessages(the batch path had the identical shape).How Did You Test This Change?
Two regression tests, each with a store configured like this repository's own small-file tests (
mappedFileSizeCommitLog = 1024 * 8) and a payload larger than one commit log file but far belowmaxMessageSize:DefaultMessageStoreTest#testPutMessageLargerThanCommitLogFileIsNotReportedAsSuccess(single message, 16 KB body)BatchPutMessageTest#testPutBatchLargerThanCommitLogFileIsNotReportedAsSuccess(batch of four 8 KB messages)Both assert that the append status is
END_OF_FILEand that the put status is notPUT_OK.Results on Temurin JDK 8 (the JDK CI uses), base
a7edeecfbplus this patch:java.lang.AssertionError: Values should be different. Actual: PUT_OKmvn -B -ntp -pl store test -Dtest='DefaultMessageStoreTest,AppendCallbackTest,BatchConsumeQueueTest,BatchPutMessageTest'—Tests run: 50, Failures: 0, Errors: 0, Skipped: 0,BUILD SUCCESS(the four classes that exercise the put path, including the 38DefaultMessageStoreTestcases)mvn -B -ntp -pl store clean package(checkstyle + spotbugs enabled):You have 0 Checkstyle violations.,BugInstance size is 0Disclosure — the full
storesuite does not complete on this machine, for three reasons I verified are independent of the patch:HAServerTest#putRequest_MultipleAckAndRequests(expected: PUT_OK but was: FLUSH_SLAVE_TIMEOUT): time/load sensitive; the same failure reproduces at the base commit in a separate worktree.BatchConsumeMessageTest(java.net.BindException: Address already in use: bindfromDefaultHAService$AcceptSocketService.beginAccept): also reproduces at the base commit, and no other process on the machine listens in the 30xxx range the test allocates from.EXCEPTION_ACCESS_VIOLATIONinlibrocksdbjni*.dll, threadTime-limited test) around the 45th test class in the same JVM; every class involved passes when run in isolation. The change touches only the commit log put path and no RocksDB code.(
skipAfterFailureCount=1is configured for the module, so any of these failures would otherwise hide the rest of the suite.)This change was prepared with AI assistance (analysis, patch and test drafting); the diff and every result above were reproduced locally by running the module's tests against the base commit and the patched tree.