Implements MinConns, the minimum size of the connection pool.
The health check will increase the number of connections to this amount if it had dropped below.
This commit is contained in:
@@ -9,7 +9,7 @@ require (
|
|||||||
github.com/jackc/pgio v1.0.0
|
github.com/jackc/pgio v1.0.0
|
||||||
github.com/jackc/pgproto3/v2 v2.0.1
|
github.com/jackc/pgproto3/v2 v2.0.1
|
||||||
github.com/jackc/pgtype v1.1.0
|
github.com/jackc/pgtype v1.1.0
|
||||||
github.com/jackc/puddle v1.0.1-0.20200126004755-807afe48a83d
|
github.com/jackc/puddle v1.0.1-0.20200203142542-cde4bcb7af80
|
||||||
github.com/mattn/go-colorable v0.1.2 // indirect
|
github.com/mattn/go-colorable v0.1.2 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.9 // indirect
|
github.com/mattn/go-isatty v0.0.9 // indirect
|
||||||
github.com/rs/zerolog v1.15.0
|
github.com/rs/zerolog v1.15.0
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ github.com/jackc/puddle v1.0.0 h1:rbjAshlgKscNa7j0jAM0uNQflis5o2XUogPMVAwtcsM=
|
|||||||
github.com/jackc/puddle v1.0.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
github.com/jackc/puddle v1.0.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||||
github.com/jackc/puddle v1.0.1-0.20200126004755-807afe48a83d h1:lYLhmugF2D1ysJgU4pyW/GcdH+X4O3T96duzNdxcHqY=
|
github.com/jackc/puddle v1.0.1-0.20200126004755-807afe48a83d h1:lYLhmugF2D1ysJgU4pyW/GcdH+X4O3T96duzNdxcHqY=
|
||||||
github.com/jackc/puddle v1.0.1-0.20200126004755-807afe48a83d/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
github.com/jackc/puddle v1.0.1-0.20200126004755-807afe48a83d/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||||
|
github.com/jackc/puddle v1.0.1-0.20200203142542-cde4bcb7af80 h1:69wtn0QFLOhbxAnvoPYtkMcMTsa6lBF/Wp9341J5Yqo=
|
||||||
|
github.com/jackc/puddle v1.0.1-0.20200203142542-cde4bcb7af80/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var defaultMaxConns = int32(4)
|
var defaultMaxConns = int32(4)
|
||||||
|
var defaultMinConns = int32(0)
|
||||||
var defaultMaxConnLifetime = time.Hour
|
var defaultMaxConnLifetime = time.Hour
|
||||||
var defaultMaxConnIdleTime = time.Minute * 30
|
var defaultMaxConnIdleTime = time.Minute * 30
|
||||||
var defaultHealthCheckPeriod = time.Minute
|
var defaultHealthCheckPeriod = time.Minute
|
||||||
@@ -71,6 +72,7 @@ type Pool struct {
|
|||||||
afterConnect func(context.Context, *pgx.Conn) error
|
afterConnect func(context.Context, *pgx.Conn) error
|
||||||
beforeAcquire func(context.Context, *pgx.Conn) bool
|
beforeAcquire func(context.Context, *pgx.Conn) bool
|
||||||
afterRelease func(*pgx.Conn) bool
|
afterRelease func(*pgx.Conn) bool
|
||||||
|
minConns int32
|
||||||
maxConnLifetime time.Duration
|
maxConnLifetime time.Duration
|
||||||
maxConnIdleTime time.Duration
|
maxConnIdleTime time.Duration
|
||||||
healthCheckPeriod time.Duration
|
healthCheckPeriod time.Duration
|
||||||
@@ -103,6 +105,10 @@ type Config struct {
|
|||||||
// MaxConns is the maximum size of the pool.
|
// MaxConns is the maximum size of the pool.
|
||||||
MaxConns int32
|
MaxConns int32
|
||||||
|
|
||||||
|
// MinConns is the minimum size of the pool. The health check will increase the number of connections to this
|
||||||
|
// amount if it had dropped below.
|
||||||
|
MinConns int32
|
||||||
|
|
||||||
// HealthCheckPeriod is the duration between checks of the health of idle connections.
|
// HealthCheckPeriod is the duration between checks of the health of idle connections.
|
||||||
HealthCheckPeriod time.Duration
|
HealthCheckPeriod time.Duration
|
||||||
|
|
||||||
@@ -133,6 +139,7 @@ func ConnectConfig(ctx context.Context, config *Config) (*Pool, error) {
|
|||||||
afterConnect: config.AfterConnect,
|
afterConnect: config.AfterConnect,
|
||||||
beforeAcquire: config.BeforeAcquire,
|
beforeAcquire: config.BeforeAcquire,
|
||||||
afterRelease: config.AfterRelease,
|
afterRelease: config.AfterRelease,
|
||||||
|
minConns: config.MinConns,
|
||||||
maxConnLifetime: config.MaxConnLifetime,
|
maxConnLifetime: config.MaxConnLifetime,
|
||||||
maxConnIdleTime: config.MaxConnIdleTime,
|
maxConnIdleTime: config.MaxConnIdleTime,
|
||||||
healthCheckPeriod: config.HealthCheckPeriod,
|
healthCheckPeriod: config.HealthCheckPeriod,
|
||||||
@@ -190,6 +197,7 @@ func ConnectConfig(ctx context.Context, config *Config) (*Pool, error) {
|
|||||||
// addition of the following variables:
|
// addition of the following variables:
|
||||||
//
|
//
|
||||||
// pool_max_conns: integer greater than 0
|
// pool_max_conns: integer greater than 0
|
||||||
|
// pool_min_conns: integer 0 or greater
|
||||||
// pool_max_conn_lifetime: duration string
|
// pool_max_conn_lifetime: duration string
|
||||||
// pool_max_conn_idle_time: duration string
|
// pool_max_conn_idle_time: duration string
|
||||||
// pool_health_check_period: duration string
|
// pool_health_check_period: duration string
|
||||||
@@ -229,6 +237,17 @@ func ParseConfig(connString string) (*Config, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s, ok := config.ConnConfig.Config.RuntimeParams["pool_min_conns"]; ok {
|
||||||
|
delete(connConfig.Config.RuntimeParams, "pool_min_conns")
|
||||||
|
n, err := strconv.ParseInt(s, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Errorf("cannot parse pool_min_conns: %w", err)
|
||||||
|
}
|
||||||
|
config.MinConns = int32(n)
|
||||||
|
} else {
|
||||||
|
config.MinConns = defaultMinConns
|
||||||
|
}
|
||||||
|
|
||||||
if s, ok := config.ConnConfig.Config.RuntimeParams["pool_max_conn_lifetime"]; ok {
|
if s, ok := config.ConnConfig.Config.RuntimeParams["pool_max_conn_lifetime"]; ok {
|
||||||
delete(connConfig.Config.RuntimeParams, "pool_max_conn_lifetime")
|
delete(connConfig.Config.RuntimeParams, "pool_max_conn_lifetime")
|
||||||
d, err := time.ParseDuration(s)
|
d, err := time.ParseDuration(s)
|
||||||
@@ -282,6 +301,7 @@ func (p *Pool) backgroundHealthCheck() {
|
|||||||
return
|
return
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
p.checkIdleConnsHealth()
|
p.checkIdleConnsHealth()
|
||||||
|
p.checkMinConns()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -301,6 +321,12 @@ func (p *Pool) checkIdleConnsHealth() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Pool) checkMinConns() {
|
||||||
|
for i := p.minConns - p.Stat().TotalConns(); i > 0; i-- {
|
||||||
|
go p.p.CreateResource(context.Background())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Pool) Acquire(ctx context.Context) (*Conn, error) {
|
func (p *Pool) Acquire(ctx context.Context) (*Conn, error) {
|
||||||
for {
|
for {
|
||||||
res, err := p.p.Acquire(ctx)
|
res, err := p.p.Acquire(ctx)
|
||||||
|
|||||||
+22
-1
@@ -23,10 +23,12 @@ func TestConnect(t *testing.T) {
|
|||||||
func TestParseConfigExtractsPoolArguments(t *testing.T) {
|
func TestParseConfigExtractsPoolArguments(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
config, err := pgxpool.ParseConfig("pool_max_conns=42")
|
config, err := pgxpool.ParseConfig("pool_max_conns=42 pool_min_conns=1")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, 42, config.MaxConns)
|
assert.EqualValues(t, 42, config.MaxConns)
|
||||||
|
assert.EqualValues(t, 1, config.MinConns)
|
||||||
assert.NotContains(t, config.ConnConfig.Config.RuntimeParams, "pool_max_conns")
|
assert.NotContains(t, config.ConnConfig.Config.RuntimeParams, "pool_max_conns")
|
||||||
|
assert.NotContains(t, config.ConnConfig.Config.RuntimeParams, "pool_min_conns")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConnectCancel(t *testing.T) {
|
func TestConnectCancel(t *testing.T) {
|
||||||
@@ -276,6 +278,25 @@ func TestPoolBackgroundChecksMaxConnIdleTime(t *testing.T) {
|
|||||||
assert.EqualValues(t, 0, stats.TotalConns())
|
assert.EqualValues(t, 0, stats.TotalConns())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPoolBackgroundChecksMinConns(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
config, err := pgxpool.ParseConfig(os.Getenv("PGX_TEST_DATABASE"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
config.HealthCheckPeriod = 100 * time.Millisecond
|
||||||
|
config.MinConns = 2
|
||||||
|
|
||||||
|
db, err := pgxpool.ConnectConfig(context.Background(), config)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
time.Sleep(config.HealthCheckPeriod + 100*time.Millisecond)
|
||||||
|
|
||||||
|
stats := db.Stat()
|
||||||
|
assert.EqualValues(t, 2, stats.TotalConns())
|
||||||
|
}
|
||||||
|
|
||||||
func TestPoolExec(t *testing.T) {
|
func TestPoolExec(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user