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 }