github.com/erda-project/erda-infra@v1.0.9/providers/mysql/v2/mysql.go (about) 1 // Copyright (c) 2021 Terminus, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package v2 16 17 import ( 18 "fmt" 19 "reflect" 20 "time" 21 22 "github.com/sirupsen/logrus" 23 "gorm.io/driver/mysql" // mysql client driver package 24 "gorm.io/gorm" 25 26 "github.com/erda-project/erda-infra/base/servicehub" 27 "github.com/erda-project/erda-infra/pkg/mysqldriver" 28 ) 29 30 var ( 31 interfaceType = reflect.TypeOf((*Interface)(nil)).Elem() 32 gormType = reflect.TypeOf((*gorm.DB)(nil)) 33 txType = reflect.TypeOf((*TX)(nil)) 34 name = "gorm.v2" 35 spec = servicehub.Spec{ 36 Services: []string{"mysql-gorm.v2", "mysql-gorm.v2-client"}, 37 Types: []reflect.Type{ 38 interfaceType, gormType, 39 }, 40 Description: "mysql-gorm.v2", 41 ConfigFunc: func() interface{} { return &config{} }, 42 Creator: func() servicehub.Provider { 43 return &provider{} 44 }, 45 } 46 ) 47 48 func init() { 49 servicehub.Register(name, &spec) 50 } 51 52 // Interface . 53 type Interface interface { 54 // DB returns the raw *gorm.DB. 55 DB() *gorm.DB 56 // Q returns the CRUD APIs without a transaction. 57 Q() *TX 58 // Begin returns the CRUD APIs with a transaction. 59 Begin() *TX 60 } 61 62 type config struct { 63 MySQLURL string `file:"url" env:"MYSQL_URL"` 64 MySQLHost string `file:"host" env:"MYSQL_HOST" default:"localhost"` 65 MySQLPort string `file:"port" env:"MYSQL_PORT" default:"3306"` 66 MySQLUsername string `file:"username" env:"MYSQL_USERNAME" default:"root"` 67 MySQLPassword string `file:"password" env:"MYSQL_PASSWORD" default:""` 68 MySQLDatabase string `file:"database" env:"MYSQL_DATABASE"` 69 MySQLMaxIdleConns uint64 `file:"max_idle_conns" env:"MYSQL_MAXIDLECONNS" default:"10"` 70 MySQLMaxOpenConns uint64 `file:"max_open_conns" env:"MYSQL_MAXOPENCONNS" default:"20"` 71 MySQLMaxLifeTime time.Duration `file:"max_lifetime" env:"MYSQL_MAXLIFETIME" default:"30m"` 72 MySQLDebug bool `file:"debug" env:"MYSQL_DEBUG" default:"false"` 73 MySQLCharset string `file:"charset" env:"MYSQL_CHARSET" default:"utf8mb4"` 74 MySQLTLS string `file:"tls" env:"MYSQL_TLS"` 75 MySQLCaCertPath string `file:"ca_cert_path" env:"MYSQL_CACERTPATH"` 76 MySQLClientCertPath string `file:"client_cert_path" env:"MYSQL_CLIENTCERTPATH"` 77 MySQLClientKeyPath string `file:"client_key_path" env:"MYSQL_CLIENTKEYPATH"` 78 } 79 80 func (c *config) url() string { 81 if c.MySQLURL != "" { 82 return c.MySQLURL 83 } 84 85 url := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=%s&parseTime=True&loc=Local", 86 c.MySQLUsername, c.MySQLPassword, c.MySQLHost, c.MySQLPort, c.MySQLDatabase, c.MySQLCharset) 87 if c.MySQLTLS != "" { 88 url = fmt.Sprintf("%v&tls=%s", url, c.MySQLTLS) 89 } 90 return url 91 } 92 93 // provider . 94 type provider struct { 95 Cfg *config 96 db *gorm.DB 97 tx *TX 98 } 99 100 // Init implements servicehub.ProviderInitializer 101 func (p *provider) Init(ctx servicehub.Context) error { 102 err := mysqldriver.OpenTLS(p.Cfg.MySQLTLS, p.Cfg.MySQLCaCertPath, p.Cfg.MySQLClientCertPath, p.Cfg.MySQLClientKeyPath) 103 if err != nil { 104 return err 105 } 106 107 logrus.WithField("provider", name).Infoln("init") 108 db, err := gorm.Open(mysql.Open(p.Cfg.url())) 109 if err != nil { 110 return fmt.Errorf("fail to connect mysql: %s", err) 111 } 112 113 s, err := db.DB() 114 if err != nil { 115 return fmt.Errorf("failed to get a conn pool") 116 } 117 118 // connection pool 119 s.SetMaxIdleConns(int(p.Cfg.MySQLMaxIdleConns)) 120 s.SetMaxOpenConns(int(p.Cfg.MySQLMaxOpenConns)) 121 s.SetConnMaxLifetime(p.Cfg.MySQLMaxLifeTime) 122 p.db = db 123 if p.Cfg.MySQLDebug { 124 p.db = p.db.Debug() 125 } 126 127 return nil 128 } 129 130 // DB implements Interface.DB 131 func (p *provider) DB() *gorm.DB { return p.db } 132 133 // Q implements Interface.Q 134 func (p *provider) Q() *TX { 135 return &TX{ 136 db: p.db, 137 valid: true, 138 } 139 } 140 141 // Begin implements Interface.Begin 142 func (p *provider) Begin() *TX { 143 return &TX{ 144 db: p.db, 145 valid: true, 146 inTx: true, 147 } 148 } 149 150 // Provide implements servicehub.DependencyProvider 151 func (p *provider) Provide(ctx servicehub.DependencyContext, args ...interface{}) interface{} { 152 if ctx.Service() == "mysql-gorm.v2-client" || ctx.Type() == gormType { 153 return p.db 154 } 155 return p 156 }