Skip to content

[ISSUE #10989] Fix transactional message escape retry backoff (2 ^ n computed with XOR) - #10993

Open
unbridled-41 wants to merge 1 commit into
apache:developfrom
unbridled-41:fix/transaction-escape-backoff
Open

[ISSUE #10989] Fix transactional message escape retry backoff (2 ^ n computed with XOR)#10993
unbridled-41 wants to merge 1 commit into
apache:developfrom
unbridled-41:fix/transaction-escape-backoff

Conversation

@unbridled-41

@unbridled-41 unbridled-41 commented Aug 29, 2026

Copy link
Copy Markdown

Which Issue(s) This PR Fixes

Brief Description

In TransactionalMessageServiceImpl#check, the retry delay between failed escape attempts (broker with enableSlaveActingMaster, escapeMessage failing) was computed as

Thread.sleep(100L * (2 ^ escapeFailCnt));

In Java ^ is XOR, not exponentiation, so the actual sleep sequence for escapeFailCnt = 1..10 was 300, 0, 100, 600, 700, 400, 500, 1000, 1100, 800 ms — non-monotonic and including a 0 ms delay on the second failure, which defeats the backoff entirely and hammers the store with immediate re-puts.

This PR extracts the computation into a package-private helper escapeRetryBackoffMillis(int) that returns the intended exponential backoff 100L * (1 << escapeFailCnt) (200, 400, 800, ... ms), and uses it at the call site. No behavior other than the delay values changes.

How Did You Test This Change?

Added TransactionalMessageServiceImplTest#testEscapeRetryBackoffMillisIsExponential, which asserts escapeRetryBackoffMillis(i) == 100L * (1L << i) for i = 1..10. It fails on the old code (XOR sequence) and passes with this change.

mvn -pl broker test -Dtest=TransactionalMessageServiceImplTest passes (9/9).

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

Summary

This PR fixes a bug in the transactional message escape retry backoff calculation. The original code used 2 ^ escapeFailCnt which is XOR operation in Java, not exponentiation. The fix correctly uses 1 << escapeFailCnt (bit shift) to compute 2^n, and extracts the calculation into a separate method for clarity. A test case is added to verify the exponential backoff behavior.

LGTM — good catch on the XOR vs exponentiation bug!


Automated review by github-manager-bot

@unbridled-41

Copy link
Copy Markdown
Author

Test evidence (before → after)

The sleep-sequence claim was verified by directly evaluating both expressions for escapeFailCnt = 1..10 (plain JDK 8):

old 100L * (2 ^ n)  : 300, 0, 100, 600, 700, 400, 500, 1000, 1100, 800
new 100L * (1 << n) : 200, 400, 800, 1600, 3200, 6400, 12800, 25600, 51200, 102400

(The sequences in the description and in #10989 have been corrected accordingly — n=8/9/10 evaluate to 1000/1100/800, not 800/900/200.)

Key point: 2 ^ 2 == 0 in Java (XOR), so the second consecutive escape failure sleeps 0 ms and immediately re-attempts the store put; and the sequence is non-monotonic throughout, so this cannot be an intentional policy.

TransactionalMessageServiceImplTest#testEscapeRetryBackoffMillisIsExponential asserts the new helper escapeRetryBackoffMillis(i) == 100L * (1L << i) for i = 1..10. Two notes on the test itself:

  • The helper was introduced by this fix, so the test cannot compile against the unfixed code — the before/after evidence for the wrong values is the expression evaluation above.
  • On the fixed code: mvn -pl broker test -Dtest=TransactionalMessageServiceImplTestTests run: 9, Failures: 0, Errors: 0, Skipped: 0 (8 pre-existing + 1 new).

The production call site (Thread.sleep(escapeRetryBackoffMillis(escapeFailCnt))) is the only place the delay is computed, so unit-testing the helper covers the behavioral change fully.

Side note on CI: the workflow runs for this PR are in action_required state (first-time contributor) and will start once a maintainer approves them.

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] Transactional message escape retry uses 2 ^ n (XOR) instead of exponential backoff, including a zero-delay retry

2 participants