fix(server): refactor server model methods to support transaction handling
This commit is contained in:
@@ -23,10 +23,10 @@ type (
|
||||
customServerLogicModel
|
||||
}
|
||||
serverModel interface {
|
||||
Insert(ctx context.Context, data *Server) error
|
||||
Insert(ctx context.Context, data *Server, tx ...*gorm.DB) error
|
||||
FindOne(ctx context.Context, id int64) (*Server, error)
|
||||
Update(ctx context.Context, data *Server) error
|
||||
Delete(ctx context.Context, id int64) error
|
||||
Update(ctx context.Context, data *Server, tx ...*gorm.DB) error
|
||||
Delete(ctx context.Context, id int64, tx ...*gorm.DB) error
|
||||
Transaction(ctx context.Context, fn func(db *gorm.DB) error) error
|
||||
}
|
||||
|
||||
@@ -77,8 +77,11 @@ func (m *defaultServerModel) getCacheKeys(data *Server) []string {
|
||||
return cacheKeys
|
||||
}
|
||||
|
||||
func (m *defaultServerModel) Insert(ctx context.Context, data *Server) error {
|
||||
func (m *defaultServerModel) Insert(ctx context.Context, data *Server, tx ...*gorm.DB) error {
|
||||
err := m.ExecCtx(ctx, func(conn *gorm.DB) error {
|
||||
if len(tx) > 0 {
|
||||
conn = tx[0]
|
||||
}
|
||||
return conn.Create(&data).Error
|
||||
}, m.getCacheKeys(data)...)
|
||||
return err
|
||||
@@ -98,19 +101,21 @@ func (m *defaultServerModel) FindOne(ctx context.Context, id int64) (*Server, er
|
||||
}
|
||||
}
|
||||
|
||||
func (m *defaultServerModel) Update(ctx context.Context, data *Server) error {
|
||||
func (m *defaultServerModel) Update(ctx context.Context, data *Server, tx ...*gorm.DB) error {
|
||||
old, err := m.FindOne(ctx, data.Id)
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
err = m.ExecCtx(ctx, func(conn *gorm.DB) error {
|
||||
db := conn
|
||||
return db.Save(data).Error
|
||||
if len(tx) > 0 {
|
||||
conn = tx[0]
|
||||
}
|
||||
return conn.Save(data).Error
|
||||
}, m.getCacheKeys(old)...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *defaultServerModel) Delete(ctx context.Context, id int64) error {
|
||||
func (m *defaultServerModel) Delete(ctx context.Context, id int64, tx ...*gorm.DB) error {
|
||||
data, err := m.FindOne(ctx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
@@ -119,8 +124,10 @@ func (m *defaultServerModel) Delete(ctx context.Context, id int64) error {
|
||||
return err
|
||||
}
|
||||
err = m.ExecCtx(ctx, func(conn *gorm.DB) error {
|
||||
db := conn
|
||||
return db.Delete(&Server{}, id).Error
|
||||
if len(tx) > 0 {
|
||||
conn = tx[0]
|
||||
}
|
||||
return conn.Delete(&Server{}, id).Error
|
||||
}, m.getCacheKeys(data)...)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -52,33 +52,26 @@ func (*Server) TableName() string {
|
||||
|
||||
func (s *Server) BeforeDelete(tx *gorm.DB) error {
|
||||
logger.Debugf("[Server] BeforeDelete")
|
||||
|
||||
if err := tx.Exec("UPDATE `server` SET sort = sort - 1 WHERE sort > ?", s.Sort).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
// 删除后重新排序,防止因 sort 缺口导致问题
|
||||
if err := reorderSort(tx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) BeforeUpdate(tx *gorm.DB) error {
|
||||
logger.Debugf("[Server] BeforeUpdate")
|
||||
|
||||
var count int64
|
||||
if err := tx.Model(&Server{}).Where("sort = ? AND id != ?", s.Sort, s.Id).Count(&count).Error; err != nil {
|
||||
if err := tx.Set("gorm:query_option", "FOR UPDATE").Model(&Server{}).
|
||||
Where("sort = ? AND id != ?", s.Sort, s.Id).Count(&count).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
logger.Debugf("[Server] Duplicate sort found, reordering...")
|
||||
if err := reorderSort(tx); err != nil {
|
||||
var maxSort int64
|
||||
if err := tx.Model(&Server{}).Select("MAX(sort)").Scan(&maxSort).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
s.Sort = maxSort + 1
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -191,17 +184,13 @@ func (RuleGroup) TableName() string {
|
||||
}
|
||||
|
||||
func reorderSort(tx *gorm.DB) error {
|
||||
var servers []*Server
|
||||
if err := tx.Model(&Server{}).Order("sort ASC").Find(&servers).Error; err != nil {
|
||||
var servers []Server
|
||||
if err := tx.Order("sort, id").Find(&servers).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i, server := range servers {
|
||||
newSort := int64(i + 1)
|
||||
if server.Sort != newSort {
|
||||
if err := tx.Model(&Server{}).
|
||||
Where("id = ?", server.Id).
|
||||
Update("sort", newSort).Error; err != nil {
|
||||
if server.Sort != int64(i)+1 {
|
||||
if err := tx.Exec("UPDATE `server` SET sort = ? WHERE id = ?", i+1, server.Id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user