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

   ### Which Issue(s) This PR Fixes
   
   - Fixes #11439
   
   ### Brief Description
   
   A compaction round writes its output into a scratch sub-folder and moves it 
into the live compaction log only when the round completes:
   
   ```java
   compacting = new TopicPartitionLog(this, COMPACTING_SUB_FOLDER);   // :682 — 
paths only, no load, no cleanup
   ...
   replaceFiles(compactFiles.toCompactFiles, current, compacting);    // :618 — 
moves the files out
   compacting.clean(false, false);                                    // :621 — 
only on the success path
   ```
   
   `TopicPartitionLog.clean(...)` walks the **in-memory** file list, which is 
empty for a freshly constructed scratch log, so files left on disk by an 
interrupted round are invisible to it — and nothing else ever cleans them. The 
next round then reuses the very same file name 
(`MappedFileQueue.tryCreateMappedFile` opens the existing 
`…/compacting/00000000000000000000` through `DefaultMappedFile`, which maps it 
`rw` **without truncating** and with `wrotePosition = 0`), overwrites it from 
offset 0, declares it full via `putEndMessage`, and `replaceFiles` / 
`replaceCqFiles` move it into the live compaction log and consume queue — with 
whatever the aborted round had written beyond the new content still in it. The 
compacted view then mixes records of two rounds (stale/duplicated entries and a 
consume-queue tail that does not belong to the log content).
   
   This change empties the scratch folder before a round starts, so the scratch 
state of an aborted round can at worst be lost (the messages are re-compacted 
by the next round) instead of being spliced into the live log:
   
   ```java
   protected static void cleanScratchFolder(TopicPartitionLog scratch) {
       UtilAll.deleteFile(new File(scratch.getLog().getStorePath()));
       UtilAll.deleteFile(new 
File(scratch.getCQ().getMappedFileQueue().getStorePath()));
   }
   ```
   
   It is called for both scratch folders that follow this pattern: 
`COMPACTING_SUB_FOLDER` in `compaction(...)` and `REPLICATING_SUB_FOLDER` in 
`pullMessageFromMaster(...)` (`:202`). Clean rounds are unaffected (the folders 
are empty then) and the existing post-round `clean(...)` check keeps working.
   
   ### How Did You Test This Change?
   
   New test 
`CompactionLogTest#testCompactionCleansTheScratchFolderOfAnInterruptedRound`: 
it pre-creates the leftover scratch file 
`…/<topic>/<queueId>/compacting/00000000000000000000` (as an interrupted round 
leaves it), runs the real `compaction(...)` through the existing mock harness 
with `putEndMessage` stubbed, and asserts the leftover is gone afterwards.
   
   Results on Temurin JDK 8 (the JDK CI uses), base `0dd48c39d` plus this patch:
   
   - before the fix: `java.lang.AssertionError: a scratch file left by an 
interrupted round must not survive into the next round`
   - after the fix: `CompactionLogTest` — `Tests run: 5, Failures: 0, Errors: 
0, Skipped: 1` (the skip is the pre-existing `testReplaceFiles`, which is 
`Assume`d off on Windows)
   - `mvn -B -ntp -pl store package 
-Dtest='CompactionLogTest,CompactionPositionMgrTest,OffsetMapTest'`: `BUILD 
SUCCESS`, 9 tests / 0 failures, `You have 0 Checkstyle violations.`, 
`BugInstance size is 0`
   
   Disclosure: the whole `store` suite cannot be run on this machine (it 
crashes inside native RocksDB after roughly 45 test classes — unrelated to this 
change, and every affected class passes on its own), so I report the 
compaction-related classes plus the static checks rather than a full-module 
claim. The change touches file-based compaction code only and does not involve 
RocksDB.
   
   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.
   


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