[fix][test] Fix flaky AdminApiTest caused by leaked brokerShutdownTimeoutMs - #26249
Merged
Merged
Conversation
…eoutMs testGetDynamicLocalConfiguration lowers the brokerShutdownTimeoutMs dynamic configuration to 10ms and never restores it. The broker applies dynamic configuration changes asynchronously, so the value can become effective while a later test method shuts the broker down. PulsarService#close then fails with "Timeout in close", stopBroker() propagates the exception without clearing the pulsar field, and the @AfterMethod fails with "Connection refused" against the broker that is no longer listening. A failing configuration method makes TestNG skip every remaining test method of the class. Restore the dynamic configuration in resetClusters() and skip the cleanup when the broker isn't running, so a single failure can no longer take down the whole class. Assisted-by: Claude Code (Opus 5)
nodece
approved these changes
Jul 27, 2026
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
AdminApiTestcan fail with the whole class collapsing after a single test method: the@AfterMethod(resetClusters) fails withConnection refusedand TestNG then skips everyremaining test method of the class.
The same failure was observed on
branch-4.0inV1AdminApiTest,which is the copy of this class that PIP-457 (#25304) removed from master. The bug itself is still
present in
AdminApiTeston master.The causal chain:
testGetDynamicLocalConfigurationlowers thebrokerShutdownTimeoutMsdynamicconfiguration to
10ms and never restores it. It only asserts the stored value; the brokerapplies dynamic configuration changes asynchronously, so whether the value has reached
pulsar.getConfiguration()by the time the next test method runs is a race — that is where theflakiness comes from.
The next test method in alphabetical order,
testInvalidDynamicConfigContentInMetadata, startswith
stopBroker(). With a 10 ms budgetPulsarService#closefails:MockedPulsarServiceBaseTest.stopBroker()runspulsar.close(); pulsar = null;, so the thrownexception skips the assignment and the test is left holding a broker that is no longer
listening, together with the
adminclient pointing at its web service port.resetClusters()then callsadmin.tenants().getTenants()and fails withConnection refused.Because it is a configuration method, TestNG skips all remaining test methods of the class
(19 in the CI run above) and the build fails.
TestRetrySupportdoes recreate the test contextfor the retry, and the retried test passes, but the configuration failure has already been
recorded.
Modifications
In
AdminApiTest:restoreBrokerShutdownTimeout()and call it at the start ofresetClusters(). It removesthe
brokerShutdownTimeoutMsdynamic configuration (which makes the broker restore the value itwas started with) and waits until the value the broker uses is no longer the override, so no
test method can leave a ~10 ms shutdown budget behind for a later
stopBroker()/restartBroker().resetClusters()when the broker isn't running, with a warning. Throwing froma configuration method skips every remaining test method of the class;
TestRetrySupportalready recreates the shared test context before the next test method runs.
testGetDynamicLocalConfigurationwait until the broker has applied the value it sets.This is a small strengthening of the test itself, and it turns the race into a deterministic
case that the
@AfterMethodhas to handle, so a regression fails consistently instead offlaking.
No production code is changed.
Verifying this change
This change is already covered by existing tests, such as
AdminApiTest.The failure was reproduced deterministically before fixing it, by making the asynchronous
propagation in
testGetDynamicLocalConfigurationexplicit and runningtestGetDynamicLocalConfiguration,testInvalidDynamicConfigContentInMetadataandtestJacksonWithTypeDifferenciestogether. On master that run fails with exactly the CIsignature —
FutureUtil$LowOverheadTimeoutException: Timeout in closeon the test method andPulsarAdminException ... Connection refusedonresetClusters, with the following test methodskipped — and it passes with this change.
The full
AdminApiTestclass was run before and after the change: 100 tests, 0 failures in bothruns. The single retried
testUpdateDynamicLoadBalancerSheddingIntervalMinutesbehaves identicallyon unmodified master (it asserts on the
conffield thatresetConfig()replaces in every@AfterMethod, so it only passes onceTestRetrySupporthas re-run the setup); it is unrelated tothis change.
branch-4.0still carriesV1AdminApiTestwith the same problem and will need a separate fix; itcannot inherit this one.
Does this pull request potentially affect one of the following parts:
If the box was checked, please highlight the changes