From 0d34f2abeef009e2e97d8b6100a8c2b628be3edf Mon Sep 17 00:00:00 2001 From: Leon <147289645+LeoninCS@users.noreply.github.com> Date: Wed, 24 Dec 2025 14:08:28 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E4=BA=86=E9=98=B2?= =?UTF-8?q?=E5=87=BB=E7=A9=BF=E9=94=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/redis/cache.go | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/internal/redis/cache.go b/internal/redis/cache.go index 416ce9e..c9f6190 100644 --- a/internal/redis/cache.go +++ b/internal/redis/cache.go @@ -2,6 +2,8 @@ package redis import ( "context" + "crypto/rand" + "encoding/hex" "os" "strconv" "time" @@ -65,3 +67,39 @@ func (c *Client) Del(ctx context.Context, key string) error { func IsMiss(err error) bool { return err == redis.Nil } + +func randToken(n int) (string, error) { + b := make([]byte, n) + if _, err := rand.Read(b); err != nil { + return "", err + } + return hex.EncodeToString(b), nil +} + +func (c *Client) Lock(ctx context.Context, key string, ttl time.Duration) (token string, ok bool, err error) { + if c == nil || c.rdb == nil { + return "", false, nil + } + token, err = randToken(16) + if err != nil { + return "", false, err + } + ok, err = c.rdb.SetNX(ctx, key, token, ttl).Result() + return token, ok, err +} + +var unlockScript = redis.NewScript(` +if redis.call("GET", KEYS[1]) == ARGV[1] then + return redis.call("DEL", KEYS[1]) +else + return 0 +end +`) + +func (c *Client) Unlock(ctx context.Context, key string, token string) error { + if c == nil || c.rdb == nil { + return nil + } + _, err := unlockScript.Run(ctx, c.rdb, []string{key}, token).Result() + return err +}