Skip to content

Reuse keep-alive HTTP connections after a fully read response - #587

Merged
slabko merged 1 commit into
masterfrom
keep-alive-connection-reuse
Sep 25, 2026
Merged

slabko merged 1 commit into
masterfrom
keep-alive-connection-reuse

Conversation

@slabko

@slabko slabko commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

The driver dropped the keep-alive connection after every request. Before sending a new request, and when closing a cursor, it checked the previous response stream with in->fail() || !in->eof(). AmortizedIStreamReader reads ahead in blocks of at least 8 KB, so the read that reaches the end of the body always stops short and sets both eofbit and failbit. That is the normal end-of-response state, but the check treated it as an error and reset the session, so every query opened a new TCP connection (and a new TLS handshake over HTTPS).

The driver dropped the keep-alive connection after every request. Before
sending a new request, and when closing a cursor, it checked the previous
response stream with `in->fail() || !in->eof()`. AmortizedIStreamReader
reads ahead in blocks of at least 8 KB, so the read that reaches the end
of the body always stops short and sets both eofbit and failbit. That is
the normal end-of-response state, but the check treated it as an error
and reset the session, so every query opened a new TCP connection (and a
new TLS handshake over HTTPS).

Replace the check with Statement::resetConnectionIfNeeded(), which resets
the session only when the stream is bad, the body has unread bytes, or
the session recorded a socket exception. closeCursor() now destroys the
result reader before inspecting the stream: the reader's destructor puts
back pre-read bytes, which clears eofbit and can set badbit, so checking
first could reuse a connection that still has unread rows on the wire.

Test server: serve multiple requests per connection so keep-alive can
actually be exercised, bind to an ephemeral loopback port instead of the
hard-coded 8124, count accepted connections, and guard the response data
with a mutex. Fix the ANSI networking test binary, which loaded the
Unicode driver, and size the zstd output buffer with ZSTD_compressBound
so compressing an empty body no longer produces a zero-length buffer.

Add tests asserting the connection count across repeated selects and
inserts (chunked, Content-Length, compressed), and that the driver
reconnects when the server closes, when a cursor is closed with unread
data, and after an incomplete response.
@slabko
slabko requested a review from mzitnik as a code owner September 24, 2026 18:01
@slabko
slabko merged commit 391ff70 into master Sep 25, 2026
20 checks passed
@slabko
slabko deleted the keep-alive-connection-reuse branch September 25, 2026 10:35
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