Skip to content

Commit 8216b38

Browse files
authored
Merge pull request #39 from smartcontractkit/bugfix/error_on_rollback_keeps_bad_connection_in_pool
If Rollback fails, txdb keeps a bad connection in the pool
2 parents 921ebb0 + 3a5ba5d commit 8216b38

File tree

2 files changed

+55
-4
lines changed

2 files changed

+55
-4
lines changed

db.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,7 @@ func (c *conn) Close() (err error) {
181181
c.opened--
182182
if c.opened == 0 {
183183
if c.tx != nil {
184-
err = c.tx.Rollback()
185-
if err != nil {
186-
return
187-
}
184+
c.tx.Rollback()
188185
c.tx = nil
189186
}
190187
c.drv.deleteConn(c.dsn)

db_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ package txdb
22

33
import (
44
"database/sql"
5+
"errors"
56
"fmt"
67
"strings"
78
"sync"
89
"testing"
10+
"time"
911
)
1012

1113
func drivers() []string {
@@ -381,3 +383,55 @@ func TestShouldReopenAfterClose(t *testing.T) {
381383
}
382384
}
383385
}
386+
387+
type canceledContext struct{}
388+
389+
func (canceledContext) Deadline() (deadline time.Time, ok bool) { return time.Time{}, true }
390+
func (canceledContext) Done() <-chan struct{} {
391+
done := make(chan struct{}, 0)
392+
close(done)
393+
return done
394+
}
395+
func (canceledContext) Err() error { return errors.New("canceled") }
396+
func (canceledContext) Value(key interface{}) interface{} { return nil }
397+
398+
func TestShouldDiscardConnectionWhenClosedBecauseOfError(t *testing.T) {
399+
for _, driver := range drivers() {
400+
t.Run(fmt.Sprintf("using driver %s", driver), func(t *testing.T) {
401+
{
402+
db, err := sql.Open(driver, "first")
403+
if err != nil {
404+
t.Fatalf(driver+": failed to open a connection, have you run 'make test'? err: %s", err)
405+
}
406+
defer db.Close()
407+
408+
tx, err := db.Begin()
409+
defer tx.Rollback()
410+
if err != nil {
411+
t.Fatalf(driver+": failed to begin transaction err: %s", err)
412+
}
413+
414+
// TODO: we somehow need to poison the DB connection here so that Rollback fails
415+
416+
_, err = tx.PrepareContext(canceledContext{}, "SELECT * FROM users")
417+
if err == nil {
418+
t.Fatalf(driver + ": should have returned error for prepare")
419+
}
420+
}
421+
422+
fmt.Println("Opening db...")
423+
424+
{
425+
db, err := sql.Open(driver, "second")
426+
if err != nil {
427+
t.Fatalf(driver+": failed to open a connection, have you run 'make test'? err: %s", err)
428+
}
429+
defer db.Close()
430+
431+
if err := db.Ping(); err != nil {
432+
t.Fatalf(driver+": failed to ping, have you run 'make test'? err: %s", err)
433+
}
434+
}
435+
})
436+
}
437+
}

0 commit comments

Comments
 (0)