From 2e8280dc18e37df395332935c75af9a8ebc692a6 Mon Sep 17 00:00:00 2001 From: Simao Mata Date: Mon, 22 May 2023 14:54:05 +0100 Subject: [PATCH] Add RunLoad to script Add new `RunLoad` method to Script. It tries to run the script using `EvalSha`, if that fails, it loads the script using SCRIPTLOAD and then tries again. This is what the redis manual recommends libraries to do: From https://redis.io/docs/manual/programmability/eval-intro/ > In this case, the application should first load it with SCRIPT LOAD > and then call EVALSHA once more to run the cached script by its SHA1 > sum. Most of Redis' clients already provide utility APIs for doing > that automatically. Please consult your client's documentation > regarding the specific details --- script.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/script.go b/script.go index 626ab03bb..0a36d8b0e 100644 --- a/script.go +++ b/script.go @@ -63,6 +63,21 @@ func (s *Script) EvalShaRO(ctx context.Context, c Scripter, keys []string, args return c.EvalShaRO(ctx, s.hash, keys, args...) } +// Optimistically uses EVALSHA to run the script. Load the script if it doesn't exist +func (s *Script) RunLoad(ctx context.Context, c Scripter, keys []string, args ...interface{}) (*Cmd, error) { + r := s.EvalSha(ctx, c, keys, args...) + + if err := r.Err(); err != nil && HasErrorPrefix(r.Err(), "NOSCRIPT") { + if err := s.Load(ctx, c).Err(); err != nil { + return nil, err + } + + return s.EvalSha(ctx, c, keys, args...), nil + } + + return r, nil +} + // 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 {