-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
data.go
119 lines (108 loc) · 3.43 KB
/
data.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package data
import (
"database/sql"
"fmt"
"strings"
"github.com/go-kratos/kratos/v2/log"
"github.com/go-redis/cache/v9"
"github.com/go-redsync/redsync/v4"
"github.com/go-redsync/redsync/v4/redis/goredis/v9"
"github.com/google/wire"
"github.com/kwstars/film-hive/app/metadata/service/internal/conf"
"github.com/pkg/errors"
"github.com/redis/go-redis/extra/redisotel/v9"
"github.com/redis/go-redis/v9"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/plugin/opentelemetry/tracing"
)
// ProviderSet is data providers.
var ProviderSet = wire.NewSet(NewData, NewMetadataRepo)
// Data .
type Data struct {
db *gorm.DB
cache *cache.Cache
dlock *redsync.Redsync
dataConf *conf.Data
}
// NewData .
func NewData(c *conf.Bootstrap, logger log.Logger) (data *Data, closer func(), err error) {
var (
helper = log.NewHelper(logger, log.WithMessageKey("metadata data"))
db *gorm.DB
rdb *redis.Client
)
if rdb, err = newRedis(c.Data); err != nil {
return
}
pool := goredis.NewPool(rdb)
mycache := cache.New(&cache.Options{
Redis: rdb,
// LocalCache: cache.NewTinyLFU(1000, time.Minute),
})
if db, err = newDB(c.Data, helper); err != nil {
return
}
closer = func() {
helper.Info("closing the data resources")
if err = rdb.Close(); err != nil {
helper.Infof("Redis close: %v", err)
}
var sqlDB *sql.DB
if sqlDB, err = db.DB(); err != nil {
err = sqlDB.Close()
helper.Infof("MySQL close: %v", err)
}
}
data = &Data{
db: db,
cache: mycache,
dlock: redsync.New(pool),
dataConf: c.Data,
}
return
}
func newRedis(c *conf.Data) (rdb *redis.Client, err error) {
rdb = redis.NewClient(&redis.Options{
Addr: c.Redis.Addr,
Password: c.Redis.Password,
DB: int(c.Redis.Db),
DialTimeout: c.Redis.DialTimeout.AsDuration(),
WriteTimeout: c.Redis.WriteTimeout.AsDuration(),
ReadTimeout: c.Redis.ReadTimeout.AsDuration(),
})
// Enable tracing instrumentation.
if err = redisotel.InstrumentTracing(rdb); err != nil {
return nil, err
}
return
}
func newDB(c *conf.Data, helper *log.Helper) (db *gorm.DB, err error) {
if db, err = gorm.Open(mysql.New(mysql.Config{
DSN: c.Database.GetSource(), // data source name
DefaultStringSize: 256, // default size for string fields
DisableDatetimePrecision: true, // disable datetime precision, which not supported before MySQL 5.6
DontSupportRenameIndex: true, // drop & create when rename index, rename index not supported before MySQL 5.7, MariaDB
DontSupportRenameColumn: true, // `change` when rename column, rename column not supported before MySQL 8, MariaDB
SkipInitializeWithVersion: false, // autoconfigure based on currently MySQL version
}), &gorm.Config{}); err != nil {
return
}
if err = db.Use(tracing.NewPlugin(tracing.WithoutMetrics())); err != nil {
return
}
// NOTE: GORM has problem detecting existing columns, see
// https://github.com/gogs/gogs/issues/6091. Therefore, only use it to create new
// tables, and do customize migration with future changes.
for _, table := range Tables {
if db.Migrator().HasTable(table) {
continue
}
name := strings.TrimPrefix(fmt.Sprintf("%T", table), "*db.")
if err = db.Migrator().AutoMigrate(table); err != nil {
return nil, errors.Wrapf(err, "auto migrate %q", name)
}
helper.Infof("Auto migrated %q", name)
}
return
}