package component import ( "database/sql" "fmt" "gitea.party/public-messag-service/config" "github.com/urfave/cli/v2" "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/schema" "gorm.io/plugin/dbresolver" "strings" ) type MySQLClient struct { DB *gorm.DB Cfg config.EntityMysql ref *MySQL } func (c *MySQLClient) Ref() *MySQL { return c.ref } func (c *MySQLClient) CliFlags(name string) []cli.Flag { return []cli.Flag{ &cli.IntFlag{ Name: fmt.Sprintf("mysql-%s-open-limit", name), Usage: fmt.Sprintf("mysql(%s) max open limit", name), Action: func(_ *cli.Context, v int) error { c.Cfg.MaxOpen = v; return nil }, }, &cli.IntFlag{ Name: fmt.Sprintf("mysql-%s-idle-limit", name), Usage: fmt.Sprintf("mysql(%s) idle open limit", name), Action: func(_ *cli.Context, v int) error { c.Cfg.MaxIdle = v; return nil }, }, &cli.StringFlag{ Name: fmt.Sprintf("mysql-%s-dsn", name), Usage: fmt.Sprintf("mysql(%s) DSN (format: `{{user_name}}:{{password}}@tcp({{host}}:{{port}})/{{db_name}}?{{connect_options}}`)", name), Action: func(_ *cli.Context, val string) (err error) { dsn := strings.Split(val, ";") if err = c.Cfg.Master.ParserDSN(dsn[0]); err == nil { if len(dsn) > 1 { c.Cfg.Slave = make([]config.ConnectMysql, 0, len(dsn)-1) for i, l := 1, len(dsn); i < l; i++ { v := config.ConnectMysql{} if err = v.ParserDSN(dsn[i]); err != nil { break } c.Cfg.Slave = append(c.Cfg.Slave, v) } } } if err != nil { err = fmt.Errorf("Mysql DSN is invalid(%s)", err.Error()) } return err }, }, } } func (c *MySQLClient) Init(env int, cc *MySQL) { c.ref = cc } func (c *MySQLClient) Config() *config.EntityMysql { return &c.Cfg } func (c *MySQLClient) Load(name string) (err error) { mastDB := mysql.Open(c.Cfg.Master.GetConnectDSN()) gormDB, err := gorm.Open(mastDB, &gorm.Config{ SkipDefaultTransaction: true, Logger: &c.ref.Log, NamingStrategy: schema.NamingStrategy{ SingularTable: true, }, }) if err == nil { if len(c.Cfg.Slave) > 0 { slaveDBs := make([]gorm.Dialector, 0, len(c.Cfg.Slave)) for k := range c.Cfg.Slave { slaveDBs = append(slaveDBs, mysql.Open(c.Cfg.Slave[k].GetConnectDSN())) } readWritePlugin := dbresolver.Register(dbresolver.Config{ Sources: []gorm.Dialector{mastDB}, Replicas: slaveDBs, Policy: dbresolver.RandomPolicy{}, }) readWritePlugin.SetMaxOpenConns(c.Cfg.MaxOpen) readWritePlugin.SetMaxIdleConns(c.Cfg.MaxIdle) err = gormDB.Use(readWritePlugin) } else { var sqlDB *sql.DB if sqlDB, err = gormDB.DB(); err == nil { sqlDB.SetMaxOpenConns(c.Cfg.MaxOpen) sqlDB.SetMaxIdleConns(c.Cfg.MaxIdle) } } } if err != nil { gormDB, err = nil, fmt.Errorf("Load Mysql (%s) Failed (Error: %s) ", name, err.Error()) } c.DB = gormDB return err }