fix(server): refactor server model methods to support transaction handling
This commit is contained in:
parent
38bcacc9e7
commit
3cadd9e621
@ -2,11 +2,11 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/perfect-panel/server/pkg/tool"
|
||||||
|
|
||||||
"github.com/perfect-panel/server/internal/svc"
|
"github.com/perfect-panel/server/internal/svc"
|
||||||
"github.com/perfect-panel/server/internal/types"
|
"github.com/perfect-panel/server/internal/types"
|
||||||
"github.com/perfect-panel/server/pkg/logger"
|
"github.com/perfect-panel/server/pkg/logger"
|
||||||
"github.com/perfect-panel/server/pkg/tool"
|
|
||||||
"github.com/perfect-panel/server/pkg/xerr"
|
"github.com/perfect-panel/server/pkg/xerr"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@ -29,20 +29,23 @@ func NewDeleteNodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Delete
|
|||||||
func (l *DeleteNodeLogic) DeleteNode(req *types.DeleteNodeRequest) error {
|
func (l *DeleteNodeLogic) DeleteNode(req *types.DeleteNodeRequest) error {
|
||||||
err := l.svcCtx.DB.Transaction(func(tx *gorm.DB) error {
|
err := l.svcCtx.DB.Transaction(func(tx *gorm.DB) error {
|
||||||
// Delete server
|
// Delete server
|
||||||
err := l.svcCtx.ServerModel.Delete(l.ctx, req.Id)
|
err := l.svcCtx.ServerModel.Delete(l.ctx, req.Id, tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Delete server to subscribe
|
// Delete server to subscribe
|
||||||
subs, err := l.svcCtx.SubscribeModel.QuerySubscribeIdsByServerIdAndServerGroupId(l.ctx, req.Id, 0)
|
subs, err := l.svcCtx.SubscribeModel.QuerySubscribeIdsByServerIdAndServerGroupId(l.ctx, req.Id, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
l.Logger.Errorf("[DeleteNode] QuerySubscribeIdsByServerIdAndServerGroupId error: %v", err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, sub := range subs {
|
for _, sub := range subs {
|
||||||
servers := tool.StringToInt64Slice(sub.Server)
|
servers := tool.StringToInt64Slice(sub.Server)
|
||||||
newServers := tool.RemoveElementBySlice(servers, req.Id)
|
newServers := tool.RemoveElementBySlice(servers, req.Id)
|
||||||
sub.Server = tool.Int64SliceToString(newServers)
|
sub.Server = tool.Int64SliceToString(newServers)
|
||||||
if err = l.svcCtx.SubscribeModel.Update(l.ctx, sub); err != nil {
|
if err = l.svcCtx.SubscribeModel.Update(l.ctx, sub, tx); err != nil {
|
||||||
|
l.Logger.Errorf("[DeleteNode] UpdateSubscribe error: %v", err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,10 +23,10 @@ type (
|
|||||||
customServerLogicModel
|
customServerLogicModel
|
||||||
}
|
}
|
||||||
serverModel interface {
|
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)
|
FindOne(ctx context.Context, id int64) (*Server, error)
|
||||||
Update(ctx context.Context, data *Server) error
|
Update(ctx context.Context, data *Server, tx ...*gorm.DB) error
|
||||||
Delete(ctx context.Context, id int64) error
|
Delete(ctx context.Context, id int64, tx ...*gorm.DB) error
|
||||||
Transaction(ctx context.Context, fn func(db *gorm.DB) error) 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
|
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 {
|
err := m.ExecCtx(ctx, func(conn *gorm.DB) error {
|
||||||
|
if len(tx) > 0 {
|
||||||
|
conn = tx[0]
|
||||||
|
}
|
||||||
return conn.Create(&data).Error
|
return conn.Create(&data).Error
|
||||||
}, m.getCacheKeys(data)...)
|
}, m.getCacheKeys(data)...)
|
||||||
return err
|
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)
|
old, err := m.FindOne(ctx, data.Id)
|
||||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = m.ExecCtx(ctx, func(conn *gorm.DB) error {
|
err = m.ExecCtx(ctx, func(conn *gorm.DB) error {
|
||||||
db := conn
|
if len(tx) > 0 {
|
||||||
return db.Save(data).Error
|
conn = tx[0]
|
||||||
|
}
|
||||||
|
return conn.Save(data).Error
|
||||||
}, m.getCacheKeys(old)...)
|
}, m.getCacheKeys(old)...)
|
||||||
return err
|
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)
|
data, err := m.FindOne(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
@ -119,8 +124,10 @@ func (m *defaultServerModel) Delete(ctx context.Context, id int64) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = m.ExecCtx(ctx, func(conn *gorm.DB) error {
|
err = m.ExecCtx(ctx, func(conn *gorm.DB) error {
|
||||||
db := conn
|
if len(tx) > 0 {
|
||||||
return db.Delete(&Server{}, id).Error
|
conn = tx[0]
|
||||||
|
}
|
||||||
|
return conn.Delete(&Server{}, id).Error
|
||||||
}, m.getCacheKeys(data)...)
|
}, m.getCacheKeys(data)...)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,33 +52,26 @@ func (*Server) TableName() string {
|
|||||||
|
|
||||||
func (s *Server) BeforeDelete(tx *gorm.DB) error {
|
func (s *Server) BeforeDelete(tx *gorm.DB) error {
|
||||||
logger.Debugf("[Server] BeforeDelete")
|
logger.Debugf("[Server] BeforeDelete")
|
||||||
|
|
||||||
if err := tx.Exec("UPDATE `server` SET sort = sort - 1 WHERE sort > ?", s.Sort).Error; err != nil {
|
if err := tx.Exec("UPDATE `server` SET sort = sort - 1 WHERE sort > ?", s.Sort).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// 删除后重新排序,防止因 sort 缺口导致问题
|
|
||||||
if err := reorderSort(tx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) BeforeUpdate(tx *gorm.DB) error {
|
func (s *Server) BeforeUpdate(tx *gorm.DB) error {
|
||||||
logger.Debugf("[Server] BeforeUpdate")
|
logger.Debugf("[Server] BeforeUpdate")
|
||||||
|
|
||||||
var count int64
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
logger.Debugf("[Server] Duplicate sort found, reordering...")
|
var maxSort int64
|
||||||
if err := reorderSort(tx); err != nil {
|
if err := tx.Model(&Server{}).Select("MAX(sort)").Scan(&maxSort).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
s.Sort = maxSort + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,17 +184,13 @@ func (RuleGroup) TableName() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func reorderSort(tx *gorm.DB) error {
|
func reorderSort(tx *gorm.DB) error {
|
||||||
var servers []*Server
|
var servers []Server
|
||||||
if err := tx.Model(&Server{}).Order("sort ASC").Find(&servers).Error; err != nil {
|
if err := tx.Order("sort, id").Find(&servers).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, server := range servers {
|
for i, server := range servers {
|
||||||
newSort := int64(i + 1)
|
if server.Sort != int64(i)+1 {
|
||||||
if server.Sort != newSort {
|
if err := tx.Exec("UPDATE `server` SET sort = ? WHERE id = ?", i+1, server.Id).Error; err != nil {
|
||||||
if err := tx.Model(&Server{}).
|
|
||||||
Where("id = ?", server.Id).
|
|
||||||
Update("sort", newSort).Error; err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user