"Stale" means that the remote peer closed the connection but we don't
know it until we try to reuse the connection, right? Because this is
definitely a problem with the async client. Users are seeing
`ConnectionClosedException` immediately thrown from the `execute`
method, and they're reaching for `setValidateAfterInactivity` to fix
it, which is unexpectedly closing perfectly good connections.

I don't have any further work planned for Unix domain socket support,
so my next task is to audit this. I'll come back with more information
on the stale connection handling of the sync and async clients on all
the LTS versions of Java. (One reason I also want to cover the sync
client is that JEP 353 might have subtly changed some behaviors on
Java 13+.)

On Tue, Jul 1, 2025 at 2:48 PM Oleg Kalnichevski <ol...@apache.org> wrote:
>
> On Tue, 2025-07-01 at 11:26 -0700, Ryan Schmitt wrote:
> > What is the intended behavior of `setValidateAfterInactivity` on the
> > async client with HTTP/1.1 connections? The current implementation
> > is:
> >
> > if (poolEntry.hasConnection()) {
> >     final ManagedAsyncClientConnection connection =
> > poolEntry.getConnection();
> >     final TimeValue timeValue =
> > connectionConfig.getValidateAfterInactivity();
> >     if (connection.isOpen() && TimeValue.isNonNegative(timeValue)) {
> >         if (timeValue.getDuration() == 0
> >                 || Deadline.calculate(poolEntry.getUpdated(),
> > timeValue).isExpired()) {
> >             final ProtocolVersion protocolVersion =
> > connection.getProtocolVersion();
> >             if (protocolVersion != null &&
> > protocolVersion.greaterEquals(HttpVersion.HTTP_2_0)) {
> >                 connection.submitCommand(new PingCommand(/* ... */,
> > Command.Priority.IMMEDIATE);
> >                 return;
> >             }
> >             if (LOG.isDebugEnabled()) {
> >                 LOG.debug("{} connection {} is closed", id,
> > ConnPoolSupport.getId(connection));
> >             }
> >             poolEntry.discardConnection(CloseMode.IMMEDIATE);
> >         }
> >     }
> > }
> >
> > In other words, the current implementation is actually just a
> > connection TTL. I got a report from someone who was seeing zero
> > connection reuse with their client after upgrading to 5.4, and it
> > turns out that it's because they were calling
> > `setValidateAfterInactivity(0)`. The intention was to _always_ check
> > for a stale connection before reuse, but it actually resulted in all
> > pooled connections being immediately closed, since 5.4 fixes the
> > handling of validateAfterInactivity/connectionTimeToLive being set to
> > `0`. This seems like a bug, but does Java provide us any way to fix
> > it?
>
> I do not think so. I do not know of a way to reliably perform a
> validity check on non-blocking connections other than sending a ping
> message. This obviously can only work with HTTP/2 only, so probably
> `validateAfterInactivity` should not apply to HTTP/1.1 connections at
> all. Generally non-blocking connections should never get stale like
> their blocking counterparts.
>
> Oleg
>
> >  I thought the usual trick was to perform a blocking read with a
> > 1ms timeout, which will surface the fact that the remote peer has
> > closed the connection.
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscr...@hc.apache.org
> For additional commands, e-mail: dev-h...@hc.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@hc.apache.org
For additional commands, e-mail: dev-h...@hc.apache.org

Reply via email to