feat: support database connectors and HTTP server configuration
This commit is contained in:
82
database/connector.go
Normal file
82
database/connector.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"database/sql/driver"
|
||||
"errors"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
// PoolConfig contains only driver-independent settings. Connection credentials,
|
||||
// TLS, logging and dial behavior belong to the application's Connector.
|
||||
// Start from DefaultPoolConfig; zero PingTimeout is invalid.
|
||||
type PoolConfig struct {
|
||||
MaxOpenConns int `json:"maxOpenConns"`
|
||||
MaxIdleConns int `json:"maxIdleConns"`
|
||||
ConnMaxLifetime time.Duration `json:"connMaxLifetime"`
|
||||
ConnMaxIdleTime time.Duration `json:"connMaxIdleTime"`
|
||||
PingTimeout time.Duration `json:"pingTimeout"`
|
||||
}
|
||||
|
||||
func DefaultPoolConfig() PoolConfig {
|
||||
return PoolConfig{MaxOpenConns: 10, MaxIdleConns: 5, ConnMaxLifetime: 30 * time.Minute, ConnMaxIdleTime: 5 * time.Minute, PingTimeout: 5 * time.Second}
|
||||
}
|
||||
|
||||
func (c PoolConfig) Validate() error {
|
||||
if c.MaxOpenConns < 0 || c.MaxIdleConns < 0 {
|
||||
return errors.New("database pool limits cannot be negative")
|
||||
}
|
||||
if c.MaxOpenConns > 0 && c.MaxIdleConns > c.MaxOpenConns {
|
||||
return errors.New("max idle connections cannot exceed max open connections")
|
||||
}
|
||||
if c.ConnMaxLifetime < 0 || c.ConnMaxIdleTime < 0 || c.PingTimeout <= 0 {
|
||||
return errors.New("database timeouts are invalid")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c PoolConfig) config() Config {
|
||||
return Config{MaxOpenConns: c.MaxOpenConns, MaxIdleConns: c.MaxIdleConns, ConnMaxLifetime: c.ConnMaxLifetime, ConnMaxIdleTime: c.ConnMaxIdleTime, PingTimeout: c.PingTimeout}
|
||||
}
|
||||
|
||||
// OpenConnector opens an independent pool using the supplied standard Connector.
|
||||
// No registered driver name or DSN is required. It applies cfg and completes a
|
||||
// startup Ping bounded by ctx and PingTimeout before returning.
|
||||
//
|
||||
// Validation failures and an already-canceled ctx leave the Connector untouched.
|
||||
// Once sql.OpenDB is called, the pool owns its lifecycle: a failed startup closes
|
||||
// the pool; on success the caller must Close the returned DB. As in database/sql,
|
||||
// this also closes a Connector that implements io.Closer. Use a separate Connector
|
||||
// for each pool if it owns resources. Nil ctx means context.Background.
|
||||
func OpenConnector(ctx context.Context, connector driver.Connector, cfg PoolConfig) (*DB, error) {
|
||||
if nilConnector(connector) {
|
||||
return nil, errors.New("database connector is required")
|
||||
}
|
||||
if err := cfg.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
if err := ctx.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return initializePool(ctx, sql.OpenDB(connector), cfg.config())
|
||||
}
|
||||
|
||||
func nilConnector(connector driver.Connector) bool {
|
||||
if connector == nil {
|
||||
return true
|
||||
}
|
||||
v := reflect.ValueOf(connector)
|
||||
switch v.Kind() {
|
||||
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Pointer, reflect.Slice:
|
||||
return v.IsNil()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// PoolConfig returns a copy of the settings used to create this pool.
|
||||
func (db *DB) PoolConfig() PoolConfig { return db.config.PoolConfig() }
|
||||
Reference in New Issue
Block a user