package models
|
|
import (
|
"fmt"
|
"gorm.io/gorm"
|
"time"
|
"wms/pkg/mysqlx"
|
)
|
|
type (
|
// Lock 分布式锁
|
Lock struct {
|
LockName string `gorm:"primaryKey"`
|
LockedBy string
|
LockedAt time.Time
|
}
|
|
LockSearch struct {
|
Lock
|
Orm *gorm.DB
|
}
|
)
|
|
func (slf *Lock) TableName() string {
|
return "distributed_lock"
|
}
|
|
func NewLockSearch() *LockSearch {
|
return &LockSearch{Orm: mysqlx.GetDB()}
|
}
|
|
func (slf *LockSearch) SetOrm(tx *gorm.DB) *LockSearch {
|
slf.Orm = tx
|
|
return slf
|
}
|
|
func (slf *LockSearch) SetLockName(lockName string) *LockSearch {
|
slf.LockName = lockName
|
return slf
|
}
|
|
func (slf *LockSearch) SetLockedBy(lockedBy string) *LockSearch {
|
slf.LockedBy = lockedBy
|
return slf
|
}
|
|
func (slf *LockSearch) build() *gorm.DB {
|
var db = slf.Orm.Model(&Lock{})
|
|
if slf.LockName != "" {
|
db = db.Where("lock_name = ?", slf.LockName)
|
}
|
|
if slf.LockedBy != "" {
|
db = db.Where("locked_by = ?", slf.LockedBy)
|
}
|
|
return db
|
}
|
|
// Create 单条插入
|
func (slf *LockSearch) Create(record *Lock) error {
|
var db = slf.build()
|
|
if err := db.Create(record).Error; err != nil {
|
return err
|
}
|
|
return nil
|
}
|
|
func (slf *LockSearch) Delete() error {
|
var db = slf.build()
|
return db.Delete(&Lock{}).Error
|
}
|
|
func (slf *LockSearch) First() (*Lock, error) {
|
var (
|
record = new(Lock)
|
db = slf.build()
|
)
|
|
if err := db.First(record).Error; err != nil {
|
return record, err
|
}
|
|
return record, nil
|
}
|
|
func (slf *LockSearch) AcquireLock(lockName, serviceID string) error {
|
err := WithTransaction(func(db *gorm.DB) error {
|
lock, err := slf.SetLockName(lockName).SetLockedBy(serviceID).First()
|
if err != nil && err != gorm.ErrRecordNotFound {
|
return err
|
}
|
if lock.LockedBy != "" {
|
return fmt.Errorf("AcquireLock failed, lockName: %s, serviceID: %+v", lockName, serviceID)
|
}
|
return slf.Create(&Lock{
|
LockName: lockName,
|
LockedBy: serviceID,
|
LockedAt: time.Now(),
|
})
|
})
|
return err
|
}
|
|
func (slf *LockSearch) ReleaseLock(lockName, serviceID string) error {
|
err := slf.SetLockName(lockName).SetLockedBy(serviceID).Delete()
|
if err != nil {
|
return fmt.Errorf("AcquireLock err: %v, lockName: %s, serviceID: %+v", err, lockName, serviceID)
|
}
|
return nil
|
}
|