You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

216 lines
6.7 KiB

  1. package redis
  2. import "context"
  3. type ScriptingFunctionsCmdable interface {
  4. Eval(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd
  5. EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd
  6. EvalRO(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd
  7. EvalShaRO(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd
  8. ScriptExists(ctx context.Context, hashes ...string) *BoolSliceCmd
  9. ScriptFlush(ctx context.Context) *StatusCmd
  10. ScriptKill(ctx context.Context) *StatusCmd
  11. ScriptLoad(ctx context.Context, script string) *StringCmd
  12. FunctionLoad(ctx context.Context, code string) *StringCmd
  13. FunctionLoadReplace(ctx context.Context, code string) *StringCmd
  14. FunctionDelete(ctx context.Context, libName string) *StringCmd
  15. FunctionFlush(ctx context.Context) *StringCmd
  16. FunctionKill(ctx context.Context) *StringCmd
  17. FunctionFlushAsync(ctx context.Context) *StringCmd
  18. FunctionList(ctx context.Context, q FunctionListQuery) *FunctionListCmd
  19. FunctionDump(ctx context.Context) *StringCmd
  20. FunctionRestore(ctx context.Context, libDump string) *StringCmd
  21. FunctionStats(ctx context.Context) *FunctionStatsCmd
  22. FCall(ctx context.Context, function string, keys []string, args ...interface{}) *Cmd
  23. FCallRo(ctx context.Context, function string, keys []string, args ...interface{}) *Cmd
  24. FCallRO(ctx context.Context, function string, keys []string, args ...interface{}) *Cmd
  25. }
  26. func (c cmdable) Eval(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd {
  27. return c.eval(ctx, "eval", script, keys, args...)
  28. }
  29. func (c cmdable) EvalRO(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd {
  30. return c.eval(ctx, "eval_ro", script, keys, args...)
  31. }
  32. func (c cmdable) EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd {
  33. return c.eval(ctx, "evalsha", sha1, keys, args...)
  34. }
  35. func (c cmdable) EvalShaRO(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd {
  36. return c.eval(ctx, "evalsha_ro", sha1, keys, args...)
  37. }
  38. func (c cmdable) eval(ctx context.Context, name, payload string, keys []string, args ...interface{}) *Cmd {
  39. cmdArgs := make([]interface{}, 3+len(keys), 3+len(keys)+len(args))
  40. cmdArgs[0] = name
  41. cmdArgs[1] = payload
  42. cmdArgs[2] = len(keys)
  43. for i, key := range keys {
  44. cmdArgs[3+i] = key
  45. }
  46. cmdArgs = appendArgs(cmdArgs, args)
  47. cmd := NewCmd(ctx, cmdArgs...)
  48. // it is possible that only args exist without a key.
  49. // rdb.eval(ctx, eval, script, nil, arg1, arg2)
  50. if len(keys) > 0 {
  51. cmd.SetFirstKeyPos(3)
  52. }
  53. _ = c(ctx, cmd)
  54. return cmd
  55. }
  56. func (c cmdable) ScriptExists(ctx context.Context, hashes ...string) *BoolSliceCmd {
  57. args := make([]interface{}, 2+len(hashes))
  58. args[0] = "script"
  59. args[1] = "exists"
  60. for i, hash := range hashes {
  61. args[2+i] = hash
  62. }
  63. cmd := NewBoolSliceCmd(ctx, args...)
  64. _ = c(ctx, cmd)
  65. return cmd
  66. }
  67. func (c cmdable) ScriptFlush(ctx context.Context) *StatusCmd {
  68. cmd := NewStatusCmd(ctx, "script", "flush")
  69. _ = c(ctx, cmd)
  70. return cmd
  71. }
  72. func (c cmdable) ScriptKill(ctx context.Context) *StatusCmd {
  73. cmd := NewStatusCmd(ctx, "script", "kill")
  74. _ = c(ctx, cmd)
  75. return cmd
  76. }
  77. func (c cmdable) ScriptLoad(ctx context.Context, script string) *StringCmd {
  78. cmd := NewStringCmd(ctx, "script", "load", script)
  79. _ = c(ctx, cmd)
  80. return cmd
  81. }
  82. // ------------------------------------------------------------------------------
  83. // FunctionListQuery is used with FunctionList to query for Redis libraries
  84. //
  85. // LibraryNamePattern - Use an empty string to get all libraries.
  86. // - Use a glob-style pattern to match multiple libraries with a matching name
  87. // - Use a library's full name to match a single library
  88. // WithCode - If true, it will return the code of the library
  89. type FunctionListQuery struct {
  90. LibraryNamePattern string
  91. WithCode bool
  92. }
  93. func (c cmdable) FunctionLoad(ctx context.Context, code string) *StringCmd {
  94. cmd := NewStringCmd(ctx, "function", "load", code)
  95. _ = c(ctx, cmd)
  96. return cmd
  97. }
  98. func (c cmdable) FunctionLoadReplace(ctx context.Context, code string) *StringCmd {
  99. cmd := NewStringCmd(ctx, "function", "load", "replace", code)
  100. _ = c(ctx, cmd)
  101. return cmd
  102. }
  103. func (c cmdable) FunctionDelete(ctx context.Context, libName string) *StringCmd {
  104. cmd := NewStringCmd(ctx, "function", "delete", libName)
  105. _ = c(ctx, cmd)
  106. return cmd
  107. }
  108. func (c cmdable) FunctionFlush(ctx context.Context) *StringCmd {
  109. cmd := NewStringCmd(ctx, "function", "flush")
  110. _ = c(ctx, cmd)
  111. return cmd
  112. }
  113. func (c cmdable) FunctionKill(ctx context.Context) *StringCmd {
  114. cmd := NewStringCmd(ctx, "function", "kill")
  115. _ = c(ctx, cmd)
  116. return cmd
  117. }
  118. func (c cmdable) FunctionFlushAsync(ctx context.Context) *StringCmd {
  119. cmd := NewStringCmd(ctx, "function", "flush", "async")
  120. _ = c(ctx, cmd)
  121. return cmd
  122. }
  123. func (c cmdable) FunctionList(ctx context.Context, q FunctionListQuery) *FunctionListCmd {
  124. args := make([]interface{}, 2, 5)
  125. args[0] = "function"
  126. args[1] = "list"
  127. if q.LibraryNamePattern != "" {
  128. args = append(args, "libraryname", q.LibraryNamePattern)
  129. }
  130. if q.WithCode {
  131. args = append(args, "withcode")
  132. }
  133. cmd := NewFunctionListCmd(ctx, args...)
  134. _ = c(ctx, cmd)
  135. return cmd
  136. }
  137. func (c cmdable) FunctionDump(ctx context.Context) *StringCmd {
  138. cmd := NewStringCmd(ctx, "function", "dump")
  139. _ = c(ctx, cmd)
  140. return cmd
  141. }
  142. func (c cmdable) FunctionRestore(ctx context.Context, libDump string) *StringCmd {
  143. cmd := NewStringCmd(ctx, "function", "restore", libDump)
  144. _ = c(ctx, cmd)
  145. return cmd
  146. }
  147. func (c cmdable) FunctionStats(ctx context.Context) *FunctionStatsCmd {
  148. cmd := NewFunctionStatsCmd(ctx, "function", "stats")
  149. _ = c(ctx, cmd)
  150. return cmd
  151. }
  152. func (c cmdable) FCall(ctx context.Context, function string, keys []string, args ...interface{}) *Cmd {
  153. cmdArgs := fcallArgs("fcall", function, keys, args...)
  154. cmd := NewCmd(ctx, cmdArgs...)
  155. if len(keys) > 0 {
  156. cmd.SetFirstKeyPos(3)
  157. }
  158. _ = c(ctx, cmd)
  159. return cmd
  160. }
  161. // FCallRo this function simply calls FCallRO,
  162. // Deprecated: to maintain convention FCallRO.
  163. func (c cmdable) FCallRo(ctx context.Context, function string, keys []string, args ...interface{}) *Cmd {
  164. return c.FCallRO(ctx, function, keys, args...)
  165. }
  166. func (c cmdable) FCallRO(ctx context.Context, function string, keys []string, args ...interface{}) *Cmd {
  167. cmdArgs := fcallArgs("fcall_ro", function, keys, args...)
  168. cmd := NewCmd(ctx, cmdArgs...)
  169. if len(keys) > 0 {
  170. cmd.SetFirstKeyPos(3)
  171. }
  172. _ = c(ctx, cmd)
  173. return cmd
  174. }
  175. func fcallArgs(command string, function string, keys []string, args ...interface{}) []interface{} {
  176. cmdArgs := make([]interface{}, 3+len(keys), 3+len(keys)+len(args))
  177. cmdArgs[0] = command
  178. cmdArgs[1] = function
  179. cmdArgs[2] = len(keys)
  180. for i, key := range keys {
  181. cmdArgs[3+i] = key
  182. }
  183. cmdArgs = append(cmdArgs, args...)
  184. return cmdArgs
  185. }