@@ -556,7 +556,8 @@ func (pgConn *PgConn) receiveMessage() (pgproto3.BackendMessage, error) {
556556 return msg , nil
557557}
558558
559- // Conn returns the underlying net.Conn. This rarely necessary.
559+ // Conn returns the underlying net.Conn. This rarely necessary. If the connection will be directly used for reading or
560+ // writing then SyncConn should usually be called before Conn.
560561func (pgConn * PgConn ) Conn () net.Conn {
561562 return pgConn .conn
562563}
@@ -1740,6 +1741,30 @@ func (pgConn *PgConn) flushWithPotentialWriteReadDeadlock() error {
17401741 return err
17411742}
17421743
1744+ // SyncConn prepares the underlying net.Conn for direct use. PgConn may internally buffer reads or use goroutines for
1745+ // background IO. This means that any direct use of the underlying net.Conn may be corrupted if a read is already
1746+ // buffered or a read is in progress. SyncConn drains read buffers and stops background IO. In some cases this may
1747+ // require sending a ping to the server. ctx can be used to cancel this operation. This should be called before any
1748+ // operation that will use the underlying net.Conn directly. e.g. Before Conn() or Hijack().
1749+ //
1750+ // This should not be confused with the PostgreSQL protocol Sync message.
1751+ func (pgConn * PgConn ) SyncConn (ctx context.Context ) error {
1752+ for i := 0 ; i < 10 ; i ++ {
1753+ if pgConn .bgReader .Status () == bgreader .StatusStopped && pgConn .frontend .ReadBufferLen () == 0 {
1754+ return nil
1755+ }
1756+
1757+ err := pgConn .Ping (ctx )
1758+ if err != nil {
1759+ return fmt .Errorf ("SyncConn: Ping failed while syncing conn: %w" , err )
1760+ }
1761+ }
1762+
1763+ // This should never happen. Only way I can imagine this occuring is if the server is constantly sending data such as
1764+ // LISTEN/NOTIFY or log notifications such that we never can get an empty buffer.
1765+ return errors .New ("SyncConn: conn never synchronized" )
1766+ }
1767+
17431768// HijackedConn is the result of hijacking a connection.
17441769//
17451770// Due to the necessary exposure of internal implementation details, it is not covered by the semantic versioning
@@ -1754,9 +1779,9 @@ type HijackedConn struct {
17541779 Config * Config
17551780}
17561781
1757- // Hijack extracts the internal connection data. pgConn must be in an idle state. pgConn is unusable after hijacking.
1758- // Hijacking is typically only useful when using pgconn to establish a connection, but taking complete control of the
1759- // raw connection after that (e.g. a load balancer or proxy).
1782+ // Hijack extracts the internal connection data. pgConn must be in an idle state. SyncConn should be called immediately
1783+ // before Hijack. pgConn is unusable after hijacking. Hijacking is typically only useful when using pgconn to establish
1784+ // a connection, but taking complete control of the raw connection after that (e.g. a load balancer or proxy).
17601785//
17611786// Due to the necessary exposure of internal implementation details, it is not covered by the semantic versioning
17621787// compatibility.
0 commit comments