mirror of https://github.com/go-redis/redis.git
Merge pull request #2221 from tisonkun/eval_ro
feat: support eval_ro and evalsha_ro
This commit is contained in:
commit
be25907703
|
@ -65,7 +65,7 @@ func cmdFirstKeyPos(cmd Cmder, info *CommandInfo) int {
|
|||
}
|
||||
|
||||
switch cmd.Name() {
|
||||
case "eval", "evalsha":
|
||||
case "eval", "evalsha", "eval_ro", "evalsha_ro":
|
||||
if cmd.stringArg(2) != "0" {
|
||||
return 3
|
||||
}
|
||||
|
|
31
commands.go
31
commands.go
|
@ -339,6 +339,8 @@ type Cmdable interface {
|
|||
|
||||
Eval(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd
|
||||
EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd
|
||||
EvalRO(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd
|
||||
EvalShaRO(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd
|
||||
ScriptExists(ctx context.Context, hashes ...string) *BoolSliceCmd
|
||||
ScriptFlush(ctx context.Context) *StatusCmd
|
||||
ScriptKill(ctx context.Context) *StatusCmd
|
||||
|
@ -3010,24 +3012,25 @@ func (c cmdable) MemoryUsage(ctx context.Context, key string, samples ...int) *I
|
|||
//------------------------------------------------------------------------------
|
||||
|
||||
func (c cmdable) Eval(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd {
|
||||
cmdArgs := make([]interface{}, 3+len(keys), 3+len(keys)+len(args))
|
||||
cmdArgs[0] = "eval"
|
||||
cmdArgs[1] = script
|
||||
cmdArgs[2] = len(keys)
|
||||
for i, key := range keys {
|
||||
cmdArgs[3+i] = key
|
||||
}
|
||||
cmdArgs = appendArgs(cmdArgs, args)
|
||||
cmd := NewCmd(ctx, cmdArgs...)
|
||||
cmd.SetFirstKeyPos(3)
|
||||
_ = c(ctx, cmd)
|
||||
return cmd
|
||||
return c.eval(ctx, "eval", script, keys, args...)
|
||||
}
|
||||
|
||||
func (c cmdable) EvalRO(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd {
|
||||
return c.eval(ctx, "eval_ro", script, keys, args...)
|
||||
}
|
||||
|
||||
func (c cmdable) EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd {
|
||||
return c.eval(ctx, "evalsha", sha1, keys, args...)
|
||||
}
|
||||
|
||||
func (c cmdable) EvalShaRO(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd {
|
||||
return c.eval(ctx, "evalsha_ro", sha1, keys, args...)
|
||||
}
|
||||
|
||||
func (c cmdable) eval(ctx context.Context, name, payload string, keys []string, args ...interface{}) *Cmd {
|
||||
cmdArgs := make([]interface{}, 3+len(keys), 3+len(keys)+len(args))
|
||||
cmdArgs[0] = "evalsha"
|
||||
cmdArgs[1] = sha1
|
||||
cmdArgs[0] = name
|
||||
cmdArgs[1] = payload
|
||||
cmdArgs[2] = len(keys)
|
||||
for i, key := range keys {
|
||||
cmdArgs[3+i] = key
|
||||
|
|
|
@ -5413,6 +5413,29 @@ var _ = Describe("Commands", func() {
|
|||
})
|
||||
})
|
||||
|
||||
Describe("EvalRO", func() {
|
||||
It("returns keys and values", func() {
|
||||
vals, err := client.EvalRO(
|
||||
ctx,
|
||||
"return {KEYS[1],ARGV[1]}",
|
||||
[]string{"key"},
|
||||
"hello",
|
||||
).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(vals).To(Equal([]interface{}{"key", "hello"}))
|
||||
})
|
||||
|
||||
It("returns all values after an error", func() {
|
||||
vals, err := client.EvalRO(
|
||||
ctx,
|
||||
`return {12, {err="error"}, "abc"}`,
|
||||
nil,
|
||||
).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(vals).To(Equal([]interface{}{int64(12), proto.RedisError("error"), "abc"}))
|
||||
})
|
||||
})
|
||||
|
||||
Describe("SlowLogGet", func() {
|
||||
It("returns slow query result", func() {
|
||||
const key = "slowlog-log-slower-than"
|
||||
|
|
20
script.go
20
script.go
|
@ -11,6 +11,8 @@ import (
|
|||
type Scripter interface {
|
||||
Eval(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd
|
||||
EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd
|
||||
EvalRO(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd
|
||||
EvalShaRO(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd
|
||||
ScriptExists(ctx context.Context, hashes ...string) *BoolSliceCmd
|
||||
ScriptLoad(ctx context.Context, script string) *StringCmd
|
||||
}
|
||||
|
@ -50,10 +52,18 @@ func (s *Script) Eval(ctx context.Context, c Scripter, keys []string, args ...in
|
|||
return c.Eval(ctx, s.src, keys, args...)
|
||||
}
|
||||
|
||||
func (s *Script) EvalRO(ctx context.Context, c Scripter, keys []string, args ...interface{}) *Cmd {
|
||||
return c.EvalRO(ctx, s.src, keys, args...)
|
||||
}
|
||||
|
||||
func (s *Script) EvalSha(ctx context.Context, c Scripter, keys []string, args ...interface{}) *Cmd {
|
||||
return c.EvalSha(ctx, s.hash, keys, args...)
|
||||
}
|
||||
|
||||
func (s *Script) EvalShaRO(ctx context.Context, c Scripter, keys []string, args ...interface{}) *Cmd {
|
||||
return c.EvalShaRO(ctx, s.hash, keys, args...)
|
||||
}
|
||||
|
||||
// Run optimistically uses EVALSHA to run the script. If script does not exist
|
||||
// it is retried using EVAL.
|
||||
func (s *Script) Run(ctx context.Context, c Scripter, keys []string, args ...interface{}) *Cmd {
|
||||
|
@ -63,3 +73,13 @@ func (s *Script) Run(ctx context.Context, c Scripter, keys []string, args ...int
|
|||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// RunRO optimistically uses EVALSHA_RO to run the script. If script does not exist
|
||||
// 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 err := r.Err(); err != nil && strings.HasPrefix(err.Error(), "NOSCRIPT ") {
|
||||
return s.EvalRO(ctx, c, keys, args...)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue