Skip to content

Commit

Permalink
resolve various race condition
Browse files Browse the repository at this point in the history
  • Loading branch information
andizzle committed Nov 8, 2017
1 parent d4f1550 commit 2e27d91
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 15 deletions.
5 changes: 1 addition & 4 deletions cpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ type CPool struct {
}

func (c *CPool) nextInPool() int {
c.lock.RLock()
defer c.lock.RUnlock()

if len(c.pool) == 0 {
if c.poolSize() == 0 {
return -1
}

Expand Down
24 changes: 13 additions & 11 deletions database.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,21 +184,23 @@ func (db *DB) PrepareContext(ctx context.Context, query string) (Stmt, error) {
return nil, err
}

stmt.stmts = append([]*sql.Stmt{write}, stmt.stmts...)
stmt.stmts = []*sql.Stmt{write}

if db.cpool.poolSize() > 1 {
go func() {
reader, err := db.cpool.Reader()
reader, err := db.cpool.Reader()
if err == nil {
// we have writer statement prepared
// this error can be ignored
go func(reader *sql.DB) {

if err != nil {
// we have writer statement prepared
// this error can be ignored
return
}
read, _ := reader.PrepareContext(ctx, query)

stmt.lock.Lock()
defer stmt.lock.Unlock()

read, _ := reader.PrepareContext(ctx, query)
stmt.stmts = append(stmt.stmts, read)
}()
stmt.stmts = append(stmt.stmts, read)
}(reader)
}
}

return stmt, nil
Expand Down
11 changes: 11 additions & 0 deletions stmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"database/sql"
"errors"
"sync"
)

// Stmt allows DB
Expand All @@ -20,6 +21,7 @@ type Stmt interface {
// stmt holds at most 2 sql.Stmt
type stmt struct {
stmts []*sql.Stmt
lock sync.RWMutex
}

// Close will close the statments connections
Expand All @@ -39,6 +41,9 @@ func (s *stmt) Exec(args ...interface{}) (sql.Result, error) {
// Exec execute statement with context
// The statement is executed on the writer database
func (s *stmt) ExecContext(ctx context.Context, args ...interface{}) (sql.Result, error) {
s.lock.RLock()
defer s.lock.RUnlock()

if len(s.stmts) == 0 {
return nil, errors.New("zero statement executable")
}
Expand All @@ -54,6 +59,9 @@ func (s *stmt) Query(args ...interface{}) (*sql.Rows, error) {
// Query execute statement with context
// The statement is executed on reader database
func (s *stmt) QueryContext(ctx context.Context, args ...interface{}) (*sql.Rows, error) {
s.lock.RLock()
defer s.lock.RUnlock()

if len(s.stmts) == 0 {
return nil, errors.New("zero statement executable")
}
Expand All @@ -74,6 +82,9 @@ func (s *stmt) QueryRow(args ...interface{}) Row {

// QueryRowContext is executed on reader database
func (s *stmt) QueryRowContext(ctx context.Context, args ...interface{}) Row {
s.lock.RLock()
defer s.lock.RUnlock()

if len(s.stmts) == 0 {
return &row{err: errors.New("zero statement executable")}
}
Expand Down

0 comments on commit 2e27d91

Please sign in to comment.