component.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. package mhayaGORM
  2. import (
  3. "fmt"
  4. "time"
  5. cfacade "github.com/mhaya/facade"
  6. clog "github.com/mhaya/logger"
  7. cprofile "github.com/mhaya/profile"
  8. "gorm.io/driver/mysql"
  9. "gorm.io/gorm"
  10. "gorm.io/gorm/logger"
  11. )
  12. const (
  13. Name = "gorm_component"
  14. dsn = "%s:%s@(%s)/%s?charset=utf8&parseTime=True&loc=Local"
  15. )
  16. type (
  17. Component struct {
  18. cfacade.Component
  19. // key:groupId,value:{key:id,value:*gorm.Db}
  20. ormMap map[string]map[string]*gorm.DB
  21. }
  22. mySqlConfig struct {
  23. Enable bool
  24. GroupId string
  25. Id string
  26. DbName string
  27. Host string
  28. UserName string
  29. Password string
  30. MaxIdleConnect int
  31. MaxOpenConnect int
  32. LogMode bool
  33. DSN string
  34. }
  35. // HashDb hash by group id
  36. HashDb func(dbMaps map[string]*gorm.DB) string
  37. )
  38. func NewComponent() *Component {
  39. return &Component{
  40. ormMap: make(map[string]map[string]*gorm.DB),
  41. }
  42. }
  43. func (s *Component) Name() string {
  44. return Name
  45. }
  46. func parseMysqlConfig(groupId string, item cfacade.ProfileJSON) *mySqlConfig {
  47. return &mySqlConfig{
  48. GroupId: groupId,
  49. Id: item.GetString("db_id"),
  50. DSN: item.GetString("dsn", ""),
  51. DbName: item.GetString("db_name"),
  52. Host: item.GetString("host"),
  53. UserName: item.GetString("user_name"),
  54. Password: item.GetString("password"),
  55. MaxIdleConnect: item.GetInt("max_idle_connect", 4),
  56. MaxOpenConnect: item.GetInt("max_open_connect", 8),
  57. LogMode: item.GetBool("log_mode", true),
  58. Enable: item.GetBool("enable", true),
  59. }
  60. }
  61. func (s *Component) Init() {
  62. // load only the database contained in the `db_id_list`
  63. dbIdList := s.App().Settings().Get("db_id_list")
  64. if dbIdList.LastError() != nil || dbIdList.Size() < 1 {
  65. clog.Warnf("[nodeId = %s] `db_id_list` property not exists.", s.App().NodeId())
  66. return
  67. }
  68. dbConfig := cprofile.GetConfig("database")
  69. if dbConfig.LastError() != nil {
  70. clog.Panic("`database` property not exists in profile file.")
  71. }
  72. for _, groupId := range dbConfig.Keys() {
  73. s.ormMap[groupId] = make(map[string]*gorm.DB)
  74. dbGroup := dbConfig.GetConfig(groupId)
  75. for i := 0; i < dbGroup.Size(); i++ {
  76. item := dbGroup.GetConfig(i)
  77. mysqlConfig := parseMysqlConfig(groupId, item)
  78. for _, key := range dbIdList.Keys() {
  79. if dbIdList.Get(key).ToString() != mysqlConfig.Id {
  80. continue
  81. }
  82. if !mysqlConfig.Enable {
  83. clog.Panicf("[dbName = %s] is disabled!", mysqlConfig.DbName)
  84. }
  85. db, err := s.createORM(mysqlConfig)
  86. if err != nil {
  87. clog.Panicf("[dbName = %s] create orm fail. error = %s", mysqlConfig.DbName, err)
  88. }
  89. s.ormMap[groupId][mysqlConfig.Id] = db
  90. clog.Infof("[dbGroup =%s, dbName = %s] is connected.", mysqlConfig.GroupId, mysqlConfig.Id)
  91. }
  92. }
  93. }
  94. }
  95. func (s *Component) createORM(cfg *mySqlConfig) (*gorm.DB, error) {
  96. db, err := gorm.Open(mysql.Open(cfg.GetDSN()), &gorm.Config{
  97. Logger: getLogger(),
  98. })
  99. if err != nil {
  100. return nil, err
  101. }
  102. sqlDB, err := db.DB()
  103. if err != nil {
  104. return nil, err
  105. }
  106. sqlDB.SetMaxIdleConns(cfg.MaxIdleConnect)
  107. sqlDB.SetMaxOpenConns(cfg.MaxOpenConnect)
  108. sqlDB.SetConnMaxLifetime(time.Minute)
  109. if cfg.LogMode {
  110. return db.Debug(), nil
  111. }
  112. return db, nil
  113. }
  114. func getLogger() logger.Interface {
  115. return logger.New(
  116. gormLogger{log: clog.DefaultLogger},
  117. logger.Config{
  118. SlowThreshold: time.Second,
  119. LogLevel: logger.Silent,
  120. Colorful: true,
  121. },
  122. )
  123. }
  124. func (s *Component) GetDb(id string) *gorm.DB {
  125. for _, group := range s.ormMap {
  126. for k, v := range group {
  127. if k == id {
  128. return v
  129. }
  130. }
  131. }
  132. return nil
  133. }
  134. func (s *Component) GetHashDb(groupId string, hashFn HashDb) (*gorm.DB, bool) {
  135. dbGroup, found := s.GetDbMap(groupId)
  136. if !found {
  137. clog.Warnf("groupId = %s not found.", groupId)
  138. return nil, false
  139. }
  140. dbId := hashFn(dbGroup)
  141. db, found := dbGroup[dbId]
  142. return db, found
  143. }
  144. func (s *Component) GetDbMap(groupId string) (map[string]*gorm.DB, bool) {
  145. dbGroup, found := s.ormMap[groupId]
  146. return dbGroup, found
  147. }
  148. func (s *mySqlConfig) GetDSN() string {
  149. if s.DSN == "" {
  150. s.DSN = dsn
  151. }
  152. return fmt.Sprintf(s.DSN, s.UserName, s.Password, s.Host, s.DbName)
  153. }