1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 |
- package global
- import (
- "context"
- "designs/utils"
- "github.com/go-redis/redis/v8"
- "time"
- )
- type Interface interface {
- Get() bool
- Block(seconds int64) bool
- Release() bool
- ForceRelease()
- }
- type lock struct {
- context context.Context
- name string
- owner string
- seconds int64
- }
- const releaseLockLuaScript = `
- if redis.call("get",KEYS[1]) == ARGV[1] then
- return redis.call("del",KEYS[1])
- else
- return 0
- end
- `
- func Lock(name string, seconds int64) Interface {
- return &lock{
- context.Background(),
- name,
- utils.RandString(16),
- seconds,
- }
- }
- func (l *lock) Get() bool {
- return App.Redis.SetNX(l.context, l.name, l.owner, time.Duration(l.seconds)*time.Second).Val()
- }
- func (l *lock) Block(seconds int64) bool {
- timer := time.After(time.Duration(seconds) * time.Second)
- for {
- select {
- case <-timer:
- return false
- default:
- if l.Get() {
- return true
- }
- time.Sleep(time.Duration(1) * time.Second)
- }
- }
- }
- func (l *lock) Release() bool {
- luaScript := redis.NewScript(releaseLockLuaScript)
- result := luaScript.Run(l.context, App.Redis, []string{l.name}, l.owner).Val().(int64)
- return result != 0
- }
- func (l *lock) ForceRelease() {
- App.Redis.Del(l.context, l.name).Val()
- }
|