Conversation
Exit the per-key creation wait when its initially positive budget is exhausted, using the existing path to release the maxTotal reservation. Leave zero and negative duration handling unchanged. Add a latch-controlled regression that requires a waiting borrower to finish before the in-flight creation completes and checks global capacity is available to another key after the timeout.
Replace the single blocked factory call with six concurrent borrowers. Each creation attempt fails after three seconds, with maxWait set to ten seconds. Verify that queued borrowers time out and release their pool reservations.
baldwk
force-pushed
the
fix/pool-420-creation-timeout
branch
from
September 28, 2026 07:43
eeb23ed to
a875b8d
Compare
baldwk
force-pushed
the
fix/pool-420-creation-timeout
branch
from
September 28, 2026 07:53
a875b8d to
eeb23ed
Compare
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.
When other threads are creating objects and have filled the slots for a key,
GenericKeyedObjectPool.create()can keep looping aftermaxWaitexpires. OnceremainingWaitDurationbecomes negative, the loop skipswait()but leavescreateasnull, so the borrower spins until another factory call finishes.Exit the loop when the wait expires. The existing return path releases the reservation against
maxTotal.Follow-up to POOL-420, targeting
POOL_2_X.How to reproduce
Six threads borrow objects for the same key with
maxTotal = 6,maxTotalPerKey = 1, andmaxWait = 10s. Each creation attempt takes 3 seconds and fails. The threads take turns trying to create an object; before this fix, the last borrower can wait about 15 seconds before starting its own attempt.The regression starts six borrowers together and simulates each connection failure with a 3-second delay followed by
SocketTimeoutException. It checks that queued borrowers getNoSuchElementExceptionand that the pool can reuse the released capacity.Validation (JDK 21)
a0c13d55) after about 18 seconds and passes with the fix.Related behavior to clarify:
blockWhenExhausted=falseA separate local reproduction on Commons Pool 2.12.1 showed that
blockWhenExhausted=falsecan still wait when in-flight factory calls occupy all creation slots for a key. I am not sure whether this is intentional.The borrowObject Javadoc describes an exhausted sub-pool as having no available idle instances and no capacity to create new ones, and specifies
NoSuchElementExceptionwhenblockWhenExhaustedis false. The expected behavior below is my reading of that contract; the last row is the part that needs clarification.blockWhenExhausted=falseNoSuchElementExceptionwithout waiting for capacity.For the last row, the reproduction used
maxTotal=24,maxTotalPerKey=1,maxWait=1s, andblockWhenExhausted=false. One factory call held the creation slot for about 3 seconds and then failed. At about 1.3 seconds, a second borrower was still waiting insidecreate()and had not entered its own factory call. It eventually returned after about 3.03 seconds. ThemaxWaitvalue is included for reproducibility; the question forfalseis whether it should wait for capacity at all.This PR addresses expiry of a positive creation-wait budget. It does not implement immediate failure for the last scenario when
blockWhenExhausted=false. Could maintainers confirm whether waiting for in-flight creation is intended in this mode, or whether this should be handled as a separate fix?