Skip to content

Commit cb84236

Browse files
committed
Added read_timeout and write_timeout (in milliseconds) to the connection string parameters and use them on reads and writes to the database connection
1 parent 65bc794 commit cb84236

1 file changed

Lines changed: 71 additions & 0 deletions

File tree

conn.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,12 @@ type conn struct {
132132
// round-trip mode for non-prepared Query calls.
133133
binaryParameters bool
134134

135+
// Timeouts for read and write operations against the database server.
136+
// A duration of 0 indicates no timeout.
137+
// specified in milliseconds
138+
readTimeout time.Duration
139+
writeTimeout time.Duration
140+
135141
// If true this connection is in the middle of a COPY
136142
inCopy bool
137143
}
@@ -151,6 +157,28 @@ func (cn *conn) handleDriverSettings(o values) (err error) {
151157
return nil
152158
}
153159

160+
timeSetting := func(key string, val *time.Duration) error {
161+
if value := o[key]; value != "" {
162+
timeout, err := strconv.Atoi(value)
163+
if err != nil {
164+
return err
165+
}
166+
// timeout is specified in milliseconds.
167+
*val = time.Duration(timeout) * time.Millisecond
168+
} else {
169+
*val = time.Duration(0) * time.Millisecond
170+
}
171+
return nil
172+
}
173+
174+
err = timeSetting("read_timeout", &cn.readTimeout)
175+
if err != nil {
176+
return err
177+
}
178+
err = timeSetting("write_timeout", &cn.writeTimeout)
179+
if err != nil {
180+
return err
181+
}
154182
err = boolSetting("disable_prepared_binary_result", &cn.disablePreparedBinaryResult)
155183
if err != nil {
156184
return err
@@ -911,23 +939,57 @@ func (cn *conn) Exec(query string, args []driver.Value) (res driver.Result, err
911939
return r, err
912940
}
913941

942+
func (cn *conn) setWriteTimeout() {
943+
// Set the write deadline if we have a write timeout set.
944+
if cn.writeTimeout != 0 {
945+
cn.c.SetWriteDeadline(time.Now().Add(cn.writeTimeout))
946+
}
947+
}
948+
949+
func (cn *conn) cleanWriteTimeout() {
950+
if cn.writeTimeout != 0 {
951+
// Clear the write deadline if we set one.
952+
cn.c.SetWriteDeadline(time.Time{})
953+
}
954+
}
955+
956+
func (cn *conn) setReadTimeout() {
957+
// Set the read deadline if we have a read timeout set.
958+
if cn.readTimeout != 0 {
959+
cn.c.SetReadDeadline(time.Now().Add(cn.readTimeout))
960+
}
961+
}
962+
963+
func (cn *conn) cleanReadTimeout() {
964+
if cn.readTimeout != 0 {
965+
// Clear the read deadline if we set one.
966+
cn.c.SetReadDeadline(time.Time{})
967+
}
968+
}
969+
914970
func (cn *conn) send(m *writeBuf) {
971+
cn.setWriteTimeout()
915972
_, err := cn.c.Write(m.wrap())
916973
if err != nil {
917974
panic(err)
918975
}
976+
cn.cleanWriteTimeout()
919977
}
920978

921979
func (cn *conn) sendStartupPacket(m *writeBuf) error {
980+
cn.setWriteTimeout()
922981
_, err := cn.c.Write((m.wrap())[1:])
982+
cn.cleanWriteTimeout()
923983
return err
924984
}
925985

926986
// Send a message of type typ to the server on the other end of cn. The
927987
// message should have no payload. This method does not use the scratch
928988
// buffer.
929989
func (cn *conn) sendSimpleMessage(typ byte) (err error) {
990+
cn.setWriteTimeout()
930991
_, err = cn.c.Write([]byte{typ, '\x00', '\x00', '\x00', '\x04'})
992+
cn.cleanWriteTimeout()
931993
return err
932994
}
933995

@@ -957,9 +1019,11 @@ func (cn *conn) recvMessage(r *readBuf) (byte, error) {
9571019
return t, nil
9581020
}
9591021

1022+
cn.setReadTimeout()
9601023
x := cn.scratch[:5]
9611024
_, err := io.ReadFull(cn.buf, x)
9621025
if err != nil {
1026+
cn.cleanReadTimeout()
9631027
return 0, err
9641028
}
9651029

@@ -972,11 +1036,14 @@ func (cn *conn) recvMessage(r *readBuf) (byte, error) {
9721036
} else {
9731037
y = make([]byte, n)
9741038
}
1039+
cn.setReadTimeout()
9751040
_, err = io.ReadFull(cn.buf, y)
9761041
if err != nil {
1042+
cn.cleanReadTimeout()
9771043
return 0, err
9781044
}
9791045
*r = y
1046+
cn.cleanReadTimeout()
9801047
return t, nil
9811048
}
9821049

@@ -1083,6 +1150,10 @@ func isDriverSetting(key string) bool {
10831150
return true
10841151
case "binary_parameters":
10851152
return true
1153+
case "read_timeout":
1154+
return true
1155+
case "write_timeout":
1156+
return true
10861157

10871158
default:
10881159
return false

0 commit comments

Comments
 (0)