Skip to content

Fix the defects the rerunner removal uncovered - #2345

Merged
hyperxpro merged 13 commits into
mainfrom
fix/rerunner-followup-findings
Sep 21, 2026
Merged

hyperxpro merged 13 commits into
mainfrom
fix/rerunner-followup-findings

Conversation

@hyperxpro

Copy link
Copy Markdown
Member

Motivation:

Removing @RepeatedIfExceptionsTest (#2343) surfaced defects that were left out of that PR:

  • The connection permit was returned only after the handler's onThrowable ran. A handler that re-submitted from there under maxConnections was refused with TooManyConnectionsException. NettyRequestThrottleTimeoutTest could not see it because its assertion was vacuous.
  • An unreachable peer (NoRouteToHostException) was retried on NIO but not on native transports.
  • A WebSocket send after close failed with a different exception depending on TLS timing, and isOpen() stayed true.
  • When onRetry() threw, its exception replaced the real failure cause.
  • Nothing stopped a connect failure from replaying a request that was already written.
  • Several tests asserted nothing, slept, or shared static state. CI jobs had no timeout.

Modification:

  • Release the permit in NettyRequestSender.abort before the handler is notified, through a new Channels.releasePermit. It is public only because the caller is in another package, and it is marked internal. A channel that gave its permit back is never pooled. HTTP/2 connections keep theirs.
  • Close an aborted channel without waiting on the SslHandler's close_notify flush. HTTP/2 closes stay graceful.
  • Treat NoRouteToHostException as a retryable connect failure on every transport.
  • Add a write guard to the WebSocket pipeline that fails sends with ClosedChannelException once the peer's Close has been handled. A listener can still answer from onClose.
  • retry() returns false when onRetry() throws, so the caller aborts with the real cause.
  • NettyConnectListener.onFailure never replays once the request is written.
  • Inject clocks into CombinedConnectionSemaphore and TimeoutsHolder through package-private constructors. The semaphore now times its budget with nanoTime.

Result:

A handler can re-submit from onThrowable without being refused, and failures report their real cause. WebSocket sends after close fail the same way on ws and wss

@hyperxpro hyperxpro changed the title Fix/rerunner followup findings Fix the defects the rerunner removal uncovered Sep 21, 2026
@hyperxpro
hyperxpro merged commit 09f7dca into main Sep 21, 2026
17 checks passed
@hyperxpro
hyperxpro deleted the fix/rerunner-followup-findings branch September 21, 2026 21:38
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.

1 participant