Skip to content

Commit be25907

Browse files
authored
Merge pull request #2221 from tisonkun/eval_ro
feat: support eval_ro and evalsha_ro
2 parents 4dcf3cc + d56af1f commit be25907

File tree

4 files changed

+61
-15
lines changed

4 files changed

+61
-15
lines changed

command.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ func cmdFirstKeyPos(cmd Cmder, info *CommandInfo) int {
6565
}
6666

6767
switch cmd.Name() {
68-
case "eval", "evalsha":
68+
case "eval", "evalsha", "eval_ro", "evalsha_ro":
6969
if cmd.stringArg(2) != "0" {
7070
return 3
7171
}

commands.go

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,8 @@ type Cmdable interface {
339339

340340
Eval(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd
341341
EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd
342+
EvalRO(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd
343+
EvalShaRO(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd
342344
ScriptExists(ctx context.Context, hashes ...string) *BoolSliceCmd
343345
ScriptFlush(ctx context.Context) *StatusCmd
344346
ScriptKill(ctx context.Context) *StatusCmd
@@ -3010,24 +3012,25 @@ func (c cmdable) MemoryUsage(ctx context.Context, key string, samples ...int) *I
30103012
//------------------------------------------------------------------------------
30113013

30123014
func (c cmdable) Eval(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd {
3013-
cmdArgs := make([]interface{}, 3+len(keys), 3+len(keys)+len(args))
3014-
cmdArgs[0] = "eval"
3015-
cmdArgs[1] = script
3016-
cmdArgs[2] = len(keys)
3017-
for i, key := range keys {
3018-
cmdArgs[3+i] = key
3019-
}
3020-
cmdArgs = appendArgs(cmdArgs, args)
3021-
cmd := NewCmd(ctx, cmdArgs...)
3022-
cmd.SetFirstKeyPos(3)
3023-
_ = c(ctx, cmd)
3024-
return cmd
3015+
return c.eval(ctx, "eval", script, keys, args...)
3016+
}
3017+
3018+
func (c cmdable) EvalRO(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd {
3019+
return c.eval(ctx, "eval_ro", script, keys, args...)
30253020
}
30263021

30273022
func (c cmdable) EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd {
3023+
return c.eval(ctx, "evalsha", sha1, keys, args...)
3024+
}
3025+
3026+
func (c cmdable) EvalShaRO(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd {
3027+
return c.eval(ctx, "evalsha_ro", sha1, keys, args...)
3028+
}
3029+
3030+
func (c cmdable) eval(ctx context.Context, name, payload string, keys []string, args ...interface{}) *Cmd {
30283031
cmdArgs := make([]interface{}, 3+len(keys), 3+len(keys)+len(args))
3029-
cmdArgs[0] = "evalsha"
3030-
cmdArgs[1] = sha1
3032+
cmdArgs[0] = name
3033+
cmdArgs[1] = payload
30313034
cmdArgs[2] = len(keys)
30323035
for i, key := range keys {
30333036
cmdArgs[3+i] = key

commands_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5413,6 +5413,29 @@ var _ = Describe("Commands", func() {
54135413
})
54145414
})
54155415

5416+
Describe("EvalRO", func() {
5417+
It("returns keys and values", func() {
5418+
vals, err := client.EvalRO(
5419+
ctx,
5420+
"return {KEYS[1],ARGV[1]}",
5421+
[]string{"key"},
5422+
"hello",
5423+
).Result()
5424+
Expect(err).NotTo(HaveOccurred())
5425+
Expect(vals).To(Equal([]interface{}{"key", "hello"}))
5426+
})
5427+
5428+
It("returns all values after an error", func() {
5429+
vals, err := client.EvalRO(
5430+
ctx,
5431+
`return {12, {err="error"}, "abc"}`,
5432+
nil,
5433+
).Result()
5434+
Expect(err).NotTo(HaveOccurred())
5435+
Expect(vals).To(Equal([]interface{}{int64(12), proto.RedisError("error"), "abc"}))
5436+
})
5437+
})
5438+
54165439
Describe("SlowLogGet", func() {
54175440
It("returns slow query result", func() {
54185441
const key = "slowlog-log-slower-than"

script.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111
type Scripter interface {
1212
Eval(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd
1313
EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd
14+
EvalRO(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd
15+
EvalShaRO(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd
1416
ScriptExists(ctx context.Context, hashes ...string) *BoolSliceCmd
1517
ScriptLoad(ctx context.Context, script string) *StringCmd
1618
}
@@ -50,10 +52,18 @@ func (s *Script) Eval(ctx context.Context, c Scripter, keys []string, args ...in
5052
return c.Eval(ctx, s.src, keys, args...)
5153
}
5254

55+
func (s *Script) EvalRO(ctx context.Context, c Scripter, keys []string, args ...interface{}) *Cmd {
56+
return c.EvalRO(ctx, s.src, keys, args...)
57+
}
58+
5359
func (s *Script) EvalSha(ctx context.Context, c Scripter, keys []string, args ...interface{}) *Cmd {
5460
return c.EvalSha(ctx, s.hash, keys, args...)
5561
}
5662

63+
func (s *Script) EvalShaRO(ctx context.Context, c Scripter, keys []string, args ...interface{}) *Cmd {
64+
return c.EvalShaRO(ctx, s.hash, keys, args...)
65+
}
66+
5767
// Run optimistically uses EVALSHA to run the script. If script does not exist
5868
// it is retried using EVAL.
5969
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
6373
}
6474
return r
6575
}
76+
77+
// RunRO optimistically uses EVALSHA_RO to run the script. If script does not exist
78+
// it is retried using EVAL_RO.
79+
func (s *Script) RunRO(ctx context.Context, c Scripter, keys []string, args ...interface{}) *Cmd {
80+
r := s.EvalShaRO(ctx, c, keys, args...)
81+
if err := r.Err(); err != nil && strings.HasPrefix(err.Error(), "NOSCRIPT ") {
82+
return s.EvalRO(ctx, c, keys, args...)
83+
}
84+
return r
85+
}

0 commit comments

Comments
 (0)