fix: align admin behavior and Kratos integrations
This commit is contained in:
+78
-35
@@ -16,21 +16,71 @@ import (
|
||||
var ProviderSet = wire.NewSet(NewData, NewSystemRepo, NewAccessRepo, NewMenuRepo, NewOrganizationRepo, NewSettingsRepo, NewVersionRepo, NewExportRepo, NewAuditRepo, NewTaskRepo, NewMediaRepo, NewAnnouncementRepo, NewEmailRepo, NewCache, NewFileStorage)
|
||||
|
||||
type Data struct {
|
||||
mu sync.RWMutex
|
||||
initMu sync.Mutex
|
||||
gormDB *gorm.DB
|
||||
redis *redis.Client
|
||||
database *conf.Data_Database
|
||||
config *conf.Data
|
||||
admin *conf.AdminBackend
|
||||
configMu sync.Mutex
|
||||
gormDB *reloadableDB
|
||||
redis *reloadableRedis
|
||||
runtime *conf.Runtime
|
||||
storage *reloadableStorage
|
||||
dbListMu sync.RWMutex
|
||||
dbList map[string]*gorm.DB
|
||||
}
|
||||
|
||||
func NewData(c *conf.Data, admin *conf.AdminBackend) (*Data, func(), error) {
|
||||
func openDatabaseList(configs []*conf.Data_Database) (map[string]*gorm.DB, error) {
|
||||
items := make(map[string]*gorm.DB)
|
||||
for _, config := range configs {
|
||||
if config == nil || config.Disable || config.AliasName == "" {
|
||||
continue
|
||||
}
|
||||
db, err := openDatabase(config, false, "")
|
||||
if err != nil {
|
||||
for _, opened := range items {
|
||||
if sqlDB, dbErr := opened.DB(); dbErr == nil {
|
||||
_ = sqlDB.Close()
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("open database %q: %w", config.AliasName, err)
|
||||
}
|
||||
items[config.AliasName] = db
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
func closeDatabaseList(items map[string]*gorm.DB) {
|
||||
for _, db := range items {
|
||||
if sqlDB, err := db.DB(); err == nil {
|
||||
_ = sqlDB.Close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Data) replaceDatabaseList(items map[string]*gorm.DB) {
|
||||
d.dbListMu.Lock()
|
||||
old := d.dbList
|
||||
d.dbList = items
|
||||
d.dbListMu.Unlock()
|
||||
closeDatabaseList(old)
|
||||
}
|
||||
|
||||
func (d *Data) database(name string) (*gorm.DB, error) {
|
||||
if name == "" {
|
||||
return d.gormDB.DB(), nil
|
||||
}
|
||||
d.dbListMu.RLock()
|
||||
db := d.dbList[name]
|
||||
d.dbListMu.RUnlock()
|
||||
if db == nil {
|
||||
return nil, fmt.Errorf("database %q not found", name)
|
||||
}
|
||||
return db, nil
|
||||
}
|
||||
|
||||
func NewData(runtime *conf.Runtime) (*Data, func(), error) {
|
||||
c := runtime.Data()
|
||||
if c == nil || c.Database == nil {
|
||||
return nil, nil, fmt.Errorf("database configuration is required")
|
||||
}
|
||||
d := &Data{database: c.Database, config: c, admin: admin}
|
||||
d := &Data{runtime: runtime}
|
||||
db, err := openDatabase(c.Database, false, "")
|
||||
usingFallback := false
|
||||
if err != nil {
|
||||
@@ -43,31 +93,33 @@ func NewData(c *conf.Data, admin *conf.AdminBackend) (*Data, func(), error) {
|
||||
}
|
||||
usingFallback = true
|
||||
}
|
||||
d.gormDB = db
|
||||
if !usingFallback {
|
||||
d.gormDB = newReloadableDB(db)
|
||||
d.dbList, err = openDatabaseList(c.DatabaseList)
|
||||
if err != nil {
|
||||
d.gormDB.close()
|
||||
return nil, nil, err
|
||||
}
|
||||
admin := runtime.Admin()
|
||||
disableAutoMigrate := admin != nil && admin.System != nil && admin.System.DisableAutoMigrate
|
||||
if !usingFallback && !disableAutoMigrate {
|
||||
if err = migrateAll(db); err != nil {
|
||||
return nil, nil, fmt.Errorf("migrate tables: %w", err)
|
||||
}
|
||||
}
|
||||
if candidate := openRedis(c.Redis); candidate != nil {
|
||||
d.redis = candidate
|
||||
}
|
||||
useRedis := admin != nil && admin.System != nil && admin.System.UseRedis
|
||||
d.redis = newReloadableRedis(openRedis(c.Redis, useRedis))
|
||||
stopConfigWatcher := d.watchConfig()
|
||||
cleanup := func() {
|
||||
d.mu.RLock()
|
||||
db := d.gormDB
|
||||
d.mu.RUnlock()
|
||||
if sqlDB, closeErr := db.DB(); closeErr == nil {
|
||||
_ = sqlDB.Close()
|
||||
}
|
||||
if d.redis != nil {
|
||||
_ = d.redis.Close()
|
||||
}
|
||||
stopConfigWatcher()
|
||||
d.gormDB.close()
|
||||
closeDatabaseList(d.dbList)
|
||||
d.redis.close()
|
||||
}
|
||||
return d, cleanup, nil
|
||||
}
|
||||
|
||||
func openRedis(config *conf.Data_Redis) *redis.Client {
|
||||
if config == nil || config.Addr == "" {
|
||||
func openRedis(config *conf.Data_Redis, enabled bool) *redis.Client {
|
||||
if !enabled || config == nil || config.Addr == "" {
|
||||
return nil
|
||||
}
|
||||
options := &redis.Options{Addr: config.Addr, Network: config.Network}
|
||||
@@ -89,15 +141,6 @@ func openRedis(config *conf.Data_Redis) *redis.Client {
|
||||
}
|
||||
|
||||
func (d *Data) activateDatabase(db *gorm.DB, config *conf.Data_Database) {
|
||||
d.mu.Lock()
|
||||
old := d.gormDB
|
||||
d.gormDB = db
|
||||
d.database = config
|
||||
d.config.Database = config
|
||||
d.mu.Unlock()
|
||||
if old != nil {
|
||||
if sqlDB, e := old.DB(); e == nil {
|
||||
_ = sqlDB.Close()
|
||||
}
|
||||
}
|
||||
d.gormDB.replace(db)
|
||||
d.runtime.UpdateDatabase(config)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user