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++
|
||||
}
|
||||
|
||||
n, err := b.conn.conn.Write(buf)
|
||||
_, err = b.conn.conn.Write(buf)
|
||||
if err != nil {
|
||||
if fatalWriteErr(n, err) {
|
||||
b.conn.die(err)
|
||||
}
|
||||
b.conn.die(err)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -1096,11 +1096,9 @@ func (c *Conn) prepareEx(name, sql string, opts *PrepareExOptions) (ps *Prepared
|
||||
buf = appendDescribe(buf, 'S', name)
|
||||
buf = appendSync(buf)
|
||||
|
||||
n, err := c.conn.Write(buf)
|
||||
_, err = c.conn.Write(buf)
|
||||
if err != nil {
|
||||
if fatalWriteErr(n, err) {
|
||||
c.die(err)
|
||||
}
|
||||
c.die(err)
|
||||
return nil, err
|
||||
}
|
||||
c.pendingReadyForQueryCount++
|
||||
@@ -1360,11 +1358,9 @@ func (c *Conn) sendPreparedQuery(ps *PreparedStatement, arguments ...interface{}
|
||||
buf = appendExecute(buf, "", 0)
|
||||
buf = appendSync(buf)
|
||||
|
||||
n, err := c.conn.Write(buf)
|
||||
_, err = c.conn.Write(buf)
|
||||
if err != nil {
|
||||
if fatalWriteErr(n, err) {
|
||||
c.die(err)
|
||||
}
|
||||
c.die(err)
|
||||
return err
|
||||
}
|
||||
c.pendingReadyForQueryCount++
|
||||
@@ -1372,17 +1368,6 @@ func (c *Conn) sendPreparedQuery(ps *PreparedStatement, arguments ...interface{}
|
||||
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.
|
||||
// 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) {
|
||||
@@ -1791,8 +1776,8 @@ func (c *Conn) execEx(ctx context.Context, sql string, options *QueryExOptions,
|
||||
buf = appendSync(buf)
|
||||
|
||||
c.lastStmtSent = true
|
||||
n, err := c.conn.Write(buf)
|
||||
if err != nil && fatalWriteErr(n, err) {
|
||||
_, err = c.conn.Write(buf)
|
||||
if err != nil {
|
||||
c.die(err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -418,8 +418,8 @@ func (c *Conn) QueryEx(ctx context.Context, sql string, options *QueryExOptions,
|
||||
buf = appendSync(buf)
|
||||
|
||||
c.lastStmtSent = true
|
||||
n, err := c.conn.Write(buf)
|
||||
if err != nil && fatalWriteErr(n, err) {
|
||||
_, err = c.conn.Write(buf)
|
||||
if err != nil {
|
||||
rows.fatal(err)
|
||||
c.die(err)
|
||||
return rows, err
|
||||
|
||||
Reference in New Issue
Block a user