fix: cap mysql connection pool
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
{
|
{
|
||||||
"listen": ":6061",
|
"listen": ":6061",
|
||||||
"mysql": {
|
"mysql": {
|
||||||
"dsn": "root:root@tcp(127.0.0.1:3306)/meeting_im?parseTime=true&charset=utf8mb4,utf8&loc=Local"
|
"dsn": "root:root@tcp(127.0.0.1:3306)/meeting_im?parseTime=true&charset=utf8mb4,utf8&loc=Local",
|
||||||
|
"max_open_conns": 15,
|
||||||
|
"max_idle_conns": 5
|
||||||
},
|
},
|
||||||
"redis": {
|
"redis": {
|
||||||
"addr": "127.0.0.1:6379",
|
"addr": "127.0.0.1:6379",
|
||||||
|
|||||||
@@ -24,7 +24,9 @@ type Config struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MySQLConfig struct {
|
type MySQLConfig struct {
|
||||||
DSN string `json:"dsn"`
|
DSN string `json:"dsn"`
|
||||||
|
MaxOpenConns int `json:"max_open_conns"`
|
||||||
|
MaxIdleConns int `json:"max_idle_conns"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RedisConfig struct {
|
type RedisConfig struct {
|
||||||
@@ -90,7 +92,9 @@ func defaultConfig() *Config {
|
|||||||
return &Config{
|
return &Config{
|
||||||
Listen: ":6061",
|
Listen: ":6061",
|
||||||
MySQL: MySQLConfig{
|
MySQL: MySQLConfig{
|
||||||
DSN: "root:root@tcp(127.0.0.1:3306)/meeting_im?parseTime=true&charset=utf8mb4,utf8&loc=Local",
|
DSN: "root:root@tcp(127.0.0.1:3306)/meeting_im?parseTime=true&charset=utf8mb4,utf8&loc=Local",
|
||||||
|
MaxOpenConns: 15,
|
||||||
|
MaxIdleConns: 5,
|
||||||
},
|
},
|
||||||
Redis: RedisConfig{
|
Redis: RedisConfig{
|
||||||
Addr: "127.0.0.1:6379",
|
Addr: "127.0.0.1:6379",
|
||||||
@@ -120,6 +124,8 @@ func defaultConfig() *Config {
|
|||||||
func applyEnv(cfg *Config) {
|
func applyEnv(cfg *Config) {
|
||||||
setString(&cfg.Listen, "IM_WORKBENCH_LISTEN")
|
setString(&cfg.Listen, "IM_WORKBENCH_LISTEN")
|
||||||
setString(&cfg.MySQL.DSN, "IM_WORKBENCH_MYSQL_DSN")
|
setString(&cfg.MySQL.DSN, "IM_WORKBENCH_MYSQL_DSN")
|
||||||
|
setInt(&cfg.MySQL.MaxOpenConns, "IM_WORKBENCH_MYSQL_MAX_OPEN_CONNS")
|
||||||
|
setInt(&cfg.MySQL.MaxIdleConns, "IM_WORKBENCH_MYSQL_MAX_IDLE_CONNS")
|
||||||
setString(&cfg.Redis.Addr, "IM_WORKBENCH_REDIS_ADDR")
|
setString(&cfg.Redis.Addr, "IM_WORKBENCH_REDIS_ADDR")
|
||||||
setString(&cfg.Redis.Username, "IM_WORKBENCH_REDIS_USERNAME")
|
setString(&cfg.Redis.Username, "IM_WORKBENCH_REDIS_USERNAME")
|
||||||
setString(&cfg.Redis.Password, "IM_WORKBENCH_REDIS_PASSWORD")
|
setString(&cfg.Redis.Password, "IM_WORKBENCH_REDIS_PASSWORD")
|
||||||
@@ -214,6 +220,14 @@ func setString(target *string, key string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setInt(target *int, key string) {
|
||||||
|
if value := strings.TrimSpace(os.Getenv(key)); value != "" {
|
||||||
|
if parsed, err := strconv.Atoi(value); err == nil {
|
||||||
|
*target = parsed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func setBool(target *bool, key string) {
|
func setBool(target *bool, key string) {
|
||||||
switch strings.ToLower(strings.TrimSpace(os.Getenv(key))) {
|
switch strings.ToLower(strings.TrimSpace(os.Getenv(key))) {
|
||||||
case "1", "true", "yes", "on":
|
case "1", "true", "yes", "on":
|
||||||
|
|||||||
@@ -23,4 +23,19 @@ func TestDefaultConfigUsesMeetingIMDatabase(t *testing.T) {
|
|||||||
if !strings.Contains(cfg.MySQL.DSN, "/meeting_im?") {
|
if !strings.Contains(cfg.MySQL.DSN, "/meeting_im?") {
|
||||||
t.Fatalf("default mysql dsn = %q, want meeting_im database", cfg.MySQL.DSN)
|
t.Fatalf("default mysql dsn = %q, want meeting_im database", cfg.MySQL.DSN)
|
||||||
}
|
}
|
||||||
|
if cfg.MySQL.MaxOpenConns != 15 || cfg.MySQL.MaxIdleConns != 5 {
|
||||||
|
t.Fatalf("default mysql pool = %d/%d, want 15/5", cfg.MySQL.MaxOpenConns, cfg.MySQL.MaxIdleConns)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApplyEnvOverridesMySQLPool(t *testing.T) {
|
||||||
|
t.Setenv("IM_WORKBENCH_MYSQL_MAX_OPEN_CONNS", "12")
|
||||||
|
t.Setenv("IM_WORKBENCH_MYSQL_MAX_IDLE_CONNS", "4")
|
||||||
|
cfg := defaultConfig()
|
||||||
|
|
||||||
|
applyEnv(cfg)
|
||||||
|
|
||||||
|
if cfg.MySQL.MaxOpenConns != 12 || cfg.MySQL.MaxIdleConns != 4 {
|
||||||
|
t.Fatalf("mysql pool = %d/%d, want 12/4", cfg.MySQL.MaxOpenConns, cfg.MySQL.MaxIdleConns)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ func SetUIDKey(encoded string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Open(cfg config.MySQLConfig) (*Store, error) {
|
func Open(cfg config.MySQLConfig) (*Store, error) {
|
||||||
st, err := openDSN(cfg.DSN)
|
st, err := openDSN(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -66,13 +66,13 @@ func Open(cfg config.MySQLConfig) (*Store, error) {
|
|||||||
return st, nil
|
return st, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func openDSN(dsn string) (*Store, error) {
|
func openDSN(cfg config.MySQLConfig) (*Store, error) {
|
||||||
db, err := sqlx.Open("mysql", dsn)
|
db, err := sqlx.Open("mysql", cfg.DSN)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
db.SetMaxOpenConns(30)
|
db.SetMaxOpenConns(cfg.MaxOpenConns)
|
||||||
db.SetMaxIdleConns(10)
|
db.SetMaxIdleConns(cfg.MaxIdleConns)
|
||||||
db.SetConnMaxLifetime(30 * time.Minute)
|
db.SetConnMaxLifetime(30 * time.Minute)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -80,7 +80,7 @@ func openDSN(dsn string) (*Store, error) {
|
|||||||
_ = db.Close()
|
_ = db.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &Store{db: db, dsn: dsn}, nil
|
return &Store{db: db, dsn: cfg.DSN}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) tenant() int64 {
|
func (s *Store) tenant() int64 {
|
||||||
|
|||||||
Reference in New Issue
Block a user