diff --git a/lib/caconfig.go b/lib/caconfig.go index 4e3836df7..9dc436d5b 100644 --- a/lib/caconfig.go +++ b/lib/caconfig.go @@ -125,9 +125,13 @@ type CAInfo struct { // CAConfigDB is the database part of the server's config type CAConfigDB struct { - Type string `def:"sqlite3" help:"Type of database; one of: sqlite3, postgres, mysql"` - Datasource string `def:"fabric-ca-server.db" help:"Data source which is database specific"` - TLS tls.ClientTLSConfig + Type string `def:"sqlite3" help:"Type of database; one of: sqlite3, postgres, mysql"` + Datasource string `def:"fabric-ca-server.db" help:"Data source which is database specific"` + TLS tls.ClientTLSConfig + MaxIdleConns int `def:"2" help:"Maximum number of connections in the idle pool; default is 2"` + MaxOpenConns int `def:"0" help:"Maximum number of open database connections; default is infinite or zero"` + ConnMaxIdleTime time.Duration `def:"15m" help:"Maximum amount of time a connection may be idle; default is infinite or zero"` + ConnMaxLifetime time.Duration `def:"30m" help:"Maximum amount of time a connection may be reused; default is infinite or zero"` } // Implements Stringer interface for CAConfigDB diff --git a/lib/server/db/db.go b/lib/server/db/db.go index 1ec7b7a15..7808c73a1 100644 --- a/lib/server/db/db.go +++ b/lib/server/db/db.go @@ -36,7 +36,10 @@ type FabricCADB interface { Rebind(query string) string MustBegin() *sqlx.Tx Close() error + SetMaxIdleConns(n int) SetMaxOpenConns(n int) + SetConnMaxLifetime(d time.Duration) + SetConnMaxIdleTime(d time.Duration) PingContext(ctx context.Context) error } @@ -54,7 +57,10 @@ type SqlxDB interface { Rebind(query string) string MustBegin() *sqlx.Tx Close() error + SetMaxIdleConns(n int) SetMaxOpenConns(n int) + SetConnMaxIdleTime(d time.Duration) + SetConnMaxLifetime(d time.Duration) PingContext(ctx context.Context) error } @@ -169,11 +175,34 @@ func (db *DB) Close() error { return db.DB.Close() } +// SetMaxIdleConns sets the maximum number of connections in the idle connection pool. +// The default is 2 +// See database/sql/sql.go:SetMaxIdleConns for further information +func (db *DB) SetMaxIdleConns(n int) { + db.DB.SetMaxIdleConns(n) +} + // SetMaxOpenConns sets number of max open connections func (db *DB) SetMaxOpenConns(n int) { db.DB.SetMaxOpenConns(n) } +// SetConnMaxIdleTime defines the maximum length of time a connection can be idle for before being +// optionally closed lazily before reuse. +func (db *DB) SetConnMaxIdleTime(d time.Duration) { + db.DB.SetConnMaxIdleTime(d) +} + +// SetConnMaxLifetime sets the lifetime of the open connections. +// 0 is the default duration set in the underlying database/sql library meaning +// connections have an infinite life and are not closed based on a connection's age. +// Setting this to a non-zero value is useful for recycling connections +// +// Works for each Postgres, MySQL, and SQLite since they all use sqlx and database/sql +func (db *DB) SetConnMaxLifetime(d time.Duration) { + db.DB.SetConnMaxLifetime(d) +} + // PingContext pings the database func (db *DB) PingContext(ctx context.Context) error { return db.DB.PingContext(ctx) diff --git a/lib/server/db/mocks/SqlxDB.go b/lib/server/db/mocks/SqlxDB.go index c84a30219..7d02cefb5 100644 --- a/lib/server/db/mocks/SqlxDB.go +++ b/lib/server/db/mocks/SqlxDB.go @@ -5,6 +5,7 @@ import ( context "context" sql "database/sql" sync "sync" + "time" db "github.com/hyperledger/fabric-ca/lib/server/db" sqlx "github.com/jmoiron/sqlx" @@ -131,11 +132,26 @@ type SqlxDB struct { selectReturnsOnCall map[int]struct { result1 error } + SetMaxIdleConnsStub func(int) + setMaxIdleConnsMutex sync.RWMutex + setMaxIdleConnsArgsForCall []struct { + arg1 int + } SetMaxOpenConnsStub func(int) setMaxOpenConnsMutex sync.RWMutex setMaxOpenConnsArgsForCall []struct { arg1 int } + SetConnMaxIdleTimeStub func(time.Duration) + setConnMaxIdleTimeMutex sync.RWMutex + setConnMaxIdleTimeArgsForCall []struct { + arg1 time.Duration + } + SetConnMaxLifetimeStub func(time.Duration) + setConnMaxLifetimeMutex sync.RWMutex + setConnMaxLifetimeArgsForCall []struct { + arg1 time.Duration + } invocations map[string][][]interface{} invocationsMutex sync.RWMutex } @@ -732,6 +748,37 @@ func (fake *SqlxDB) SelectReturnsOnCall(i int, result1 error) { }{result1} } +func (fake *SqlxDB) SetMaxIdleConns(arg1 int) { + fake.setMaxIdleConnsMutex.Lock() + fake.setMaxIdleConnsArgsForCall = append(fake.setMaxIdleConnsArgsForCall, struct { + arg1 int + }{arg1}) + fake.recordInvocation("SetMaxIdleConns", []interface{}{arg1}) + fake.setMaxIdleConnsMutex.Unlock() + if fake.SetMaxIdleConnsStub != nil { + fake.SetMaxIdleConnsStub(arg1) + } +} + +func (fake *SqlxDB) SetMaxIdleConnsCallCount() int { + fake.setMaxIdleConnsMutex.RLock() + defer fake.setMaxIdleConnsMutex.RUnlock() + return len(fake.setMaxIdleConnsArgsForCall) +} + +func (fake *SqlxDB) SetMaxIdleConnsCalls(stub func(int)) { + fake.setMaxIdleConnsMutex.Lock() + defer fake.setMaxIdleConnsMutex.Unlock() + fake.SetMaxIdleConnsStub = stub +} + +func (fake *SqlxDB) SetMaxIdleConnsArgsForCall(i int) int { + fake.setMaxIdleConnsMutex.RLock() + defer fake.setMaxIdleConnsMutex.RUnlock() + argsForCall := fake.setMaxIdleConnsArgsForCall[i] + return argsForCall.arg1 +} + func (fake *SqlxDB) SetMaxOpenConns(arg1 int) { fake.setMaxOpenConnsMutex.Lock() fake.setMaxOpenConnsArgsForCall = append(fake.setMaxOpenConnsArgsForCall, struct { @@ -763,6 +810,68 @@ func (fake *SqlxDB) SetMaxOpenConnsArgsForCall(i int) int { return argsForCall.arg1 } +func (fake *SqlxDB) SetConnMaxIdleTime(arg1 time.Duration) { + fake.setConnMaxIdleTimeMutex.Lock() + fake.setConnMaxIdleTimeArgsForCall = append(fake.setConnMaxIdleTimeArgsForCall, struct { + arg1 time.Duration + }{arg1}) + fake.recordInvocation("SetConnMaxIdleTime", []interface{}{arg1}) + fake.setConnMaxIdleTimeMutex.Unlock() + if fake.SetConnMaxIdleTimeStub != nil { + fake.SetConnMaxIdleTimeStub(arg1) + } +} + +func (fake *SqlxDB) SetConnMaxIdleTimeCallCount() int { + fake.setConnMaxIdleTimeMutex.RLock() + defer fake.setConnMaxIdleTimeMutex.RUnlock() + return len(fake.setConnMaxIdleTimeArgsForCall) +} + +func (fake *SqlxDB) SetConnMaxIdleTimeCalls(stub func(time.Duration)) { + fake.setConnMaxIdleTimeMutex.Lock() + defer fake.setConnMaxIdleTimeMutex.Unlock() + fake.SetConnMaxIdleTimeStub = stub +} + +func (fake *SqlxDB) SetConnMaxIdleTimeArgsForCall(i int) time.Duration { + fake.setConnMaxIdleTimeMutex.RLock() + defer fake.setConnMaxIdleTimeMutex.RUnlock() + argsForCall := fake.setConnMaxIdleTimeArgsForCall[i] + return argsForCall.arg1 +} + +func (fake *SqlxDB) SetConnMaxLifetime(arg1 time.Duration) { + fake.setConnMaxLifetimeMutex.Lock() + fake.setConnMaxLifetimeArgsForCall = append(fake.setConnMaxLifetimeArgsForCall, struct { + arg1 time.Duration + }{arg1}) + fake.recordInvocation("SetConnMaxLifetime", []interface{}{arg1}) + fake.setConnMaxLifetimeMutex.Unlock() + if fake.SetConnMaxLifetimeStub != nil { + fake.SetConnMaxLifetimeStub(arg1) + } +} + +func (fake *SqlxDB) SetConnMaxLifetimeCallCount() int { + fake.setConnMaxLifetimeMutex.RLock() + defer fake.setConnMaxLifetimeMutex.RUnlock() + return len(fake.setConnMaxLifetimeArgsForCall) +} + +func (fake *SqlxDB) SetConnMaxLifetimeCalls(stub func(time.Duration)) { + fake.setConnMaxLifetimeMutex.Lock() + defer fake.setConnMaxLifetimeMutex.Unlock() + fake.SetConnMaxLifetimeStub = stub +} + +func (fake *SqlxDB) SetConnMaxLifetimeArgsForCall(i int) time.Duration { + fake.setConnMaxLifetimeMutex.RLock() + defer fake.setConnMaxLifetimeMutex.RUnlock() + argsForCall := fake.setConnMaxLifetimeArgsForCall[i] + return argsForCall.arg1 +} + func (fake *SqlxDB) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock()