Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

db: reconnect on connection errors #286

Open
wants to merge 30 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
9012927
Add a recovering mechanism to reconnect and retry a query if the serv…
xiam Oct 4, 2016
cabedd7
Fix bug with ghost values in execer
xiam Oct 5, 2016
c93dbcf
Update retry mechanism.
xiam Oct 17, 2016
1de668f
Merge branch 'issue-226' of github.com:upper/db into issue-226
xiam Oct 17, 2016
6475aea
Make d.recoverFromErr only catch ErrBadConn.
xiam Oct 17, 2016
b3306f0
Merge pull request #282 from upper/issue-280
Oct 21, 2016
c267726
Merge pull request #281 from upper/issue-279
Oct 21, 2016
de7bff7
Manual merge
xiam Oct 24, 2016
7a86715
Add reconnect (WIP +debug messages)
xiam Oct 24, 2016
0f9bfe3
Better logic for handling connect/reconnect
xiam Oct 26, 2016
4af4871
Cleaning up remaining reconnection bits
xiam Oct 27, 2016
f08946e
Removing log messages and adding a test for bad connection.
xiam Nov 4, 2016
e523258
Update docstrings
xiam Nov 4, 2016
2a02240
Remove "could not read block" from db.ErrServerRefusedConnection
xiam Nov 4, 2016
cfb43e3
Ping within a transaction.
xiam Nov 4, 2016
3538ba3
Don't block Transaction() before connecting.
xiam Nov 4, 2016
13181c0
Merge pull request #269 from upper/issue-226
Nov 8, 2016
ec0678d
Use db.ErrTooManyReconnectionAttempts instead of db.ErrGivingUpTrying…
xiam Nov 8, 2016
6d206db
Merge branch 'master' into feature/err-too-many-reconnection-attempts
xiam Nov 8, 2016
53a97dd
Merge pull request #283 from upper/feature/err-too-many-reconnection-…
Nov 10, 2016
37e2780
Fixes after testing reconnect with a low number of available connecti…
xiam Nov 10, 2016
78d28bc
Make retry-on-error configurable and disable it by default.
xiam Nov 10, 2016
340d8eb
Add db.Conf.SetRetryQueryOnError to PostgreSQL test.
xiam Nov 10, 2016
118944d
Fix call to c.setBinaryOption
xiam Nov 10, 2016
7017914
Add missing db.Conf.RetryQueryOnError
xiam Nov 10, 2016
ed13348
Add d.recoverAttempts for counting recovery attempts up to discardCon…
xiam Nov 14, 2016
02b5a72
Use flushConnectionPoolAfterRecoverAttempts and remove ConnCheck.
xiam Nov 14, 2016
963d413
Merge branch 'master' into feature/test-reconnect-with-few-connections
xiam Nov 16, 2016
838332f
Removing flawed logic: don't close before having a valid new conn to …
xiam Nov 16, 2016
33b8d62
Mark prepared statements as ready to be closed after using them
xiam Nov 16, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 31 additions & 8 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ import (

// Settings defines methods to get or set configuration values.
type Settings interface {
// SetRetryQueryOnError enables or disable query retry-on-error features.
SetRetryQueryOnError(bool)
// Returns true if query retry is enabled.
RetryQueryOnError() bool

// SetLogging enables or disables logging.
SetLogging(bool)
// LoggingEnabled returns true if logging is enabled, false otherwise.
Expand All @@ -45,6 +50,8 @@ type conf struct {
queryLogger Logger
queryLoggerMu sync.RWMutex
defaultLogger defaultLogger

queryRetryOnError uint32
}

func (c *conf) Logger() Logger {
Expand All @@ -58,27 +65,43 @@ func (c *conf) Logger() Logger {
return c.queryLogger
}

func (c *conf) SetRetryQueryOnError(v bool) {
c.setBinaryOption(&c.queryRetryOnError, v)
}

func (c *conf) RetryQueryOnError() bool {
return c.binaryOption(&c.queryRetryOnError)
}

func (c *conf) SetLogger(lg Logger) {
c.queryLoggerMu.Lock()
defer c.queryLoggerMu.Unlock()

c.queryLogger = lg
}

func (c *conf) SetLogging(value bool) {
func (c *conf) binaryOption(dest *uint32) bool {
if v := atomic.LoadUint32(dest); v == 1 {
return true
}
return false
}

func (c *conf) setBinaryOption(dest *uint32, value bool) {
if value {
atomic.StoreUint32(&c.loggingEnabled, 1)
atomic.StoreUint32(dest, 1)
return
}
atomic.StoreUint32(&c.loggingEnabled, 0)
atomic.StoreUint32(dest, 0)
}

func (c *conf) SetLogging(value bool) {
c.setBinaryOption(&c.loggingEnabled, value)
}

func (c *conf) LoggingEnabled() bool {
if v := atomic.LoadUint32(&c.loggingEnabled); v == 1 {
return true
}
return false
return c.binaryOption(&c.loggingEnabled)
}

// Conf provides global configuration settings for upper-db.
// Conf provides default global configuration settings for upper-db.
var Conf Settings = &conf{}
13 changes: 11 additions & 2 deletions db.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,15 @@ func newCompound(c ...Compound) *compound {
return &compound{c}
}

func defaultJoin(in ...Compound) []Compound {
for i := range in {
if cond, ok := in[i].(Cond); ok && len(cond) > 1 {
in[i] = And(cond)
}
}
return in
}

func (c *compound) Sentences() []Compound {
return c.conds
}
Expand All @@ -292,7 +301,7 @@ type Union struct {

// Or adds more terms to the compound.
func (o *Union) Or(conds ...Compound) *Union {
o.compound.push(conds...)
o.compound.push(defaultJoin(conds...)...)
return o
}

Expand Down Expand Up @@ -420,7 +429,7 @@ func And(conds ...Compound) *Intersection {
// db.Cond{"year": 1987},
// )
func Or(conds ...Compound) *Union {
return &Union{compound: newCompound(conds...)}
return &Union{compound: newCompound(defaultJoin(conds...)...)}
}

// Raw marks chunks of data as protected, so they pass directly to the query
Expand Down
46 changes: 24 additions & 22 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,28 @@ import (

// Error messages.
var (
ErrNoMoreRows = errors.New(`upper: no more rows in this result set`)
ErrNotConnected = errors.New(`upper: you're currently not connected`)
ErrMissingDatabaseName = errors.New(`upper: missing database name`)
ErrMissingCollectionName = errors.New(`upper: missing collection name`)
ErrCollectionDoesNotExist = errors.New(`upper: collection does not exist`)
ErrSockerOrHost = errors.New(`upper: you may connect either to a unix socket or a tcp address, but not both`)
ErrQueryLimitParam = errors.New(`upper: a query can accept only one limit parameter`)
ErrQuerySortParam = errors.New(`upper: a query can accept only one order by parameter`)
ErrQueryOffsetParam = errors.New(`upper: a query can accept only one offset parameter`)
ErrMissingConditions = errors.New(`upper: missing selector conditions`)
ErrUnsupported = errors.New(`upper: this action is currently unsupported on this database`)
ErrUndefined = errors.New(`upper: this value is undefined`)
ErrQueryIsPending = errors.New(`upper: can't execute this instruction while the result set is still open`)
ErrUnsupportedDestination = errors.New(`upper: unsupported destination type`)
ErrUnsupportedType = errors.New(`upper: this type does not support marshaling`)
ErrUnsupportedValue = errors.New(`upper: this value does not support unmarshaling`)
ErrUnknownConditionType = errors.New(`upper: arguments of type %T can't be used as constraints`)
ErrTooManyClients = errors.New(`upper: can't connect to database server: too many clients`)
ErrGivingUpTryingToConnect = errors.New(`upper: giving up trying to connect: too many clients`)
ErrMissingConnURL = errors.New(`upper: missing DSN`)
ErrNotImplemented = errors.New(`upper: call not implemented`)
ErrAlreadyWithinTransaction = errors.New(`upper: already within a transaction`)
ErrNoMoreRows = errors.New(`upper: no more rows in this result set`)
ErrNotConnected = errors.New(`upper: you're currently not connected`)
ErrMissingDatabaseName = errors.New(`upper: missing database name`)
ErrMissingCollectionName = errors.New(`upper: missing collection name`)
ErrCollectionDoesNotExist = errors.New(`upper: collection does not exist`)
ErrSockerOrHost = errors.New(`upper: you may connect either to a unix socket or a tcp address, but not both`)
ErrQueryLimitParam = errors.New(`upper: a query can accept only one limit parameter`)
ErrQuerySortParam = errors.New(`upper: a query can accept only one order by parameter`)
ErrQueryOffsetParam = errors.New(`upper: a query can accept only one offset parameter`)
ErrMissingConditions = errors.New(`upper: missing selector conditions`)
ErrUnsupported = errors.New(`upper: this action is currently unsupported on this database`)
ErrUndefined = errors.New(`upper: this value is undefined`)
ErrQueryIsPending = errors.New(`upper: can't execute this instruction while the result set is still open`)
ErrUnsupportedDestination = errors.New(`upper: unsupported destination type`)
ErrUnsupportedType = errors.New(`upper: this type does not support marshaling`)
ErrUnsupportedValue = errors.New(`upper: this value does not support unmarshaling`)
ErrUnknownConditionType = errors.New(`upper: arguments of type %T can't be used as constraints`)
ErrTooManyClients = errors.New(`upper: can't connect to database server: too many clients`)
ErrGivingUpTryingToConnect = errors.New(`upper: giving up trying to connect: too many clients`)
ErrTooManyReconnectionAttempts = errors.New(`upper: too many reconnection attempts`)
ErrMissingConnURL = errors.New(`upper: missing DSN`)
ErrNotImplemented = errors.New(`upper: call not implemented`)
ErrAlreadyWithinTransaction = errors.New(`upper: already within a transaction`)
ErrServerRefusedConnection = errors.New(`upper: database server refused connection`)
)
Loading