Skip to content

Commit

Permalink
Merge pull request #39 from smartcontractkit/bugfix/error_on_rollback…
Browse files Browse the repository at this point in the history
…_keeps_bad_connection_in_pool

If Rollback fails, txdb keeps a bad connection in the pool
  • Loading branch information
l3pp4rd committed Apr 2, 2021
2 parents 921ebb0 + 3a5ba5d commit 8216b38
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 4 deletions.
5 changes: 1 addition & 4 deletions db.go
Expand Up @@ -181,10 +181,7 @@ func (c *conn) Close() (err error) {
c.opened--
if c.opened == 0 {
if c.tx != nil {
err = c.tx.Rollback()
if err != nil {
return
}
c.tx.Rollback()
c.tx = nil
}
c.drv.deleteConn(c.dsn)
Expand Down
54 changes: 54 additions & 0 deletions db_test.go
Expand Up @@ -2,10 +2,12 @@ package txdb

import (
"database/sql"
"errors"
"fmt"
"strings"
"sync"
"testing"
"time"
)

func drivers() []string {
Expand Down Expand Up @@ -381,3 +383,55 @@ func TestShouldReopenAfterClose(t *testing.T) {
}
}
}

type canceledContext struct{}

func (canceledContext) Deadline() (deadline time.Time, ok bool) { return time.Time{}, true }
func (canceledContext) Done() <-chan struct{} {
done := make(chan struct{}, 0)
close(done)
return done
}
func (canceledContext) Err() error { return errors.New("canceled") }
func (canceledContext) Value(key interface{}) interface{} { return nil }

func TestShouldDiscardConnectionWhenClosedBecauseOfError(t *testing.T) {
for _, driver := range drivers() {
t.Run(fmt.Sprintf("using driver %s", driver), func(t *testing.T) {
{
db, err := sql.Open(driver, "first")
if err != nil {
t.Fatalf(driver+": failed to open a connection, have you run 'make test'? err: %s", err)
}
defer db.Close()

tx, err := db.Begin()
defer tx.Rollback()
if err != nil {
t.Fatalf(driver+": failed to begin transaction err: %s", err)
}

// TODO: we somehow need to poison the DB connection here so that Rollback fails

_, err = tx.PrepareContext(canceledContext{}, "SELECT * FROM users")
if err == nil {
t.Fatalf(driver + ": should have returned error for prepare")
}
}

fmt.Println("Opening db...")

{
db, err := sql.Open(driver, "second")
if err != nil {
t.Fatalf(driver+": failed to open a connection, have you run 'make test'? err: %s", err)
}
defer db.Close()

if err := db.Ping(); err != nil {
t.Fatalf(driver+": failed to ping, have you run 'make test'? err: %s", err)
}
}
})
}
}

0 comments on commit 8216b38

Please sign in to comment.