script.go 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. package redis
  2. import (
  3. "crypto/sha1"
  4. "encoding/hex"
  5. "io"
  6. "strings"
  7. )
  8. type scripter interface {
  9. Eval(script string, keys []string, args ...interface{}) *Cmd
  10. EvalSha(sha1 string, keys []string, args ...interface{}) *Cmd
  11. ScriptExists(hashes ...string) *BoolSliceCmd
  12. ScriptLoad(script string) *StringCmd
  13. }
  14. var _ scripter = (*Client)(nil)
  15. var _ scripter = (*Ring)(nil)
  16. var _ scripter = (*ClusterClient)(nil)
  17. type Script struct {
  18. src, hash string
  19. }
  20. func NewScript(src string) *Script {
  21. h := sha1.New()
  22. io.WriteString(h, src)
  23. return &Script{
  24. src: src,
  25. hash: hex.EncodeToString(h.Sum(nil)),
  26. }
  27. }
  28. func (s *Script) Hash() string {
  29. return s.hash
  30. }
  31. func (s *Script) Load(c scripter) *StringCmd {
  32. return c.ScriptLoad(s.src)
  33. }
  34. func (s *Script) Exists(c scripter) *BoolSliceCmd {
  35. return c.ScriptExists(s.hash)
  36. }
  37. func (s *Script) Eval(c scripter, keys []string, args ...interface{}) *Cmd {
  38. return c.Eval(s.src, keys, args...)
  39. }
  40. func (s *Script) EvalSha(c scripter, keys []string, args ...interface{}) *Cmd {
  41. return c.EvalSha(s.hash, keys, args...)
  42. }
  43. // Run optimistically uses EVALSHA to run the script. If script does not exist
  44. // it is retried using EVAL.
  45. func (s *Script) Run(c scripter, keys []string, args ...interface{}) *Cmd {
  46. r := s.EvalSha(c, keys, args...)
  47. if err := r.Err(); err != nil && strings.HasPrefix(err.Error(), "NOSCRIPT ") {
  48. return s.Eval(c, keys, args...)
  49. }
  50. return r
  51. }