[fix][test] Run makeReadEntryProbFail's errorOrNot on a caller-provided executor - #26123
Merged
merlimat merged 2 commits intoJul 1, 2026
Merged
Conversation
…eReadEntryProbFail The injected readUnconfirmedAsync answer evaluated the errorOrNot supplier on the thread that calls readUnconfirmedAsync. When a test supplies a blocking implementation, that read thread is held for the whole duration of the block and the test can deadlock. For example, PersistentReplicatorInflightTaskTest#testReadEntriesFailedCompletesInFlightTaskAfterReplicatorTerminated waits on a CountDownLatch before returning the failure, so its failRead.await(30, SECONDS) always timed out. Evaluate errorOrNot with CompletableFuture.supplyAsync so it runs on ForkJoinPool.commonPool(), leaving the caller thread free, and compose the resulting read future with thenCompose.
merlimat
approved these changes
Jul 1, 2026
…ed executor The previous commit routed every intercepted read through CompletableFuture.supplyAsync (ForkJoinPool.commonPool()) to keep a blocking errorOrNot off the caller thread. That funnels all managed ledger reads through a shared, unordered pool and starved OneWayReplicatorTest.testProbBKErrorWhenReplicating (10k messages), which timed out its 45s limit on CI where the common pool has few threads. makeReadEntryProbFail now takes an Executor that runs errorOrNot, letting each caller decide where it runs: - OneWayReplicatorTest.testProbBKErrorWhenReplicating passes MoreExecutors.directExecutor() to keep read interception inline and ordered on the calling thread (its errorOrNot never blocks). - The blocking PersistentReplicatorInflightTaskTest cases pass a dedicated single-threaded executor (@cleanup("shutdownNow")) so a blocking errorOrNot runs off the read thread while reads stay ordered.
sandeep-ctds
pushed a commit
to datastax/pulsar
that referenced
this pull request
Jul 31, 2026
…ed executor (apache#26123) (cherry picked from commit 12d8aa9)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
ManagedLedgerTest.makeReadEntryProbFailinstalls a Mockito answer onLedgerHandle.readUnconfirmedAsyncthat consults a caller-suppliedSupplier<ManagedLedgerException>(errorOrNot) to decide whether a read shouldfail.
errorOrNotwas evaluated directly on the thread that callsreadUnconfirmedAsync.When a test supplies a blocking
errorOrNot, that read thread is held for thewhole duration of the block, which can stall or deadlock the test. For example,
PersistentReplicatorInflightTaskTest#testReadEntriesFailedCompletesInFlightTaskAfterReplicatorTerminated(added in #25767) blocks in
errorOrNoton aCountDownLatchuntil the testreleases it after terminating the replicator. Because the calling thread was
blocked, the test flow could not make progress and its
failRead.await(30, SECONDS)always timed out.Modifications
makeReadEntryProbFailnow takes anExecutorthat runserrorOrNot, so eachcaller decides where it runs (composing the resulting read via
thenCompose).OneWayReplicatorTest.testProbBKErrorWhenReplicatingpassesMoreExecutors.directExecutor()to keep read interception inline and orderedon the calling thread — its
errorOrNotnever blocks.PersistentReplicatorInflightTaskTestcases pass adedicated single-threaded executor (
@Cleanup("shutdownNow")) so a blockingerrorOrNotruns off the read thread while reads stay ordered.This only touches test code; production code is unaffected.
Verifying this change
This change is covered by the existing tests that use
makeReadEntryProbFail.Verified locally:
OneWayReplicatorTest.testProbBKErrorWhenReplicating: passes in ~17s.PersistentReplicatorInflightTaskTest: 15 tests, 0 failures, includingtestReadEntriesFailedCompletesInFlightTaskAfterReplicatorTerminated.Make sure that the change passes the CI checks.
Does this pull request potentially affect one of the following parts: