41 lines
1.0 KiB
Go
41 lines
1.0 KiB
Go
package lock
|
||
|
||
import (
|
||
"context"
|
||
|
||
"github.com/gogf/gf/v2/database/gdb"
|
||
"github.com/gogf/gf/v2/errors/gerror"
|
||
)
|
||
|
||
// TryOptimisticLock 乐观锁通用方法(基于 version 字段)
|
||
// 参数说明:
|
||
// - ctx: 请求上下文
|
||
// - model: 对应表的 gdb.Model,如 dao.User.Ctx(ctx)
|
||
// - idKey: 主键名,通常是 "id"
|
||
// - idVal: 主键值
|
||
// - clientVersion: 前端传来的 version 值
|
||
// 返回:新的 version,如果冲突返回错误
|
||
func TryOptimisticLock(ctx context.Context, model *gdb.Model, idKey string, idVal any, clientVersion int) (newVersion int, err error) {
|
||
if idVal == 0 || clientVersion == 0 {
|
||
return 0, gerror.New("缺少 ID 或版本号参数")
|
||
}
|
||
|
||
// 尝试根据 version 进行原子更新
|
||
result, err := model.
|
||
Where(idKey, idVal).
|
||
Where("version", clientVersion).
|
||
Increment("version", 1)
|
||
|
||
if err != nil {
|
||
return 0, err
|
||
}
|
||
|
||
// 检查是否真的更新成功
|
||
rows, _ := result.RowsAffected()
|
||
if rows == 0 {
|
||
return 0, gerror.New("数据版本冲突,请刷新后重试")
|
||
}
|
||
|
||
return clientVersion + 1, nil
|
||
}
|