github.com/erda-project/erda-infra@v1.0.9/providers/mysqlxorm/xorm.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 mysqlxorm
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"reflect"
    21  	"time"
    22  
    23  	_ "github.com/go-sql-driver/mysql" // mysql client driver package
    24  	"github.com/xormplus/core"
    25  	"github.com/xormplus/xorm"
    26  
    27  	"github.com/erda-project/erda-infra/base/logs"
    28  	"github.com/erda-project/erda-infra/base/servicehub"
    29  	"github.com/erda-project/erda-infra/pkg/mysqldriver"
    30  )
    31  
    32  // Interface .
    33  type Interface interface {
    34  	DB() *xorm.Engine
    35  	NewSession(ops ...SessionOption) *Session
    36  }
    37  
    38  var (
    39  	interfaceType = reflect.TypeOf((*Interface)(nil)).Elem()
    40  	xormType      = reflect.TypeOf((*xorm.Engine)(nil))
    41  )
    42  
    43  type config struct {
    44  	MySQLURL            string        `file:"url" env:"MYSQL_URL"`
    45  	MySQLHost           string        `file:"host" env:"MYSQL_HOST" default:"localhost"`
    46  	MySQLPort           string        `file:"port" env:"MYSQL_PORT" default:"3306"`
    47  	MySQLUsername       string        `file:"username" env:"MYSQL_USERNAME" default:"root"`
    48  	MySQLPassword       string        `file:"password" env:"MYSQL_PASSWORD" default:""`
    49  	MySQLDatabase       string        `file:"database" env:"MYSQL_DATABASE"`
    50  	MySQLMaxIdleConns   uint64        `file:"max_idle_conns" env:"MYSQL_MAXIDLECONNS" default:"10"`
    51  	MySQLMaxOpenConns   uint64        `file:"max_open_conns" env:"MYSQL_MAXOPENCONNS" default:"20"`
    52  	MySQLMaxLifeTime    time.Duration `file:"max_lifetime" env:"MYSQL_MAXLIFETIME" default:"30m"`
    53  	MySQLShowSQL        bool          `file:"show_sql" env:"MYSQL_SHOW_SQL" default:"false"`
    54  	MySQLProperties     string        `file:"properties" env:"MYSQL_PROPERTIES" default:"charset=utf8mb4&collation=utf8mb4_unicode_ci&parseTime=True&loc=Local"`
    55  	MySQLTLS            string        `file:"tls" env:"MYSQL_TLS"`
    56  	MySQLCaCertPath     string        `file:"ca_cert_path" env:"MYSQL_CACERTPATH"`
    57  	MySQLClientCertPath string        `file:"client_cert_path" env:"MYSQL_CLIENTCERTPATH"`
    58  	MySQLClientKeyPath  string        `file:"client_key_path" env:"MYSQL_CLIENTKEYPATH"`
    59  
    60  	MySQLPingWhenInit   bool   `file:"ping_when_init" env:"MYSQL_PING_WHEN_INIT" default:"true"`
    61  	MySQLPingTimeoutSec uint64 `file:"ping_timeout_sec" env:"MYSQL_PING_TIMEOUT_SEC" default:"10"`
    62  }
    63  
    64  func (c *config) url() string {
    65  	if c.MySQLURL != "" {
    66  		return c.MySQLURL
    67  	}
    68  
    69  	url := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?%s",
    70  		c.MySQLUsername, c.MySQLPassword, c.MySQLHost, c.MySQLPort, c.MySQLDatabase, c.MySQLProperties)
    71  	if c.MySQLTLS != "" {
    72  		url = fmt.Sprintf("%v&tls=%s", url, c.MySQLTLS)
    73  	}
    74  	return url
    75  }
    76  
    77  // provider .
    78  type provider struct {
    79  	Cfg *config
    80  	Log logs.Logger
    81  	db  *xorm.Engine
    82  }
    83  
    84  // Init .
    85  func (p *provider) Init(ctx servicehub.Context) error {
    86  	err := mysqldriver.OpenTLS(p.Cfg.MySQLTLS, p.Cfg.MySQLCaCertPath, p.Cfg.MySQLClientCertPath, p.Cfg.MySQLClientKeyPath)
    87  	if err != nil {
    88  		return err
    89  	}
    90  
    91  	db, err := xorm.NewEngine("mysql", p.Cfg.url())
    92  	if err != nil {
    93  		return fmt.Errorf("failed to connect to mysql server, err: %v", err)
    94  	}
    95  
    96  	db.SetMapper(core.GonicMapper{})
    97  	if p.Cfg.MySQLShowSQL {
    98  		db.ShowSQL(true)
    99  		db.ShowExecTime(true)
   100  		db.SetLogLevel(core.LOG_DEBUG)
   101  	}
   102  
   103  	// connection pool
   104  	db.SetMaxIdleConns(int(p.Cfg.MySQLMaxIdleConns))
   105  	db.SetMaxOpenConns(int(p.Cfg.MySQLMaxOpenConns))
   106  	db.SetConnMaxLifetime(p.Cfg.MySQLMaxLifeTime)
   107  	db.SetDisableGlobalCache(true)
   108  
   109  	// ping when init
   110  	if p.Cfg.MySQLPingWhenInit {
   111  		ctxForPing, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(p.Cfg.MySQLPingTimeoutSec))
   112  		defer cancel()
   113  		if err := db.PingContext(ctxForPing); err != nil {
   114  			return err
   115  		}
   116  	}
   117  
   118  	p.db = db
   119  	return nil
   120  }
   121  
   122  func (p *provider) DB() *xorm.Engine { return p.db }
   123  
   124  func (p *provider) Provide(ctx servicehub.DependencyContext, args ...interface{}) interface{} {
   125  	if ctx.Service() == "mysql-xorm-client" || ctx.Type() == xormType {
   126  		return p.db
   127  	}
   128  	return p
   129  }
   130  
   131  func init() {
   132  	servicehub.Register("mysql-xorm", &servicehub.Spec{
   133  		Services: []string{"mysql-xorm", "mysql-xorm-client"},
   134  		Types: []reflect.Type{
   135  			interfaceType, xormType,
   136  		},
   137  		Description: "mysql-xorm",
   138  		ConfigFunc:  func() interface{} { return &config{} },
   139  		Creator: func() servicehub.Provider {
   140  			return &provider{}
   141  		},
   142  	})
   143  }