Skip to content

HERESUP-98784: RetryExecutor to close the response it abandons, releasing the connection - #166

Merged
ashishKhushiKumar merged 1 commit into
heremaps:masterfrom
Azbesciak:HERESUP-98784
Oct 14, 2026
Merged

ashishKhushiKumar merged 1 commit into
heremaps:masterfrom
Azbesciak:HERESUP-98784

Conversation

@Azbesciak

Copy link
Copy Markdown
Contributor

HERESUP-98784

RetryExecutor never closes the response it abandons, so a pooled HttpProvider never gets that connection back. Once every connection for the route has leaked this way, the next attempt blocks on the connection-request timeout and the call fails with a pool timeout instead of the status the server sent.

HereAccessTokenProvider with a stock ApacheHttpClientProvider and Socket5xxExponentialRandomBackoffPolicy, against a server scripted 503, 503, 200: before, two requests, then ConnectionPoolTimeoutException after ~11 s. After, three requests and the token.

Affected: anyone passing a response-retrying policy to setRetryPolicy/withRetryPolicy, in 0.4.33 through 0.4.36. Callers on the NoRetryPolicy default are not.

The fix closes the abandoned response before the next attempt starts. The closed response stays in the RetryContext, so a policy sees exactly what it saw before, and the response handed back to the caller is never closed.

Apache's close() drains the body, so a 5xx whose body stalls now costs one read timeout before the retry. Against a server that sends a partial body then hangs, 8 ms became 5 s. Aborting instead is not reachable through HttpProvider.HttpResponse.

Also found, not fixed here

  • Socket5xxExponentialRandomBackoffPolicy.shouldRetry: the getCause() instanceof SocketTimeoutException arm sits outside the maxNumberOfRetries check. A connect timeout arrives in that shape, so an unreachable endpoint retries without bound.
  • getNextRetryIntervalMillis computes retryIntervalMillis * nextInt(1 << retryCount) in int: 0 ms on about half of first retries, negative from retryCount 22, IllegalArgumentException at 31.
  • RetryExecutor swallows InterruptedException without restoring the interrupt flag.
  • ApacheHttpClientProvider builds JSON bodies as a non-repeatable BasicHttpEntity, so a retried JSON-body request resends an empty body. Form-encoded requests, including the token endpoint, are fine.

…sing the connection

A pooled HttpProvider ran out of connections after as many attempts as the pool holds per route, so the caller saw a connection-pool timeout instead of the response the server sent. A token fetch against a server answering 503, 503, 200 used to reach the server twice and fail; it now reaches it three times and returns the token.
@ashishKhushiKumar
ashishKhushiKumar merged commit 0b9a5af into heremaps:master Oct 14, 2026
2 checks passed
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.

2 participants