feat(error): Add typed error for NOSCRIPT replies from Redis (#3738)

This commit is contained in:
LINKIWI
2026-03-18 17:02:09 +02:00
committed by GitHub
parent 60b46d93fd
commit 2ba8388eed
4 changed files with 45 additions and 2 deletions
+32
View File
@@ -2,6 +2,8 @@ package redis_test
import (
"context"
"crypto/rand"
"crypto/sha1"
"encoding/json"
"fmt"
"reflect"
@@ -8648,6 +8650,21 @@ var _ = Describe("Commands", func() {
Expect(err).NotTo(HaveOccurred())
Expect(vals).To(BeEmpty())
})
It("propagates NOSCRIPT errors on EVALSHA of an unknown digest", func() {
digest := make([]byte, 32)
_, err := rand.Read(digest)
Expect(err).NotTo(HaveOccurred())
_, err = client.EvalSha(
ctx,
fmt.Sprintf("%x", sha1.Sum(digest)),
[]string{},
nil,
).Result()
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(redis.ErrNoScript))
})
})
Describe("EvalRO", func() {
@@ -8682,6 +8699,21 @@ var _ = Describe("Commands", func() {
Expect(err).NotTo(HaveOccurred())
Expect(vals).To(BeEmpty())
})
It("propagates NOSCRIPT errors on EVALSHA_RO of an unknown digest", func() {
digest := make([]byte, 32)
_, err := rand.Read(digest)
Expect(err).NotTo(HaveOccurred())
_, err = client.EvalShaRO(
ctx,
fmt.Sprintf("%x", sha1.Sum(digest)),
[]string{},
nil,
).Result()
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(redis.ErrNoScript))
})
})
Describe("Functions", func() {
+5
View File
@@ -28,6 +28,11 @@ var ErrPoolTimeout = pool.ErrPoolTimeout
// is used on a ClusterClient with keys in different slots.
var ErrCrossSlot = proto.RedisError("CROSSSLOT Keys in request don't hash to the same slot")
// ErrNoScript is returned when EVALSHA is requested for a script digest that
// is not available in the script cache. Note that this error text is reproduced
// literally from that used by Redis.
var ErrNoScript = proto.RedisError("NOSCRIPT No matching script. Please use EVAL.")
// HasErrorPrefix checks if the err is a Redis error and the message contains a prefix.
func HasErrorPrefix(err error, prefix string) bool {
var rErr Error
+3 -2
View File
@@ -4,6 +4,7 @@ import (
"context"
"crypto/sha1"
"encoding/hex"
"errors"
"io"
)
@@ -67,7 +68,7 @@ func (s *Script) EvalShaRO(ctx context.Context, c Scripter, keys []string, args
// it is retried using EVAL.
func (s *Script) Run(ctx context.Context, c Scripter, keys []string, args ...interface{}) *Cmd {
r := s.EvalSha(ctx, c, keys, args...)
if HasErrorPrefix(r.Err(), "NOSCRIPT") {
if errors.Is(r.Err(), ErrNoScript) {
return s.Eval(ctx, c, keys, args...)
}
return r
@@ -77,7 +78,7 @@ func (s *Script) Run(ctx context.Context, c Scripter, keys []string, args ...int
// it is retried using EVAL_RO.
func (s *Script) RunRO(ctx context.Context, c Scripter, keys []string, args ...interface{}) *Cmd {
r := s.EvalShaRO(ctx, c, keys, args...)
if HasErrorPrefix(r.Err(), "NOSCRIPT") {
if errors.Is(r.Err(), ErrNoScript) {
return s.EvalRO(ctx, c, keys, args...)
}
return r
+5
View File
@@ -60,6 +60,11 @@ func (c cmdable) eval(ctx context.Context, name, payload string, keys []string,
cmd.SetFirstKeyPos(3)
}
_ = c(ctx, cmd)
if err := cmd.Err(); err != nil {
if HasErrorPrefix(err, "NOSCRIPT") {
cmd.SetErr(ErrNoScript)
}
}
return cmd
}