All Write errors are fatal
With TLS connections a Write timeout caused by a SetDeadline permanently breaks the connection. However, the errors are reported as temporary. So there is no way to determine if it really is recoverable. As these were the only kind of Write error that was recovered all Write errors are now fatal to the connection. https://github.com/jackc/pgx/issues/494 https://github.com/jackc/pgx/issues/506 https://github.com/golang/go/issues/29971
This commit is contained in:
@@ -133,11 +133,9 @@ func (b *Batch) Send(ctx context.Context, txOptions *TxOptions) error {
|
|||||||
b.conn.pendingReadyForQueryCount++
|
b.conn.pendingReadyForQueryCount++
|
||||||
}
|
}
|
||||||
|
|
||||||
n, err := b.conn.conn.Write(buf)
|
_, err = b.conn.conn.Write(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if fatalWriteErr(n, err) {
|
b.conn.die(err)
|
||||||
b.conn.die(err)
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1096,11 +1096,9 @@ func (c *Conn) prepareEx(name, sql string, opts *PrepareExOptions) (ps *Prepared
|
|||||||
buf = appendDescribe(buf, 'S', name)
|
buf = appendDescribe(buf, 'S', name)
|
||||||
buf = appendSync(buf)
|
buf = appendSync(buf)
|
||||||
|
|
||||||
n, err := c.conn.Write(buf)
|
_, err = c.conn.Write(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if fatalWriteErr(n, err) {
|
c.die(err)
|
||||||
c.die(err)
|
|
||||||
}
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
c.pendingReadyForQueryCount++
|
c.pendingReadyForQueryCount++
|
||||||
@@ -1360,11 +1358,9 @@ func (c *Conn) sendPreparedQuery(ps *PreparedStatement, arguments ...interface{}
|
|||||||
buf = appendExecute(buf, "", 0)
|
buf = appendExecute(buf, "", 0)
|
||||||
buf = appendSync(buf)
|
buf = appendSync(buf)
|
||||||
|
|
||||||
n, err := c.conn.Write(buf)
|
_, err = c.conn.Write(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if fatalWriteErr(n, err) {
|
c.die(err)
|
||||||
c.die(err)
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c.pendingReadyForQueryCount++
|
c.pendingReadyForQueryCount++
|
||||||
@@ -1372,17 +1368,6 @@ func (c *Conn) sendPreparedQuery(ps *PreparedStatement, arguments ...interface{}
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// fatalWriteError takes the response of a net.Conn.Write and determines if it is fatal
|
|
||||||
func fatalWriteErr(bytesWritten int, err error) bool {
|
|
||||||
// Partial writes break the connection
|
|
||||||
if bytesWritten > 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
netErr, is := err.(net.Error)
|
|
||||||
return !(is && netErr.Timeout())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exec executes sql. sql can be either a prepared statement name or an SQL string.
|
// Exec executes sql. sql can be either a prepared statement name or an SQL string.
|
||||||
// arguments should be referenced positionally from the sql string as $1, $2, etc.
|
// arguments should be referenced positionally from the sql string as $1, $2, etc.
|
||||||
func (c *Conn) Exec(sql string, arguments ...interface{}) (commandTag CommandTag, err error) {
|
func (c *Conn) Exec(sql string, arguments ...interface{}) (commandTag CommandTag, err error) {
|
||||||
@@ -1791,8 +1776,8 @@ func (c *Conn) execEx(ctx context.Context, sql string, options *QueryExOptions,
|
|||||||
buf = appendSync(buf)
|
buf = appendSync(buf)
|
||||||
|
|
||||||
c.lastStmtSent = true
|
c.lastStmtSent = true
|
||||||
n, err := c.conn.Write(buf)
|
_, err = c.conn.Write(buf)
|
||||||
if err != nil && fatalWriteErr(n, err) {
|
if err != nil {
|
||||||
c.die(err)
|
c.die(err)
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -418,8 +418,8 @@ func (c *Conn) QueryEx(ctx context.Context, sql string, options *QueryExOptions,
|
|||||||
buf = appendSync(buf)
|
buf = appendSync(buf)
|
||||||
|
|
||||||
c.lastStmtSent = true
|
c.lastStmtSent = true
|
||||||
n, err := c.conn.Write(buf)
|
_, err = c.conn.Write(buf)
|
||||||
if err != nil && fatalWriteErr(n, err) {
|
if err != nil {
|
||||||
rows.fatal(err)
|
rows.fatal(err)
|
||||||
c.die(err)
|
c.die(err)
|
||||||
return rows, err
|
return rows, err
|
||||||
|
|||||||
Reference in New Issue
Block a user