thread-master/apps/backend/internal/lib/redislock/redislock.go

48 lines
1.1 KiB
Go
Raw Normal View History

2026-07-13 08:59:13 +00:00
package redislock
import (
"context"
"fmt"
"time"
"github.com/zeromicro/go-zero/core/stores/redis"
)
// Lock is a small Redis lease. Value must uniquely identify the worker that
// owns it; Release uses a Lua compare-and-delete to avoid deleting a renewed
// lease owned by another worker.
type Lock struct {
client *redis.Redis
key string
owner string
ttl time.Duration
}
func New(conf redis.RedisConf, key, owner string, ttl time.Duration) *Lock {
return &Lock{client: redis.MustNewRedis(conf), key: key, owner: owner, ttl: ttl}
}
func (l *Lock) Acquire(ctx context.Context) (bool, error) {
if l == nil || l.client == nil || l.key == "" || l.owner == "" {
return false, fmt.Errorf("invalid redis lock")
}
seconds := int(l.ttl.Seconds())
if seconds < 1 {
seconds = 1
}
return l.client.SetnxExCtx(ctx, l.key, l.owner, seconds)
}
func (l *Lock) Release(ctx context.Context) error {
if l == nil || l.client == nil {
return fmt.Errorf("invalid redis lock")
}
_, err := l.client.EvalCtx(ctx, `
if redis.call('GET', KEYS[1]) == ARGV[1] then
return redis.call('DEL', KEYS[1])
end
return 0
`, []string{l.key}, l.owner)
return err
}