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() {
|
switch cmd.Name() {
|
||||||
case "eval", "evalsha":
|
case "eval", "evalsha", "eval_ro", "evalsha_ro":
|
||||||
if cmd.stringArg(2) != "0" {
|
if cmd.stringArg(2) != "0" {
|
||||||
return 3
|
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
|
Eval(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd
|
||||||
EvalSha(ctx context.Context, sha1 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
|
ScriptExists(ctx context.Context, hashes ...string) *BoolSliceCmd
|
||||||
ScriptFlush(ctx context.Context) *StatusCmd
|
ScriptFlush(ctx context.Context) *StatusCmd
|
||||||
ScriptKill(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 {
|
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))
|
return c.eval(ctx, "eval", script, keys, args...)
|
||||||
cmdArgs[0] = "eval"
|
}
|
||||||
cmdArgs[1] = script
|
|
||||||
cmdArgs[2] = len(keys)
|
func (c cmdable) EvalRO(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd {
|
||||||
for i, key := range keys {
|
return c.eval(ctx, "eval_ro", script, keys, args...)
|
||||||
cmdArgs[3+i] = key
|
|
||||||
}
|
|
||||||
cmdArgs = appendArgs(cmdArgs, args)
|
|
||||||
cmd := NewCmd(ctx, cmdArgs...)
|
|
||||||
cmd.SetFirstKeyPos(3)
|
|
||||||
_ = c(ctx, cmd)
|
|
||||||
return cmd
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c cmdable) EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd {
|
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 := make([]interface{}, 3+len(keys), 3+len(keys)+len(args))
|
||||||
cmdArgs[0] = "evalsha"
|
cmdArgs[0] = name
|
||||||
cmdArgs[1] = sha1
|
cmdArgs[1] = payload
|
||||||
cmdArgs[2] = len(keys)
|
cmdArgs[2] = len(keys)
|
||||||
for i, key := range keys {
|
for i, key := range keys {
|
||||||
cmdArgs[3+i] = key
|
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() {
|
Describe("SlowLogGet", func() {
|
||||||
It("returns slow query result", func() {
|
It("returns slow query result", func() {
|
||||||
const key = "slowlog-log-slower-than"
|
const key = "slowlog-log-slower-than"
|
||||||
|
|
20
script.go
20
script.go
|
@ -11,6 +11,8 @@ import (
|
||||||
type Scripter interface {
|
type Scripter interface {
|
||||||
Eval(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd
|
Eval(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd
|
||||||
EvalSha(ctx context.Context, sha1 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
|
ScriptExists(ctx context.Context, hashes ...string) *BoolSliceCmd
|
||||||
ScriptLoad(ctx context.Context, script string) *StringCmd
|
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...)
|
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 {
|
func (s *Script) EvalSha(ctx context.Context, c Scripter, keys []string, args ...interface{}) *Cmd {
|
||||||
return c.EvalSha(ctx, s.hash, keys, args...)
|
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
|
// Run optimistically uses EVALSHA to run the script. If script does not exist
|
||||||
// it is retried using EVAL.
|
// it is retried using EVAL.
|
||||||
func (s *Script) Run(ctx context.Context, c Scripter, keys []string, args ...interface{}) *Cmd {
|
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
|
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