Skip to content

[ISSUE #10668] Handle stale Timer references after CommitLog truncation - #10741

Open
btlqql wants to merge 1 commit into
apache:developfrom
btlqql:btlqql/rocketmq-10668-timer-truncate
Open

[ISSUE #10668] Handle stale Timer references after CommitLog truncation#10741
btlqql wants to merge 1 commit into
apache:developfrom
btlqql:btlqql/rocketmq-10668-timer-truncate

Conversation

@btlqql

@btlqql btlqql commented Aug 1, 2026

Copy link
Copy Markdown

What is changed

  • Notify TimerMessageStore after DefaultMessageStore truncation and clamp its consume-queue cursor.
  • Release queued timer requests that reference truncated CommitLog offsets.
  • Fast-fail out-of-range CommitLog reads and reject stale/non-timer messages before enqueue/dequeue conversion.
  • Add regression coverage for invalid timer messages and stale request cleanup.

Why

After CommitLog truncation, TimerLog entries can still reference offsets that are gone or later overwritten. The timer pipeline could repeatedly retry those requests and prevent dequeue progress.

Tests

  • Server compile: mvn -pl store -am -DskipTests ... compile
  • Server tests: mvn -pl store -am -Dtest=TimerMessageStoreTest -DfailIfNoTests=false ... test
  • Result: 12 tests, 0 failures, 0 errors, 0 skipped.
  • git diff --check

Fixes #10668

@btlqql
btlqql marked this pull request as ready for review August 1, 2026 13:57

@RockteMQ-AI RockteMQ-AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review by github-manager-bot

Summary

Fixes a data integrity gap where TimerMessageStore could retain stale references after CommitLog truncation. Adds truncation notification from DefaultMessageStore, drains/filters stale timer requests, clamps cursor offsets, validates timer messages before enqueue/dequeue, and adds bounds checking to getMessageByCommitOffset.

Findings

  • [Info] DefaultMessageStore.java:806-808 — Null-guarded notification to TimerMessageStore after truncation is correctly placed after recoverTopicQueueTable() and before reput service restart. Good integration point.
  • [Info] TimerMessageStore.java:1129-1163onCommitLogDispatchTruncate correctly handles three queues:
    • enqueuePutQueue / dequeuePutQueue: drained via discardTruncatedRequests, stale requests released with idempotentRelease(false)
    • dequeueGetQueue: drained list-by-list, filtered, and re-offered
    • Cursor clamping: currQueueOffset and commitQueueOffset are clamped to valid range, then checkpointed
  • [Info] TimerMessageStore.java:1213-1218 — Bounds check in getMessageByCommitOffset avoids unnecessary retry loops when offset is clearly outside CommitLog range. Good performance optimization.
  • [Info] TimerMessageStore.java:1231-1245isValidTimerMessage validates topic, real topic, and real queue ID. Package-private visibility enables direct unit testing.
  • [Info] Enqueue/dequeue paths now skip invalid timer messages with warning logs instead of processing potentially corrupted data.
  • [Info] Tests cover both message validation and truncation cleanup scenarios.

Minor Observations

  • [Info] TimerMessageStore.java:1141-1152 — The drain-and-reoffer pattern on dequeueGetQueue is not atomic. If another thread adds items between drain and reoffer, those items could be temporarily invisible. In practice, this queue is likely only accessed by the dequeue thread, so this should be safe. Worth a comment for future maintainers.
  • [Info] TimerMessageStore.java:1215offsetPy > maxPhyOffset - sizePy could theoretically underflow if maxPhyOffset < sizePy, but this should never happen with a valid CommitLog. No action needed.

Assessment

Solid fix for a real data integrity issue. The approach is thorough — covering notification, cleanup, validation, and bounds checking. Well-tested.


Automated review by github-manager-bot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Timer dequeue may get stuck after CommitLog truncation due to stale TimerLog references

2 participants