Skip to content

Add an optional client-side read timeout for established connections #728

Description

@star-sil

Feature Request

Is your feature request related to a problem? Please describe

An established TCP connection can remain open when PostgreSQL protocol responses stop reaching the client.
This can happen when a firewall or network path silently drops return traffic or when a failover leaves an existing socket half-open without promptly delivering a FIN, RST, or error.
The driver has no client-side deadline for this state so an in-flight publisher can wait indefinitely.
Subscriber or pool-level timeouts do not guarantee physical channel termination, potentially blocking cleanup and pool capacity.

Describe the solution you'd like

Please consider an optional client-side response-inactivity timeout represented as a Duration and disabled by default.
While a protocol response is outstanding, it would limit the interval with no inbound PostgreSQL protocol data.
On expiry the driver should close the channel, fail all in-flight publishers with a connection-level resource error and prevent reuse.

Unlike a total query deadline, the timer would reset when relevant inbound protocol data arrives.
A long result stream could therefore continue while data is arriving but a quiet long-running statement could time out.
This is a channel safeguard, not automatic CancelRequest on subscriber cancellation so all pipelined operations on the same channel can fail together.

Describe alternatives you've considered

  • connectTimeout only covers connection establishment.
  • statementTimeout is enforced by PostgreSQL, so the client must still receive its error response.
  • tcpKeepAlive is OS-dependent and can consider a reachable proxy endpoint healthy.
  • Reactor timeout() cancels a publisher but does not guarantee physical channel termination.
  • A pool lease timeout cannot abort the driver's in-flight protocol operation or socket.

This differs from #381 (statementTimeout), #251 (CancelRequest on cancellation), and #595 (connection establishment).

Teachability, Documentation, Adoption, Migration Strategy

The option would be opt-in and accept an ISO-8601 duration in the builder and connection URL, for example:

r2dbc:postgresql://user:password@host/database?socketTimeout=PT30S

The exact option name (socketTimeout or readTimeout) and which inbound protocol events reset the timer can be agreed before implementation. I am willing to work on it after those semantics are confirmed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions