Skip to content

feat: add custom transport support for Postgres and MySQL#4281

Open
Benjscho wants to merge 2 commits into
launchbadge:mainfrom
Benjscho:feat/custom-socket-async-rw
Open

feat: add custom transport support for Postgres and MySQL#4281
Benjscho wants to merge 2 commits into
launchbadge:mainfrom
Benjscho:feat/custom-socket-async-rw

Conversation

@Benjscho
Copy link
Copy Markdown

Add methods to PgConnection and MySqlConnection that accept pre-connected sockets implementing AsyncRead + AsyncWrite, enabling custom transport layers (vsock, QUIC, turmoil, SSH tunnels, etc.) without forking sqlx.

Per feedback on #4187, this uses AsyncRead + AsyncWrite traits instead of exposing the internal Socket trait. Two separate methods are provided for each runtime's trait set:

  • connect_with_custom_tokio(): accepts tokio::io::{AsyncRead, AsyncWrite}
  • connect_with_custom_futures(): accepts futures_io::{AsyncRead, AsyncWrite}

Also adds PoolOptions::connector() so pools can use custom transports:

PgPoolOptions::new()
    .connector(|options| async move {
        let socket = VsockStream::connect(addr).await?;
        PgConnection::connect_with_custom_tokio(socket, &options).await
    })
    .connect_with(options)
    .await?

TLS upgrade is negotiated automatically based on the connection options. No new public trait exposure. No behavioral changes to existing code.

Does your PR solve an issue?

No

Is this a breaking change?

No, it is additive with no behavior changes.

@Benjscho Benjscho force-pushed the feat/custom-socket-async-rw branch from aa95915 to ea6f530 Compare May 25, 2026 18:07
Add methods to PgConnection and MySqlConnection that accept pre-connected
sockets implementing AsyncRead + AsyncWrite, enabling custom transport
layers (vsock, QUIC, turmoil, SSH tunnels, etc.) without forking sqlx.

Per maintainer feedback on launchbadge#4187, this uses AsyncRead + AsyncWrite traits
instead of exposing the internal Socket trait. Two separate methods are
provided for each runtime's trait set:

- connect_with_custom_tokio(): accepts tokio::io::{AsyncRead, AsyncWrite}
- connect_with_custom_futures(): accepts futures_io::{AsyncRead, AsyncWrite}

Also adds PoolOptions::connector() so pools can use custom transports:

    PgPoolOptions::new()
        .connector(|options| async move {
            let socket = VsockStream::connect(addr).await?;
            PgConnection::connect_with_custom_tokio(socket, &options).await
        })
        .connect_with(options)
        .await?

TLS upgrade is negotiated automatically based on the connection options.
No new public trait exposure. No behavioral changes to existing code.
@Benjscho Benjscho force-pushed the feat/custom-socket-async-rw branch 4 times, most recently from 6fdce0f to 073247c Compare May 25, 2026 21:37
@Benjscho Benjscho force-pushed the feat/custom-socket-async-rw branch from 073247c to 0704cd9 Compare May 25, 2026 21:44
@Benjscho Benjscho marked this pull request as ready for review May 25, 2026 23:27
@Benjscho
Copy link
Copy Markdown
Author

@abonander would you be able to take a look at this when you have time? This was me taking a swing at addressing feedback on #4187.

const ADAPTER_BUF_SIZE: usize = 8192;

/// Generates an adapter struct + `Socket` impl for a given async I/O trait family.
macro_rules! impl_socket_adapter {
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This macro was to avoid repeating the code across tokio & futures, but happy to just expand it out if it makes things too unreadable

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