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.

3430 lines
99 KiB

  1. package redis
  2. import (
  3. "context"
  4. "errors"
  5. "io"
  6. "time"
  7. "github.com/go-redis/redis/v8/internal"
  8. )
  9. // KeepTTL is a Redis KEEPTTL option to keep existing TTL, it requires your redis-server version >= 6.0,
  10. // otherwise you will receive an error: (error) ERR syntax error.
  11. // For example:
  12. //
  13. // rdb.Set(ctx, key, value, redis.KeepTTL)
  14. const KeepTTL = -1
  15. func usePrecise(dur time.Duration) bool {
  16. return dur < time.Second || dur%time.Second != 0
  17. }
  18. func formatMs(ctx context.Context, dur time.Duration) int64 {
  19. if dur > 0 && dur < time.Millisecond {
  20. internal.Logger.Printf(
  21. ctx,
  22. "specified duration is %s, but minimal supported value is %s - truncating to 1ms",
  23. dur, time.Millisecond,
  24. )
  25. return 1
  26. }
  27. return int64(dur / time.Millisecond)
  28. }
  29. func formatSec(ctx context.Context, dur time.Duration) int64 {
  30. if dur > 0 && dur < time.Second {
  31. internal.Logger.Printf(
  32. ctx,
  33. "specified duration is %s, but minimal supported value is %s - truncating to 1s",
  34. dur, time.Second,
  35. )
  36. return 1
  37. }
  38. return int64(dur / time.Second)
  39. }
  40. func appendArgs(dst, src []interface{}) []interface{} {
  41. if len(src) == 1 {
  42. return appendArg(dst, src[0])
  43. }
  44. dst = append(dst, src...)
  45. return dst
  46. }
  47. func appendArg(dst []interface{}, arg interface{}) []interface{} {
  48. switch arg := arg.(type) {
  49. case []string:
  50. for _, s := range arg {
  51. dst = append(dst, s)
  52. }
  53. return dst
  54. case []interface{}:
  55. dst = append(dst, arg...)
  56. return dst
  57. case map[string]interface{}:
  58. for k, v := range arg {
  59. dst = append(dst, k, v)
  60. }
  61. return dst
  62. case map[string]string:
  63. for k, v := range arg {
  64. dst = append(dst, k, v)
  65. }
  66. return dst
  67. default:
  68. return append(dst, arg)
  69. }
  70. }
  71. type Cmdable interface {
  72. Pipeline() Pipeliner
  73. Pipelined(ctx context.Context, fn func(Pipeliner) error) ([]Cmder, error)
  74. TxPipelined(ctx context.Context, fn func(Pipeliner) error) ([]Cmder, error)
  75. TxPipeline() Pipeliner
  76. Command(ctx context.Context) *CommandsInfoCmd
  77. ClientGetName(ctx context.Context) *StringCmd
  78. Echo(ctx context.Context, message interface{}) *StringCmd
  79. Ping(ctx context.Context) *StatusCmd
  80. Quit(ctx context.Context) *StatusCmd
  81. Del(ctx context.Context, keys ...string) *IntCmd
  82. Unlink(ctx context.Context, keys ...string) *IntCmd
  83. Dump(ctx context.Context, key string) *StringCmd
  84. Exists(ctx context.Context, keys ...string) *IntCmd
  85. Expire(ctx context.Context, key string, expiration time.Duration) *BoolCmd
  86. ExpireAt(ctx context.Context, key string, tm time.Time) *BoolCmd
  87. Keys(ctx context.Context, pattern string) *StringSliceCmd
  88. Migrate(ctx context.Context, host, port, key string, db int, timeout time.Duration) *StatusCmd
  89. Move(ctx context.Context, key string, db int) *BoolCmd
  90. ObjectRefCount(ctx context.Context, key string) *IntCmd
  91. ObjectEncoding(ctx context.Context, key string) *StringCmd
  92. ObjectIdleTime(ctx context.Context, key string) *DurationCmd
  93. Persist(ctx context.Context, key string) *BoolCmd
  94. PExpire(ctx context.Context, key string, expiration time.Duration) *BoolCmd
  95. PExpireAt(ctx context.Context, key string, tm time.Time) *BoolCmd
  96. PTTL(ctx context.Context, key string) *DurationCmd
  97. RandomKey(ctx context.Context) *StringCmd
  98. Rename(ctx context.Context, key, newkey string) *StatusCmd
  99. RenameNX(ctx context.Context, key, newkey string) *BoolCmd
  100. Restore(ctx context.Context, key string, ttl time.Duration, value string) *StatusCmd
  101. RestoreReplace(ctx context.Context, key string, ttl time.Duration, value string) *StatusCmd
  102. Sort(ctx context.Context, key string, sort *Sort) *StringSliceCmd
  103. SortStore(ctx context.Context, key, store string, sort *Sort) *IntCmd
  104. SortInterfaces(ctx context.Context, key string, sort *Sort) *SliceCmd
  105. Touch(ctx context.Context, keys ...string) *IntCmd
  106. TTL(ctx context.Context, key string) *DurationCmd
  107. Type(ctx context.Context, key string) *StatusCmd
  108. Append(ctx context.Context, key, value string) *IntCmd
  109. Decr(ctx context.Context, key string) *IntCmd
  110. DecrBy(ctx context.Context, key string, decrement int64) *IntCmd
  111. Get(ctx context.Context, key string) *StringCmd
  112. GetRange(ctx context.Context, key string, start, end int64) *StringCmd
  113. GetSet(ctx context.Context, key string, value interface{}) *StringCmd
  114. GetEx(ctx context.Context, key string, expiration time.Duration) *StringCmd
  115. GetDel(ctx context.Context, key string) *StringCmd
  116. Incr(ctx context.Context, key string) *IntCmd
  117. IncrBy(ctx context.Context, key string, value int64) *IntCmd
  118. IncrByFloat(ctx context.Context, key string, value float64) *FloatCmd
  119. MGet(ctx context.Context, keys ...string) *SliceCmd
  120. MSet(ctx context.Context, values ...interface{}) *StatusCmd
  121. MSetNX(ctx context.Context, values ...interface{}) *BoolCmd
  122. Set(ctx context.Context, key string, value interface{}, expiration time.Duration) *StatusCmd
  123. SetArgs(ctx context.Context, key string, value interface{}, a SetArgs) *StatusCmd
  124. // TODO: rename to SetEx
  125. SetEX(ctx context.Context, key string, value interface{}, expiration time.Duration) *StatusCmd
  126. SetNX(ctx context.Context, key string, value interface{}, expiration time.Duration) *BoolCmd
  127. SetXX(ctx context.Context, key string, value interface{}, expiration time.Duration) *BoolCmd
  128. SetRange(ctx context.Context, key string, offset int64, value string) *IntCmd
  129. StrLen(ctx context.Context, key string) *IntCmd
  130. GetBit(ctx context.Context, key string, offset int64) *IntCmd
  131. SetBit(ctx context.Context, key string, offset int64, value int) *IntCmd
  132. BitCount(ctx context.Context, key string, bitCount *BitCount) *IntCmd
  133. BitOpAnd(ctx context.Context, destKey string, keys ...string) *IntCmd
  134. BitOpOr(ctx context.Context, destKey string, keys ...string) *IntCmd
  135. BitOpXor(ctx context.Context, destKey string, keys ...string) *IntCmd
  136. BitOpNot(ctx context.Context, destKey string, key string) *IntCmd
  137. BitPos(ctx context.Context, key string, bit int64, pos ...int64) *IntCmd
  138. BitField(ctx context.Context, key string, args ...interface{}) *IntSliceCmd
  139. Scan(ctx context.Context, cursor uint64, match string, count int64) *ScanCmd
  140. ScanType(ctx context.Context, cursor uint64, match string, count int64, keyType string) *ScanCmd
  141. SScan(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd
  142. HScan(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd
  143. ZScan(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd
  144. HDel(ctx context.Context, key string, fields ...string) *IntCmd
  145. HExists(ctx context.Context, key, field string) *BoolCmd
  146. HGet(ctx context.Context, key, field string) *StringCmd
  147. HGetAll(ctx context.Context, key string) *StringStringMapCmd
  148. HIncrBy(ctx context.Context, key, field string, incr int64) *IntCmd
  149. HIncrByFloat(ctx context.Context, key, field string, incr float64) *FloatCmd
  150. HKeys(ctx context.Context, key string) *StringSliceCmd
  151. HLen(ctx context.Context, key string) *IntCmd
  152. HMGet(ctx context.Context, key string, fields ...string) *SliceCmd
  153. HSet(ctx context.Context, key string, values ...interface{}) *IntCmd
  154. HMSet(ctx context.Context, key string, values ...interface{}) *BoolCmd
  155. HSetNX(ctx context.Context, key, field string, value interface{}) *BoolCmd
  156. HVals(ctx context.Context, key string) *StringSliceCmd
  157. HRandField(ctx context.Context, key string, count int, withValues bool) *StringSliceCmd
  158. BLPop(ctx context.Context, timeout time.Duration, keys ...string) *StringSliceCmd
  159. BRPop(ctx context.Context, timeout time.Duration, keys ...string) *StringSliceCmd
  160. BRPopLPush(ctx context.Context, source, destination string, timeout time.Duration) *StringCmd
  161. LIndex(ctx context.Context, key string, index int64) *StringCmd
  162. LInsert(ctx context.Context, key, op string, pivot, value interface{}) *IntCmd
  163. LInsertBefore(ctx context.Context, key string, pivot, value interface{}) *IntCmd
  164. LInsertAfter(ctx context.Context, key string, pivot, value interface{}) *IntCmd
  165. LLen(ctx context.Context, key string) *IntCmd
  166. LPop(ctx context.Context, key string) *StringCmd
  167. LPopCount(ctx context.Context, key string, count int) *StringSliceCmd
  168. LPos(ctx context.Context, key string, value string, args LPosArgs) *IntCmd
  169. LPosCount(ctx context.Context, key string, value string, count int64, args LPosArgs) *IntSliceCmd
  170. LPush(ctx context.Context, key string, values ...interface{}) *IntCmd
  171. LPushX(ctx context.Context, key string, values ...interface{}) *IntCmd
  172. LRange(ctx context.Context, key string, start, stop int64) *StringSliceCmd
  173. LRem(ctx context.Context, key string, count int64, value interface{}) *IntCmd
  174. LSet(ctx context.Context, key string, index int64, value interface{}) *StatusCmd
  175. LTrim(ctx context.Context, key string, start, stop int64) *StatusCmd
  176. RPop(ctx context.Context, key string) *StringCmd
  177. RPopCount(ctx context.Context, key string, count int) *StringSliceCmd
  178. RPopLPush(ctx context.Context, source, destination string) *StringCmd
  179. RPush(ctx context.Context, key string, values ...interface{}) *IntCmd
  180. RPushX(ctx context.Context, key string, values ...interface{}) *IntCmd
  181. LMove(ctx context.Context, source, destination, srcpos, destpos string) *StringCmd
  182. BLMove(ctx context.Context, source, destination, srcpos, destpos string, timeout time.Duration) *StringCmd
  183. SAdd(ctx context.Context, key string, members ...interface{}) *IntCmd
  184. SCard(ctx context.Context, key string) *IntCmd
  185. SDiff(ctx context.Context, keys ...string) *StringSliceCmd
  186. SDiffStore(ctx context.Context, destination string, keys ...string) *IntCmd
  187. SInter(ctx context.Context, keys ...string) *StringSliceCmd
  188. SInterStore(ctx context.Context, destination string, keys ...string) *IntCmd
  189. SIsMember(ctx context.Context, key string, member interface{}) *BoolCmd
  190. SMIsMember(ctx context.Context, key string, members ...interface{}) *BoolSliceCmd
  191. SMembers(ctx context.Context, key string) *StringSliceCmd
  192. SMembersMap(ctx context.Context, key string) *StringStructMapCmd
  193. SMove(ctx context.Context, source, destination string, member interface{}) *BoolCmd
  194. SPop(ctx context.Context, key string) *StringCmd
  195. SPopN(ctx context.Context, key string, count int64) *StringSliceCmd
  196. SRandMember(ctx context.Context, key string) *StringCmd
  197. SRandMemberN(ctx context.Context, key string, count int64) *StringSliceCmd
  198. SRem(ctx context.Context, key string, members ...interface{}) *IntCmd
  199. SUnion(ctx context.Context, keys ...string) *StringSliceCmd
  200. SUnionStore(ctx context.Context, destination string, keys ...string) *IntCmd
  201. XAdd(ctx context.Context, a *XAddArgs) *StringCmd
  202. XDel(ctx context.Context, stream string, ids ...string) *IntCmd
  203. XLen(ctx context.Context, stream string) *IntCmd
  204. XRange(ctx context.Context, stream, start, stop string) *XMessageSliceCmd
  205. XRangeN(ctx context.Context, stream, start, stop string, count int64) *XMessageSliceCmd
  206. XRevRange(ctx context.Context, stream string, start, stop string) *XMessageSliceCmd
  207. XRevRangeN(ctx context.Context, stream string, start, stop string, count int64) *XMessageSliceCmd
  208. XRead(ctx context.Context, a *XReadArgs) *XStreamSliceCmd
  209. XReadStreams(ctx context.Context, streams ...string) *XStreamSliceCmd
  210. XGroupCreate(ctx context.Context, stream, group, start string) *StatusCmd
  211. XGroupCreateMkStream(ctx context.Context, stream, group, start string) *StatusCmd
  212. XGroupSetID(ctx context.Context, stream, group, start string) *StatusCmd
  213. XGroupDestroy(ctx context.Context, stream, group string) *IntCmd
  214. XGroupCreateConsumer(ctx context.Context, stream, group, consumer string) *IntCmd
  215. XGroupDelConsumer(ctx context.Context, stream, group, consumer string) *IntCmd
  216. XReadGroup(ctx context.Context, a *XReadGroupArgs) *XStreamSliceCmd
  217. XAck(ctx context.Context, stream, group string, ids ...string) *IntCmd
  218. XPending(ctx context.Context, stream, group string) *XPendingCmd
  219. XPendingExt(ctx context.Context, a *XPendingExtArgs) *XPendingExtCmd
  220. XClaim(ctx context.Context, a *XClaimArgs) *XMessageSliceCmd
  221. XClaimJustID(ctx context.Context, a *XClaimArgs) *StringSliceCmd
  222. XAutoClaim(ctx context.Context, a *XAutoClaimArgs) *XAutoClaimCmd
  223. XAutoClaimJustID(ctx context.Context, a *XAutoClaimArgs) *XAutoClaimJustIDCmd
  224. // TODO: XTrim and XTrimApprox remove in v9.
  225. XTrim(ctx context.Context, key string, maxLen int64) *IntCmd
  226. XTrimApprox(ctx context.Context, key string, maxLen int64) *IntCmd
  227. XTrimMaxLen(ctx context.Context, key string, maxLen int64) *IntCmd
  228. XTrimMaxLenApprox(ctx context.Context, key string, maxLen, limit int64) *IntCmd
  229. XTrimMinID(ctx context.Context, key string, minID string) *IntCmd
  230. XTrimMinIDApprox(ctx context.Context, key string, minID string, limit int64) *IntCmd
  231. XInfoGroups(ctx context.Context, key string) *XInfoGroupsCmd
  232. XInfoStream(ctx context.Context, key string) *XInfoStreamCmd
  233. XInfoStreamFull(ctx context.Context, key string, count int) *XInfoStreamFullCmd
  234. XInfoConsumers(ctx context.Context, key string, group string) *XInfoConsumersCmd
  235. BZPopMax(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd
  236. BZPopMin(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd
  237. // TODO: remove
  238. // ZAddCh
  239. // ZIncr
  240. // ZAddNXCh
  241. // ZAddXXCh
  242. // ZIncrNX
  243. // ZIncrXX
  244. // in v9.
  245. // use ZAddArgs and ZAddArgsIncr.
  246. ZAdd(ctx context.Context, key string, members ...*Z) *IntCmd
  247. ZAddNX(ctx context.Context, key string, members ...*Z) *IntCmd
  248. ZAddXX(ctx context.Context, key string, members ...*Z) *IntCmd
  249. ZAddCh(ctx context.Context, key string, members ...*Z) *IntCmd
  250. ZAddNXCh(ctx context.Context, key string, members ...*Z) *IntCmd
  251. ZAddXXCh(ctx context.Context, key string, members ...*Z) *IntCmd
  252. ZAddArgs(ctx context.Context, key string, args ZAddArgs) *IntCmd
  253. ZAddArgsIncr(ctx context.Context, key string, args ZAddArgs) *FloatCmd
  254. ZIncr(ctx context.Context, key string, member *Z) *FloatCmd
  255. ZIncrNX(ctx context.Context, key string, member *Z) *FloatCmd
  256. ZIncrXX(ctx context.Context, key string, member *Z) *FloatCmd
  257. ZCard(ctx context.Context, key string) *IntCmd
  258. ZCount(ctx context.Context, key, min, max string) *IntCmd
  259. ZLexCount(ctx context.Context, key, min, max string) *IntCmd
  260. ZIncrBy(ctx context.Context, key string, increment float64, member string) *FloatCmd
  261. ZInter(ctx context.Context, store *ZStore) *StringSliceCmd
  262. ZInterWithScores(ctx context.Context, store *ZStore) *ZSliceCmd
  263. ZInterStore(ctx context.Context, destination string, store *ZStore) *IntCmd
  264. ZMScore(ctx context.Context, key string, members ...string) *FloatSliceCmd
  265. ZPopMax(ctx context.Context, key string, count ...int64) *ZSliceCmd
  266. ZPopMin(ctx context.Context, key string, count ...int64) *ZSliceCmd
  267. ZRange(ctx context.Context, key string, start, stop int64) *StringSliceCmd
  268. ZRangeWithScores(ctx context.Context, key string, start, stop int64) *ZSliceCmd
  269. ZRangeByScore(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd
  270. ZRangeByLex(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd
  271. ZRangeByScoreWithScores(ctx context.Context, key string, opt *ZRangeBy) *ZSliceCmd
  272. ZRangeArgs(ctx context.Context, z ZRangeArgs) *StringSliceCmd
  273. ZRangeArgsWithScores(ctx context.Context, z ZRangeArgs) *ZSliceCmd
  274. ZRangeStore(ctx context.Context, dst string, z ZRangeArgs) *IntCmd
  275. ZRank(ctx context.Context, key, member string) *IntCmd
  276. ZRem(ctx context.Context, key string, members ...interface{}) *IntCmd
  277. ZRemRangeByRank(ctx context.Context, key string, start, stop int64) *IntCmd
  278. ZRemRangeByScore(ctx context.Context, key, min, max string) *IntCmd
  279. ZRemRangeByLex(ctx context.Context, key, min, max string) *IntCmd
  280. ZRevRange(ctx context.Context, key string, start, stop int64) *StringSliceCmd
  281. ZRevRangeWithScores(ctx context.Context, key string, start, stop int64) *ZSliceCmd
  282. ZRevRangeByScore(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd
  283. ZRevRangeByLex(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd
  284. ZRevRangeByScoreWithScores(ctx context.Context, key string, opt *ZRangeBy) *ZSliceCmd
  285. ZRevRank(ctx context.Context, key, member string) *IntCmd
  286. ZScore(ctx context.Context, key, member string) *FloatCmd
  287. ZUnionStore(ctx context.Context, dest string, store *ZStore) *IntCmd
  288. ZUnion(ctx context.Context, store ZStore) *StringSliceCmd
  289. ZUnionWithScores(ctx context.Context, store ZStore) *ZSliceCmd
  290. ZRandMember(ctx context.Context, key string, count int, withScores bool) *StringSliceCmd
  291. ZDiff(ctx context.Context, keys ...string) *StringSliceCmd
  292. ZDiffWithScores(ctx context.Context, keys ...string) *ZSliceCmd
  293. ZDiffStore(ctx context.Context, destination string, keys ...string) *IntCmd
  294. PFAdd(ctx context.Context, key string, els ...interface{}) *IntCmd
  295. PFCount(ctx context.Context, keys ...string) *IntCmd
  296. PFMerge(ctx context.Context, dest string, keys ...string) *StatusCmd
  297. BgRewriteAOF(ctx context.Context) *StatusCmd
  298. BgSave(ctx context.Context) *StatusCmd
  299. ClientKill(ctx context.Context, ipPort string) *StatusCmd
  300. ClientKillByFilter(ctx context.Context, keys ...string) *IntCmd
  301. ClientList(ctx context.Context) *StringCmd
  302. ClientPause(ctx context.Context, dur time.Duration) *BoolCmd
  303. ClientID(ctx context.Context) *IntCmd
  304. ConfigGet(ctx context.Context, parameter string) *SliceCmd
  305. ConfigResetStat(ctx context.Context) *StatusCmd
  306. ConfigSet(ctx context.Context, parameter, value string) *StatusCmd
  307. ConfigRewrite(ctx context.Context) *StatusCmd
  308. DBSize(ctx context.Context) *IntCmd
  309. FlushAll(ctx context.Context) *StatusCmd
  310. FlushAllAsync(ctx context.Context) *StatusCmd
  311. FlushDB(ctx context.Context) *StatusCmd
  312. FlushDBAsync(ctx context.Context) *StatusCmd
  313. Info(ctx context.Context, section ...string) *StringCmd
  314. LastSave(ctx context.Context) *IntCmd
  315. Save(ctx context.Context) *StatusCmd
  316. Shutdown(ctx context.Context) *StatusCmd
  317. ShutdownSave(ctx context.Context) *StatusCmd
  318. ShutdownNoSave(ctx context.Context) *StatusCmd
  319. SlaveOf(ctx context.Context, host, port string) *StatusCmd
  320. Time(ctx context.Context) *TimeCmd
  321. DebugObject(ctx context.Context, key string) *StringCmd
  322. ReadOnly(ctx context.Context) *StatusCmd
  323. ReadWrite(ctx context.Context) *StatusCmd
  324. MemoryUsage(ctx context.Context, key string, samples ...int) *IntCmd
  325. Eval(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd
  326. EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd
  327. ScriptExists(ctx context.Context, hashes ...string) *BoolSliceCmd
  328. ScriptFlush(ctx context.Context) *StatusCmd
  329. ScriptKill(ctx context.Context) *StatusCmd
  330. ScriptLoad(ctx context.Context, script string) *StringCmd
  331. Publish(ctx context.Context, channel string, message interface{}) *IntCmd
  332. PubSubChannels(ctx context.Context, pattern string) *StringSliceCmd
  333. PubSubNumSub(ctx context.Context, channels ...string) *StringIntMapCmd
  334. PubSubNumPat(ctx context.Context) *IntCmd
  335. ClusterSlots(ctx context.Context) *ClusterSlotsCmd
  336. ClusterNodes(ctx context.Context) *StringCmd
  337. ClusterMeet(ctx context.Context, host, port string) *StatusCmd
  338. ClusterForget(ctx context.Context, nodeID string) *StatusCmd
  339. ClusterReplicate(ctx context.Context, nodeID string) *StatusCmd
  340. ClusterResetSoft(ctx context.Context) *StatusCmd
  341. ClusterResetHard(ctx context.Context) *StatusCmd
  342. ClusterInfo(ctx context.Context) *StringCmd
  343. ClusterKeySlot(ctx context.Context, key string) *IntCmd
  344. ClusterGetKeysInSlot(ctx context.Context, slot int, count int) *StringSliceCmd
  345. ClusterCountFailureReports(ctx context.Context, nodeID string) *IntCmd
  346. ClusterCountKeysInSlot(ctx context.Context, slot int) *IntCmd
  347. ClusterDelSlots(ctx context.Context, slots ...int) *StatusCmd
  348. ClusterDelSlotsRange(ctx context.Context, min, max int) *StatusCmd
  349. ClusterSaveConfig(ctx context.Context) *StatusCmd
  350. ClusterSlaves(ctx context.Context, nodeID string) *StringSliceCmd
  351. ClusterFailover(ctx context.Context) *StatusCmd
  352. ClusterAddSlots(ctx context.Context, slots ...int) *StatusCmd
  353. ClusterAddSlotsRange(ctx context.Context, min, max int) *StatusCmd
  354. GeoAdd(ctx context.Context, key string, geoLocation ...*GeoLocation) *IntCmd
  355. GeoPos(ctx context.Context, key string, members ...string) *GeoPosCmd
  356. GeoRadius(ctx context.Context, key string, longitude, latitude float64, query *GeoRadiusQuery) *GeoLocationCmd
  357. GeoRadiusStore(ctx context.Context, key string, longitude, latitude float64, query *GeoRadiusQuery) *IntCmd
  358. GeoRadiusByMember(ctx context.Context, key, member string, query *GeoRadiusQuery) *GeoLocationCmd
  359. GeoRadiusByMemberStore(ctx context.Context, key, member string, query *GeoRadiusQuery) *IntCmd
  360. GeoSearch(ctx context.Context, key string, q *GeoSearchQuery) *StringSliceCmd
  361. GeoSearchLocation(ctx context.Context, key string, q *GeoSearchLocationQuery) *GeoSearchLocationCmd
  362. GeoSearchStore(ctx context.Context, key, store string, q *GeoSearchStoreQuery) *IntCmd
  363. GeoDist(ctx context.Context, key string, member1, member2, unit string) *FloatCmd
  364. GeoHash(ctx context.Context, key string, members ...string) *StringSliceCmd
  365. }
  366. type StatefulCmdable interface {
  367. Cmdable
  368. Auth(ctx context.Context, password string) *StatusCmd
  369. AuthACL(ctx context.Context, username, password string) *StatusCmd
  370. Select(ctx context.Context, index int) *StatusCmd
  371. SwapDB(ctx context.Context, index1, index2 int) *StatusCmd
  372. ClientSetName(ctx context.Context, name string) *BoolCmd
  373. }
  374. var (
  375. _ Cmdable = (*Client)(nil)
  376. _ Cmdable = (*Tx)(nil)
  377. _ Cmdable = (*Ring)(nil)
  378. _ Cmdable = (*ClusterClient)(nil)
  379. )
  380. type cmdable func(ctx context.Context, cmd Cmder) error
  381. type statefulCmdable func(ctx context.Context, cmd Cmder) error
  382. //------------------------------------------------------------------------------
  383. func (c statefulCmdable) Auth(ctx context.Context, password string) *StatusCmd {
  384. cmd := NewStatusCmd(ctx, "auth", password)
  385. _ = c(ctx, cmd)
  386. return cmd
  387. }
  388. // AuthACL Perform an AUTH command, using the given user and pass.
  389. // Should be used to authenticate the current connection with one of the connections defined in the ACL list
  390. // when connecting to a Redis 6.0 instance, or greater, that is using the Redis ACL system.
  391. func (c statefulCmdable) AuthACL(ctx context.Context, username, password string) *StatusCmd {
  392. cmd := NewStatusCmd(ctx, "auth", username, password)
  393. _ = c(ctx, cmd)
  394. return cmd
  395. }
  396. func (c cmdable) Wait(ctx context.Context, numSlaves int, timeout time.Duration) *IntCmd {
  397. cmd := NewIntCmd(ctx, "wait", numSlaves, int(timeout/time.Millisecond))
  398. _ = c(ctx, cmd)
  399. return cmd
  400. }
  401. func (c statefulCmdable) Select(ctx context.Context, index int) *StatusCmd {
  402. cmd := NewStatusCmd(ctx, "select", index)
  403. _ = c(ctx, cmd)
  404. return cmd
  405. }
  406. func (c statefulCmdable) SwapDB(ctx context.Context, index1, index2 int) *StatusCmd {
  407. cmd := NewStatusCmd(ctx, "swapdb", index1, index2)
  408. _ = c(ctx, cmd)
  409. return cmd
  410. }
  411. // ClientSetName assigns a name to the connection.
  412. func (c statefulCmdable) ClientSetName(ctx context.Context, name string) *BoolCmd {
  413. cmd := NewBoolCmd(ctx, "client", "setname", name)
  414. _ = c(ctx, cmd)
  415. return cmd
  416. }
  417. //------------------------------------------------------------------------------
  418. func (c cmdable) Command(ctx context.Context) *CommandsInfoCmd {
  419. cmd := NewCommandsInfoCmd(ctx, "command")
  420. _ = c(ctx, cmd)
  421. return cmd
  422. }
  423. // ClientGetName returns the name of the connection.
  424. func (c cmdable) ClientGetName(ctx context.Context) *StringCmd {
  425. cmd := NewStringCmd(ctx, "client", "getname")
  426. _ = c(ctx, cmd)
  427. return cmd
  428. }
  429. func (c cmdable) Echo(ctx context.Context, message interface{}) *StringCmd {
  430. cmd := NewStringCmd(ctx, "echo", message)
  431. _ = c(ctx, cmd)
  432. return cmd
  433. }
  434. func (c cmdable) Ping(ctx context.Context) *StatusCmd {
  435. cmd := NewStatusCmd(ctx, "ping")
  436. _ = c(ctx, cmd)
  437. return cmd
  438. }
  439. func (c cmdable) Quit(_ context.Context) *StatusCmd {
  440. panic("not implemented")
  441. }
  442. func (c cmdable) Del(ctx context.Context, keys ...string) *IntCmd {
  443. args := make([]interface{}, 1+len(keys))
  444. args[0] = "del"
  445. for i, key := range keys {
  446. args[1+i] = key
  447. }
  448. cmd := NewIntCmd(ctx, args...)
  449. _ = c(ctx, cmd)
  450. return cmd
  451. }
  452. func (c cmdable) Unlink(ctx context.Context, keys ...string) *IntCmd {
  453. args := make([]interface{}, 1+len(keys))
  454. args[0] = "unlink"
  455. for i, key := range keys {
  456. args[1+i] = key
  457. }
  458. cmd := NewIntCmd(ctx, args...)
  459. _ = c(ctx, cmd)
  460. return cmd
  461. }
  462. func (c cmdable) Dump(ctx context.Context, key string) *StringCmd {
  463. cmd := NewStringCmd(ctx, "dump", key)
  464. _ = c(ctx, cmd)
  465. return cmd
  466. }
  467. func (c cmdable) Exists(ctx context.Context, keys ...string) *IntCmd {
  468. args := make([]interface{}, 1+len(keys))
  469. args[0] = "exists"
  470. for i, key := range keys {
  471. args[1+i] = key
  472. }
  473. cmd := NewIntCmd(ctx, args...)
  474. _ = c(ctx, cmd)
  475. return cmd
  476. }
  477. func (c cmdable) Expire(ctx context.Context, key string, expiration time.Duration) *BoolCmd {
  478. cmd := NewBoolCmd(ctx, "expire", key, formatSec(ctx, expiration))
  479. _ = c(ctx, cmd)
  480. return cmd
  481. }
  482. func (c cmdable) ExpireAt(ctx context.Context, key string, tm time.Time) *BoolCmd {
  483. cmd := NewBoolCmd(ctx, "expireat", key, tm.Unix())
  484. _ = c(ctx, cmd)
  485. return cmd
  486. }
  487. func (c cmdable) Keys(ctx context.Context, pattern string) *StringSliceCmd {
  488. cmd := NewStringSliceCmd(ctx, "keys", pattern)
  489. _ = c(ctx, cmd)
  490. return cmd
  491. }
  492. func (c cmdable) Migrate(ctx context.Context, host, port, key string, db int, timeout time.Duration) *StatusCmd {
  493. cmd := NewStatusCmd(
  494. ctx,
  495. "migrate",
  496. host,
  497. port,
  498. key,
  499. db,
  500. formatMs(ctx, timeout),
  501. )
  502. cmd.setReadTimeout(timeout)
  503. _ = c(ctx, cmd)
  504. return cmd
  505. }
  506. func (c cmdable) Move(ctx context.Context, key string, db int) *BoolCmd {
  507. cmd := NewBoolCmd(ctx, "move", key, db)
  508. _ = c(ctx, cmd)
  509. return cmd
  510. }
  511. func (c cmdable) ObjectRefCount(ctx context.Context, key string) *IntCmd {
  512. cmd := NewIntCmd(ctx, "object", "refcount", key)
  513. _ = c(ctx, cmd)
  514. return cmd
  515. }
  516. func (c cmdable) ObjectEncoding(ctx context.Context, key string) *StringCmd {
  517. cmd := NewStringCmd(ctx, "object", "encoding", key)
  518. _ = c(ctx, cmd)
  519. return cmd
  520. }
  521. func (c cmdable) ObjectIdleTime(ctx context.Context, key string) *DurationCmd {
  522. cmd := NewDurationCmd(ctx, time.Second, "object", "idletime", key)
  523. _ = c(ctx, cmd)
  524. return cmd
  525. }
  526. func (c cmdable) Persist(ctx context.Context, key string) *BoolCmd {
  527. cmd := NewBoolCmd(ctx, "persist", key)
  528. _ = c(ctx, cmd)
  529. return cmd
  530. }
  531. func (c cmdable) PExpire(ctx context.Context, key string, expiration time.Duration) *BoolCmd {
  532. cmd := NewBoolCmd(ctx, "pexpire", key, formatMs(ctx, expiration))
  533. _ = c(ctx, cmd)
  534. return cmd
  535. }
  536. func (c cmdable) PExpireAt(ctx context.Context, key string, tm time.Time) *BoolCmd {
  537. cmd := NewBoolCmd(
  538. ctx,
  539. "pexpireat",
  540. key,
  541. tm.UnixNano()/int64(time.Millisecond),
  542. )
  543. _ = c(ctx, cmd)
  544. return cmd
  545. }
  546. func (c cmdable) PTTL(ctx context.Context, key string) *DurationCmd {
  547. cmd := NewDurationCmd(ctx, time.Millisecond, "pttl", key)
  548. _ = c(ctx, cmd)
  549. return cmd
  550. }
  551. func (c cmdable) RandomKey(ctx context.Context) *StringCmd {
  552. cmd := NewStringCmd(ctx, "randomkey")
  553. _ = c(ctx, cmd)
  554. return cmd
  555. }
  556. func (c cmdable) Rename(ctx context.Context, key, newkey string) *StatusCmd {
  557. cmd := NewStatusCmd(ctx, "rename", key, newkey)
  558. _ = c(ctx, cmd)
  559. return cmd
  560. }
  561. func (c cmdable) RenameNX(ctx context.Context, key, newkey string) *BoolCmd {
  562. cmd := NewBoolCmd(ctx, "renamenx", key, newkey)
  563. _ = c(ctx, cmd)
  564. return cmd
  565. }
  566. func (c cmdable) Restore(ctx context.Context, key string, ttl time.Duration, value string) *StatusCmd {
  567. cmd := NewStatusCmd(
  568. ctx,
  569. "restore",
  570. key,
  571. formatMs(ctx, ttl),
  572. value,
  573. )
  574. _ = c(ctx, cmd)
  575. return cmd
  576. }
  577. func (c cmdable) RestoreReplace(ctx context.Context, key string, ttl time.Duration, value string) *StatusCmd {
  578. cmd := NewStatusCmd(
  579. ctx,
  580. "restore",
  581. key,
  582. formatMs(ctx, ttl),
  583. value,
  584. "replace",
  585. )
  586. _ = c(ctx, cmd)
  587. return cmd
  588. }
  589. type Sort struct {
  590. By string
  591. Offset, Count int64
  592. Get []string
  593. Order string
  594. Alpha bool
  595. }
  596. func (sort *Sort) args(key string) []interface{} {
  597. args := []interface{}{"sort", key}
  598. if sort.By != "" {
  599. args = append(args, "by", sort.By)
  600. }
  601. if sort.Offset != 0 || sort.Count != 0 {
  602. args = append(args, "limit", sort.Offset, sort.Count)
  603. }
  604. for _, get := range sort.Get {
  605. args = append(args, "get", get)
  606. }
  607. if sort.Order != "" {
  608. args = append(args, sort.Order)
  609. }
  610. if sort.Alpha {
  611. args = append(args, "alpha")
  612. }
  613. return args
  614. }
  615. func (c cmdable) Sort(ctx context.Context, key string, sort *Sort) *StringSliceCmd {
  616. cmd := NewStringSliceCmd(ctx, sort.args(key)...)
  617. _ = c(ctx, cmd)
  618. return cmd
  619. }
  620. func (c cmdable) SortStore(ctx context.Context, key, store string, sort *Sort) *IntCmd {
  621. args := sort.args(key)
  622. if store != "" {
  623. args = append(args, "store", store)
  624. }
  625. cmd := NewIntCmd(ctx, args...)
  626. _ = c(ctx, cmd)
  627. return cmd
  628. }
  629. func (c cmdable) SortInterfaces(ctx context.Context, key string, sort *Sort) *SliceCmd {
  630. cmd := NewSliceCmd(ctx, sort.args(key)...)
  631. _ = c(ctx, cmd)
  632. return cmd
  633. }
  634. func (c cmdable) Touch(ctx context.Context, keys ...string) *IntCmd {
  635. args := make([]interface{}, len(keys)+1)
  636. args[0] = "touch"
  637. for i, key := range keys {
  638. args[i+1] = key
  639. }
  640. cmd := NewIntCmd(ctx, args...)
  641. _ = c(ctx, cmd)
  642. return cmd
  643. }
  644. func (c cmdable) TTL(ctx context.Context, key string) *DurationCmd {
  645. cmd := NewDurationCmd(ctx, time.Second, "ttl", key)
  646. _ = c(ctx, cmd)
  647. return cmd
  648. }
  649. func (c cmdable) Type(ctx context.Context, key string) *StatusCmd {
  650. cmd := NewStatusCmd(ctx, "type", key)
  651. _ = c(ctx, cmd)
  652. return cmd
  653. }
  654. func (c cmdable) Append(ctx context.Context, key, value string) *IntCmd {
  655. cmd := NewIntCmd(ctx, "append", key, value)
  656. _ = c(ctx, cmd)
  657. return cmd
  658. }
  659. func (c cmdable) Decr(ctx context.Context, key string) *IntCmd {
  660. cmd := NewIntCmd(ctx, "decr", key)
  661. _ = c(ctx, cmd)
  662. return cmd
  663. }
  664. func (c cmdable) DecrBy(ctx context.Context, key string, decrement int64) *IntCmd {
  665. cmd := NewIntCmd(ctx, "decrby", key, decrement)
  666. _ = c(ctx, cmd)
  667. return cmd
  668. }
  669. // Get Redis `GET key` command. It returns redis.Nil error when key does not exist.
  670. func (c cmdable) Get(ctx context.Context, key string) *StringCmd {
  671. cmd := NewStringCmd(ctx, "get", key)
  672. _ = c(ctx, cmd)
  673. return cmd
  674. }
  675. func (c cmdable) GetRange(ctx context.Context, key string, start, end int64) *StringCmd {
  676. cmd := NewStringCmd(ctx, "getrange", key, start, end)
  677. _ = c(ctx, cmd)
  678. return cmd
  679. }
  680. func (c cmdable) GetSet(ctx context.Context, key string, value interface{}) *StringCmd {
  681. cmd := NewStringCmd(ctx, "getset", key, value)
  682. _ = c(ctx, cmd)
  683. return cmd
  684. }
  685. // GetEx An expiration of zero removes the TTL associated with the key (i.e. GETEX key persist).
  686. // Requires Redis >= 6.2.0.
  687. func (c cmdable) GetEx(ctx context.Context, key string, expiration time.Duration) *StringCmd {
  688. args := make([]interface{}, 0, 4)
  689. args = append(args, "getex", key)
  690. if expiration > 0 {
  691. if usePrecise(expiration) {
  692. args = append(args, "px", formatMs(ctx, expiration))
  693. } else {
  694. args = append(args, "ex", formatSec(ctx, expiration))
  695. }
  696. } else if expiration == 0 {
  697. args = append(args, "persist")
  698. }
  699. cmd := NewStringCmd(ctx, args...)
  700. _ = c(ctx, cmd)
  701. return cmd
  702. }
  703. // GetDel redis-server version >= 6.2.0.
  704. func (c cmdable) GetDel(ctx context.Context, key string) *StringCmd {
  705. cmd := NewStringCmd(ctx, "getdel", key)
  706. _ = c(ctx, cmd)
  707. return cmd
  708. }
  709. func (c cmdable) Incr(ctx context.Context, key string) *IntCmd {
  710. cmd := NewIntCmd(ctx, "incr", key)
  711. _ = c(ctx, cmd)
  712. return cmd
  713. }
  714. func (c cmdable) IncrBy(ctx context.Context, key string, value int64) *IntCmd {
  715. cmd := NewIntCmd(ctx, "incrby", key, value)
  716. _ = c(ctx, cmd)
  717. return cmd
  718. }
  719. func (c cmdable) IncrByFloat(ctx context.Context, key string, value float64) *FloatCmd {
  720. cmd := NewFloatCmd(ctx, "incrbyfloat", key, value)
  721. _ = c(ctx, cmd)
  722. return cmd
  723. }
  724. func (c cmdable) MGet(ctx context.Context, keys ...string) *SliceCmd {
  725. args := make([]interface{}, 1+len(keys))
  726. args[0] = "mget"
  727. for i, key := range keys {
  728. args[1+i] = key
  729. }
  730. cmd := NewSliceCmd(ctx, args...)
  731. _ = c(ctx, cmd)
  732. return cmd
  733. }
  734. // MSet is like Set but accepts multiple values:
  735. // - MSet("key1", "value1", "key2", "value2")
  736. // - MSet([]string{"key1", "value1", "key2", "value2"})
  737. // - MSet(map[string]interface{}{"key1": "value1", "key2": "value2"})
  738. func (c cmdable) MSet(ctx context.Context, values ...interface{}) *StatusCmd {
  739. args := make([]interface{}, 1, 1+len(values))
  740. args[0] = "mset"
  741. args = appendArgs(args, values)
  742. cmd := NewStatusCmd(ctx, args...)
  743. _ = c(ctx, cmd)
  744. return cmd
  745. }
  746. // MSetNX is like SetNX but accepts multiple values:
  747. // - MSetNX("key1", "value1", "key2", "value2")
  748. // - MSetNX([]string{"key1", "value1", "key2", "value2"})
  749. // - MSetNX(map[string]interface{}{"key1": "value1", "key2": "value2"})
  750. func (c cmdable) MSetNX(ctx context.Context, values ...interface{}) *BoolCmd {
  751. args := make([]interface{}, 1, 1+len(values))
  752. args[0] = "msetnx"
  753. args = appendArgs(args, values)
  754. cmd := NewBoolCmd(ctx, args...)
  755. _ = c(ctx, cmd)
  756. return cmd
  757. }
  758. // Set Redis `SET key value [expiration]` command.
  759. // Use expiration for `SETEX`-like behavior.
  760. //
  761. // Zero expiration means the key has no expiration time.
  762. // KeepTTL is a Redis KEEPTTL option to keep existing TTL, it requires your redis-server version >= 6.0,
  763. // otherwise you will receive an error: (error) ERR syntax error.
  764. func (c cmdable) Set(ctx context.Context, key string, value interface{}, expiration time.Duration) *StatusCmd {
  765. args := make([]interface{}, 3, 5)
  766. args[0] = "set"
  767. args[1] = key
  768. args[2] = value
  769. if expiration > 0 {
  770. if usePrecise(expiration) {
  771. args = append(args, "px", formatMs(ctx, expiration))
  772. } else {
  773. args = append(args, "ex", formatSec(ctx, expiration))
  774. }
  775. } else if expiration == KeepTTL {
  776. args = append(args, "keepttl")
  777. }
  778. cmd := NewStatusCmd(ctx, args...)
  779. _ = c(ctx, cmd)
  780. return cmd
  781. }
  782. // SetArgs provides arguments for the SetArgs function.
  783. type SetArgs struct {
  784. // Mode can be `NX` or `XX` or empty.
  785. Mode string
  786. // Zero `TTL` or `Expiration` means that the key has no expiration time.
  787. TTL time.Duration
  788. ExpireAt time.Time
  789. // When Get is true, the command returns the old value stored at key, or nil when key did not exist.
  790. Get bool
  791. // KeepTTL is a Redis KEEPTTL option to keep existing TTL, it requires your redis-server version >= 6.0,
  792. // otherwise you will receive an error: (error) ERR syntax error.
  793. KeepTTL bool
  794. }
  795. // SetArgs supports all the options that the SET command supports.
  796. // It is the alternative to the Set function when you want
  797. // to have more control over the options.
  798. func (c cmdable) SetArgs(ctx context.Context, key string, value interface{}, a SetArgs) *StatusCmd {
  799. args := []interface{}{"set", key, value}
  800. if a.KeepTTL {
  801. args = append(args, "keepttl")
  802. }
  803. if !a.ExpireAt.IsZero() {
  804. args = append(args, "exat", a.ExpireAt.Unix())
  805. }
  806. if a.TTL > 0 {
  807. if usePrecise(a.TTL) {
  808. args = append(args, "px", formatMs(ctx, a.TTL))
  809. } else {
  810. args = append(args, "ex", formatSec(ctx, a.TTL))
  811. }
  812. }
  813. if a.Mode != "" {
  814. args = append(args, a.Mode)
  815. }
  816. if a.Get {
  817. args = append(args, "get")
  818. }
  819. cmd := NewStatusCmd(ctx, args...)
  820. _ = c(ctx, cmd)
  821. return cmd
  822. }
  823. // SetEX Redis `SETEX key expiration value` command.
  824. func (c cmdable) SetEX(ctx context.Context, key string, value interface{}, expiration time.Duration) *StatusCmd {
  825. cmd := NewStatusCmd(ctx, "setex", key, formatSec(ctx, expiration), value)
  826. _ = c(ctx, cmd)
  827. return cmd
  828. }
  829. // SetNX Redis `SET key value [expiration] NX` command.
  830. //
  831. // Zero expiration means the key has no expiration time.
  832. // KeepTTL is a Redis KEEPTTL option to keep existing TTL, it requires your redis-server version >= 6.0,
  833. // otherwise you will receive an error: (error) ERR syntax error.
  834. func (c cmdable) SetNX(ctx context.Context, key string, value interface{}, expiration time.Duration) *BoolCmd {
  835. var cmd *BoolCmd
  836. switch expiration {
  837. case 0:
  838. // Use old `SETNX` to support old Redis versions.
  839. cmd = NewBoolCmd(ctx, "setnx", key, value)
  840. case KeepTTL:
  841. cmd = NewBoolCmd(ctx, "set", key, value, "keepttl", "nx")
  842. default:
  843. if usePrecise(expiration) {
  844. cmd = NewBoolCmd(ctx, "set", key, value, "px", formatMs(ctx, expiration), "nx")
  845. } else {
  846. cmd = NewBoolCmd(ctx, "set", key, value, "ex", formatSec(ctx, expiration), "nx")
  847. }
  848. }
  849. _ = c(ctx, cmd)
  850. return cmd
  851. }
  852. // SetXX Redis `SET key value [expiration] XX` command.
  853. //
  854. // Zero expiration means the key has no expiration time.
  855. // KeepTTL is a Redis KEEPTTL option to keep existing TTL, it requires your redis-server version >= 6.0,
  856. // otherwise you will receive an error: (error) ERR syntax error.
  857. func (c cmdable) SetXX(ctx context.Context, key string, value interface{}, expiration time.Duration) *BoolCmd {
  858. var cmd *BoolCmd
  859. switch expiration {
  860. case 0:
  861. cmd = NewBoolCmd(ctx, "set", key, value, "xx")
  862. case KeepTTL:
  863. cmd = NewBoolCmd(ctx, "set", key, value, "keepttl", "xx")
  864. default:
  865. if usePrecise(expiration) {
  866. cmd = NewBoolCmd(ctx, "set", key, value, "px", formatMs(ctx, expiration), "xx")
  867. } else {
  868. cmd = NewBoolCmd(ctx, "set", key, value, "ex", formatSec(ctx, expiration), "xx")
  869. }
  870. }
  871. _ = c(ctx, cmd)
  872. return cmd
  873. }
  874. func (c cmdable) SetRange(ctx context.Context, key string, offset int64, value string) *IntCmd {
  875. cmd := NewIntCmd(ctx, "setrange", key, offset, value)
  876. _ = c(ctx, cmd)
  877. return cmd
  878. }
  879. func (c cmdable) StrLen(ctx context.Context, key string) *IntCmd {
  880. cmd := NewIntCmd(ctx, "strlen", key)
  881. _ = c(ctx, cmd)
  882. return cmd
  883. }
  884. //------------------------------------------------------------------------------
  885. func (c cmdable) GetBit(ctx context.Context, key string, offset int64) *IntCmd {
  886. cmd := NewIntCmd(ctx, "getbit", key, offset)
  887. _ = c(ctx, cmd)
  888. return cmd
  889. }
  890. func (c cmdable) SetBit(ctx context.Context, key string, offset int64, value int) *IntCmd {
  891. cmd := NewIntCmd(
  892. ctx,
  893. "setbit",
  894. key,
  895. offset,
  896. value,
  897. )
  898. _ = c(ctx, cmd)
  899. return cmd
  900. }
  901. type BitCount struct {
  902. Start, End int64
  903. }
  904. func (c cmdable) BitCount(ctx context.Context, key string, bitCount *BitCount) *IntCmd {
  905. args := []interface{}{"bitcount", key}
  906. if bitCount != nil {
  907. args = append(
  908. args,
  909. bitCount.Start,
  910. bitCount.End,
  911. )
  912. }
  913. cmd := NewIntCmd(ctx, args...)
  914. _ = c(ctx, cmd)
  915. return cmd
  916. }
  917. func (c cmdable) bitOp(ctx context.Context, op, destKey string, keys ...string) *IntCmd {
  918. args := make([]interface{}, 3+len(keys))
  919. args[0] = "bitop"
  920. args[1] = op
  921. args[2] = destKey
  922. for i, key := range keys {
  923. args[3+i] = key
  924. }
  925. cmd := NewIntCmd(ctx, args...)
  926. _ = c(ctx, cmd)
  927. return cmd
  928. }
  929. func (c cmdable) BitOpAnd(ctx context.Context, destKey string, keys ...string) *IntCmd {
  930. return c.bitOp(ctx, "and", destKey, keys...)
  931. }
  932. func (c cmdable) BitOpOr(ctx context.Context, destKey string, keys ...string) *IntCmd {
  933. return c.bitOp(ctx, "or", destKey, keys...)
  934. }
  935. func (c cmdable) BitOpXor(ctx context.Context, destKey string, keys ...string) *IntCmd {
  936. return c.bitOp(ctx, "xor", destKey, keys...)
  937. }
  938. func (c cmdable) BitOpNot(ctx context.Context, destKey string, key string) *IntCmd {
  939. return c.bitOp(ctx, "not", destKey, key)
  940. }
  941. func (c cmdable) BitPos(ctx context.Context, key string, bit int64, pos ...int64) *IntCmd {
  942. args := make([]interface{}, 3+len(pos))
  943. args[0] = "bitpos"
  944. args[1] = key
  945. args[2] = bit
  946. switch len(pos) {
  947. case 0:
  948. case 1:
  949. args[3] = pos[0]
  950. case 2:
  951. args[3] = pos[0]
  952. args[4] = pos[1]
  953. default:
  954. panic("too many arguments")
  955. }
  956. cmd := NewIntCmd(ctx, args...)
  957. _ = c(ctx, cmd)
  958. return cmd
  959. }
  960. func (c cmdable) BitField(ctx context.Context, key string, args ...interface{}) *IntSliceCmd {
  961. a := make([]interface{}, 0, 2+len(args))
  962. a = append(a, "bitfield")
  963. a = append(a, key)
  964. a = append(a, args...)
  965. cmd := NewIntSliceCmd(ctx, a...)
  966. _ = c(ctx, cmd)
  967. return cmd
  968. }
  969. //------------------------------------------------------------------------------
  970. func (c cmdable) Scan(ctx context.Context, cursor uint64, match string, count int64) *ScanCmd {
  971. args := []interface{}{"scan", cursor}
  972. if match != "" {
  973. args = append(args, "match", match)
  974. }
  975. if count > 0 {
  976. args = append(args, "count", count)
  977. }
  978. cmd := NewScanCmd(ctx, c, args...)
  979. _ = c(ctx, cmd)
  980. return cmd
  981. }
  982. func (c cmdable) ScanType(ctx context.Context, cursor uint64, match string, count int64, keyType string) *ScanCmd {
  983. args := []interface{}{"scan", cursor}
  984. if match != "" {
  985. args = append(args, "match", match)
  986. }
  987. if count > 0 {
  988. args = append(args, "count", count)
  989. }
  990. if keyType != "" {
  991. args = append(args, "type", keyType)
  992. }
  993. cmd := NewScanCmd(ctx, c, args...)
  994. _ = c(ctx, cmd)
  995. return cmd
  996. }
  997. func (c cmdable) SScan(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd {
  998. args := []interface{}{"sscan", key, cursor}
  999. if match != "" {
  1000. args = append(args, "match", match)
  1001. }
  1002. if count > 0 {
  1003. args = append(args, "count", count)
  1004. }
  1005. cmd := NewScanCmd(ctx, c, args...)
  1006. _ = c(ctx, cmd)
  1007. return cmd
  1008. }
  1009. func (c cmdable) HScan(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd {
  1010. args := []interface{}{"hscan", key, cursor}
  1011. if match != "" {
  1012. args = append(args, "match", match)
  1013. }
  1014. if count > 0 {
  1015. args = append(args, "count", count)
  1016. }
  1017. cmd := NewScanCmd(ctx, c, args...)
  1018. _ = c(ctx, cmd)
  1019. return cmd
  1020. }
  1021. func (c cmdable) ZScan(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd {
  1022. args := []interface{}{"zscan", key, cursor}
  1023. if match != "" {
  1024. args = append(args, "match", match)
  1025. }
  1026. if count > 0 {
  1027. args = append(args, "count", count)
  1028. }
  1029. cmd := NewScanCmd(ctx, c, args...)
  1030. _ = c(ctx, cmd)
  1031. return cmd
  1032. }
  1033. //------------------------------------------------------------------------------
  1034. func (c cmdable) HDel(ctx context.Context, key string, fields ...string) *IntCmd {
  1035. args := make([]interface{}, 2+len(fields))
  1036. args[0] = "hdel"
  1037. args[1] = key
  1038. for i, field := range fields {
  1039. args[2+i] = field
  1040. }
  1041. cmd := NewIntCmd(ctx, args...)
  1042. _ = c(ctx, cmd)
  1043. return cmd
  1044. }
  1045. func (c cmdable) HExists(ctx context.Context, key, field string) *BoolCmd {
  1046. cmd := NewBoolCmd(ctx, "hexists", key, field)
  1047. _ = c(ctx, cmd)
  1048. return cmd
  1049. }
  1050. func (c cmdable) HGet(ctx context.Context, key, field string) *StringCmd {
  1051. cmd := NewStringCmd(ctx, "hget", key, field)
  1052. _ = c(ctx, cmd)
  1053. return cmd
  1054. }
  1055. func (c cmdable) HGetAll(ctx context.Context, key string) *StringStringMapCmd {
  1056. cmd := NewStringStringMapCmd(ctx, "hgetall", key)
  1057. _ = c(ctx, cmd)
  1058. return cmd
  1059. }
  1060. func (c cmdable) HIncrBy(ctx context.Context, key, field string, incr int64) *IntCmd {
  1061. cmd := NewIntCmd(ctx, "hincrby", key, field, incr)
  1062. _ = c(ctx, cmd)
  1063. return cmd
  1064. }
  1065. func (c cmdable) HIncrByFloat(ctx context.Context, key, field string, incr float64) *FloatCmd {
  1066. cmd := NewFloatCmd(ctx, "hincrbyfloat", key, field, incr)
  1067. _ = c(ctx, cmd)
  1068. return cmd
  1069. }
  1070. func (c cmdable) HKeys(ctx context.Context, key string) *StringSliceCmd {
  1071. cmd := NewStringSliceCmd(ctx, "hkeys", key)
  1072. _ = c(ctx, cmd)
  1073. return cmd
  1074. }
  1075. func (c cmdable) HLen(ctx context.Context, key string) *IntCmd {
  1076. cmd := NewIntCmd(ctx, "hlen", key)
  1077. _ = c(ctx, cmd)
  1078. return cmd
  1079. }
  1080. // HMGet returns the values for the specified fields in the hash stored at key.
  1081. // It returns an interface{} to distinguish between empty string and nil value.
  1082. func (c cmdable) HMGet(ctx context.Context, key string, fields ...string) *SliceCmd {
  1083. args := make([]interface{}, 2+len(fields))
  1084. args[0] = "hmget"
  1085. args[1] = key
  1086. for i, field := range fields {
  1087. args[2+i] = field
  1088. }
  1089. cmd := NewSliceCmd(ctx, args...)
  1090. _ = c(ctx, cmd)
  1091. return cmd
  1092. }
  1093. // HSet accepts values in following formats:
  1094. // - HSet("myhash", "key1", "value1", "key2", "value2")
  1095. // - HSet("myhash", []string{"key1", "value1", "key2", "value2"})
  1096. // - HSet("myhash", map[string]interface{}{"key1": "value1", "key2": "value2"})
  1097. //
  1098. // Note that it requires Redis v4 for multiple field/value pairs support.
  1099. func (c cmdable) HSet(ctx context.Context, key string, values ...interface{}) *IntCmd {
  1100. args := make([]interface{}, 2, 2+len(values))
  1101. args[0] = "hset"
  1102. args[1] = key
  1103. args = appendArgs(args, values)
  1104. cmd := NewIntCmd(ctx, args...)
  1105. _ = c(ctx, cmd)
  1106. return cmd
  1107. }
  1108. // HMSet is a deprecated version of HSet left for compatibility with Redis 3.
  1109. func (c cmdable) HMSet(ctx context.Context, key string, values ...interface{}) *BoolCmd {
  1110. args := make([]interface{}, 2, 2+len(values))
  1111. args[0] = "hmset"
  1112. args[1] = key
  1113. args = appendArgs(args, values)
  1114. cmd := NewBoolCmd(ctx, args...)
  1115. _ = c(ctx, cmd)
  1116. return cmd
  1117. }
  1118. func (c cmdable) HSetNX(ctx context.Context, key, field string, value interface{}) *BoolCmd {
  1119. cmd := NewBoolCmd(ctx, "hsetnx", key, field, value)
  1120. _ = c(ctx, cmd)
  1121. return cmd
  1122. }
  1123. func (c cmdable) HVals(ctx context.Context, key string) *StringSliceCmd {
  1124. cmd := NewStringSliceCmd(ctx, "hvals", key)
  1125. _ = c(ctx, cmd)
  1126. return cmd
  1127. }
  1128. // HRandField redis-server version >= 6.2.0.
  1129. func (c cmdable) HRandField(ctx context.Context, key string, count int, withValues bool) *StringSliceCmd {
  1130. args := make([]interface{}, 0, 4)
  1131. // Although count=0 is meaningless, redis accepts count=0.
  1132. args = append(args, "hrandfield", key, count)
  1133. if withValues {
  1134. args = append(args, "withvalues")
  1135. }
  1136. cmd := NewStringSliceCmd(ctx, args...)
  1137. _ = c(ctx, cmd)
  1138. return cmd
  1139. }
  1140. //------------------------------------------------------------------------------
  1141. func (c cmdable) BLPop(ctx context.Context, timeout time.Duration, keys ...string) *StringSliceCmd {
  1142. args := make([]interface{}, 1+len(keys)+1)
  1143. args[0] = "blpop"
  1144. for i, key := range keys {
  1145. args[1+i] = key
  1146. }
  1147. args[len(args)-1] = formatSec(ctx, timeout)
  1148. cmd := NewStringSliceCmd(ctx, args...)
  1149. cmd.setReadTimeout(timeout)
  1150. _ = c(ctx, cmd)
  1151. return cmd
  1152. }
  1153. func (c cmdable) BRPop(ctx context.Context, timeout time.Duration, keys ...string) *StringSliceCmd {
  1154. args := make([]interface{}, 1+len(keys)+1)
  1155. args[0] = "brpop"
  1156. for i, key := range keys {
  1157. args[1+i] = key
  1158. }
  1159. args[len(keys)+1] = formatSec(ctx, timeout)
  1160. cmd := NewStringSliceCmd(ctx, args...)
  1161. cmd.setReadTimeout(timeout)
  1162. _ = c(ctx, cmd)
  1163. return cmd
  1164. }
  1165. func (c cmdable) BRPopLPush(ctx context.Context, source, destination string, timeout time.Duration) *StringCmd {
  1166. cmd := NewStringCmd(
  1167. ctx,
  1168. "brpoplpush",
  1169. source,
  1170. destination,
  1171. formatSec(ctx, timeout),
  1172. )
  1173. cmd.setReadTimeout(timeout)
  1174. _ = c(ctx, cmd)
  1175. return cmd
  1176. }
  1177. func (c cmdable) LIndex(ctx context.Context, key string, index int64) *StringCmd {
  1178. cmd := NewStringCmd(ctx, "lindex", key, index)
  1179. _ = c(ctx, cmd)
  1180. return cmd
  1181. }
  1182. func (c cmdable) LInsert(ctx context.Context, key, op string, pivot, value interface{}) *IntCmd {
  1183. cmd := NewIntCmd(ctx, "linsert", key, op, pivot, value)
  1184. _ = c(ctx, cmd)
  1185. return cmd
  1186. }
  1187. func (c cmdable) LInsertBefore(ctx context.Context, key string, pivot, value interface{}) *IntCmd {
  1188. cmd := NewIntCmd(ctx, "linsert", key, "before", pivot, value)
  1189. _ = c(ctx, cmd)
  1190. return cmd
  1191. }
  1192. func (c cmdable) LInsertAfter(ctx context.Context, key string, pivot, value interface{}) *IntCmd {
  1193. cmd := NewIntCmd(ctx, "linsert", key, "after", pivot, value)
  1194. _ = c(ctx, cmd)
  1195. return cmd
  1196. }
  1197. func (c cmdable) LLen(ctx context.Context, key string) *IntCmd {
  1198. cmd := NewIntCmd(ctx, "llen", key)
  1199. _ = c(ctx, cmd)
  1200. return cmd
  1201. }
  1202. func (c cmdable) LPop(ctx context.Context, key string) *StringCmd {
  1203. cmd := NewStringCmd(ctx, "lpop", key)
  1204. _ = c(ctx, cmd)
  1205. return cmd
  1206. }
  1207. func (c cmdable) LPopCount(ctx context.Context, key string, count int) *StringSliceCmd {
  1208. cmd := NewStringSliceCmd(ctx, "lpop", key, count)
  1209. _ = c(ctx, cmd)
  1210. return cmd
  1211. }
  1212. type LPosArgs struct {
  1213. Rank, MaxLen int64
  1214. }
  1215. func (c cmdable) LPos(ctx context.Context, key string, value string, a LPosArgs) *IntCmd {
  1216. args := []interface{}{"lpos", key, value}
  1217. if a.Rank != 0 {
  1218. args = append(args, "rank", a.Rank)
  1219. }
  1220. if a.MaxLen != 0 {
  1221. args = append(args, "maxlen", a.MaxLen)
  1222. }
  1223. cmd := NewIntCmd(ctx, args...)
  1224. _ = c(ctx, cmd)
  1225. return cmd
  1226. }
  1227. func (c cmdable) LPosCount(ctx context.Context, key string, value string, count int64, a LPosArgs) *IntSliceCmd {
  1228. args := []interface{}{"lpos", key, value, "count", count}
  1229. if a.Rank != 0 {
  1230. args = append(args, "rank", a.Rank)
  1231. }
  1232. if a.MaxLen != 0 {
  1233. args = append(args, "maxlen", a.MaxLen)
  1234. }
  1235. cmd := NewIntSliceCmd(ctx, args...)
  1236. _ = c(ctx, cmd)
  1237. return cmd
  1238. }
  1239. func (c cmdable) LPush(ctx context.Context, key string, values ...interface{}) *IntCmd {
  1240. args := make([]interface{}, 2, 2+len(values))
  1241. args[0] = "lpush"
  1242. args[1] = key
  1243. args = appendArgs(args, values)
  1244. cmd := NewIntCmd(ctx, args...)
  1245. _ = c(ctx, cmd)
  1246. return cmd
  1247. }
  1248. func (c cmdable) LPushX(ctx context.Context, key string, values ...interface{}) *IntCmd {
  1249. args := make([]interface{}, 2, 2+len(values))
  1250. args[0] = "lpushx"
  1251. args[1] = key
  1252. args = appendArgs(args, values)
  1253. cmd := NewIntCmd(ctx, args...)
  1254. _ = c(ctx, cmd)
  1255. return cmd
  1256. }
  1257. func (c cmdable) LRange(ctx context.Context, key string, start, stop int64) *StringSliceCmd {
  1258. cmd := NewStringSliceCmd(
  1259. ctx,
  1260. "lrange",
  1261. key,
  1262. start,
  1263. stop,
  1264. )
  1265. _ = c(ctx, cmd)
  1266. return cmd
  1267. }
  1268. func (c cmdable) LRem(ctx context.Context, key string, count int64, value interface{}) *IntCmd {
  1269. cmd := NewIntCmd(ctx, "lrem", key, count, value)
  1270. _ = c(ctx, cmd)
  1271. return cmd
  1272. }
  1273. func (c cmdable) LSet(ctx context.Context, key string, index int64, value interface{}) *StatusCmd {
  1274. cmd := NewStatusCmd(ctx, "lset", key, index, value)
  1275. _ = c(ctx, cmd)
  1276. return cmd
  1277. }
  1278. func (c cmdable) LTrim(ctx context.Context, key string, start, stop int64) *StatusCmd {
  1279. cmd := NewStatusCmd(
  1280. ctx,
  1281. "ltrim",
  1282. key,
  1283. start,
  1284. stop,
  1285. )
  1286. _ = c(ctx, cmd)
  1287. return cmd
  1288. }
  1289. func (c cmdable) RPop(ctx context.Context, key string) *StringCmd {
  1290. cmd := NewStringCmd(ctx, "rpop", key)
  1291. _ = c(ctx, cmd)
  1292. return cmd
  1293. }
  1294. func (c cmdable) RPopCount(ctx context.Context, key string, count int) *StringSliceCmd {
  1295. cmd := NewStringSliceCmd(ctx, "rpop", key, count)
  1296. _ = c(ctx, cmd)
  1297. return cmd
  1298. }
  1299. func (c cmdable) RPopLPush(ctx context.Context, source, destination string) *StringCmd {
  1300. cmd := NewStringCmd(ctx, "rpoplpush", source, destination)
  1301. _ = c(ctx, cmd)
  1302. return cmd
  1303. }
  1304. func (c cmdable) RPush(ctx context.Context, key string, values ...interface{}) *IntCmd {
  1305. args := make([]interface{}, 2, 2+len(values))
  1306. args[0] = "rpush"
  1307. args[1] = key
  1308. args = appendArgs(args, values)
  1309. cmd := NewIntCmd(ctx, args...)
  1310. _ = c(ctx, cmd)
  1311. return cmd
  1312. }
  1313. func (c cmdable) RPushX(ctx context.Context, key string, values ...interface{}) *IntCmd {
  1314. args := make([]interface{}, 2, 2+len(values))
  1315. args[0] = "rpushx"
  1316. args[1] = key
  1317. args = appendArgs(args, values)
  1318. cmd := NewIntCmd(ctx, args...)
  1319. _ = c(ctx, cmd)
  1320. return cmd
  1321. }
  1322. func (c cmdable) LMove(ctx context.Context, source, destination, srcpos, destpos string) *StringCmd {
  1323. cmd := NewStringCmd(ctx, "lmove", source, destination, srcpos, destpos)
  1324. _ = c(ctx, cmd)
  1325. return cmd
  1326. }
  1327. func (c cmdable) BLMove(
  1328. ctx context.Context, source, destination, srcpos, destpos string, timeout time.Duration,
  1329. ) *StringCmd {
  1330. cmd := NewStringCmd(ctx, "blmove", source, destination, srcpos, destpos, formatSec(ctx, timeout))
  1331. cmd.setReadTimeout(timeout)
  1332. _ = c(ctx, cmd)
  1333. return cmd
  1334. }
  1335. //------------------------------------------------------------------------------
  1336. func (c cmdable) SAdd(ctx context.Context, key string, members ...interface{}) *IntCmd {
  1337. args := make([]interface{}, 2, 2+len(members))
  1338. args[0] = "sadd"
  1339. args[1] = key
  1340. args = appendArgs(args, members)
  1341. cmd := NewIntCmd(ctx, args...)
  1342. _ = c(ctx, cmd)
  1343. return cmd
  1344. }
  1345. func (c cmdable) SCard(ctx context.Context, key string) *IntCmd {
  1346. cmd := NewIntCmd(ctx, "scard", key)
  1347. _ = c(ctx, cmd)
  1348. return cmd
  1349. }
  1350. func (c cmdable) SDiff(ctx context.Context, keys ...string) *StringSliceCmd {
  1351. args := make([]interface{}, 1+len(keys))
  1352. args[0] = "sdiff"
  1353. for i, key := range keys {
  1354. args[1+i] = key
  1355. }
  1356. cmd := NewStringSliceCmd(ctx, args...)
  1357. _ = c(ctx, cmd)
  1358. return cmd
  1359. }
  1360. func (c cmdable) SDiffStore(ctx context.Context, destination string, keys ...string) *IntCmd {
  1361. args := make([]interface{}, 2+len(keys))
  1362. args[0] = "sdiffstore"
  1363. args[1] = destination
  1364. for i, key := range keys {
  1365. args[2+i] = key
  1366. }
  1367. cmd := NewIntCmd(ctx, args...)
  1368. _ = c(ctx, cmd)
  1369. return cmd
  1370. }
  1371. func (c cmdable) SInter(ctx context.Context, keys ...string) *StringSliceCmd {
  1372. args := make([]interface{}, 1+len(keys))
  1373. args[0] = "sinter"
  1374. for i, key := range keys {
  1375. args[1+i] = key
  1376. }
  1377. cmd := NewStringSliceCmd(ctx, args...)
  1378. _ = c(ctx, cmd)
  1379. return cmd
  1380. }
  1381. func (c cmdable) SInterStore(ctx context.Context, destination string, keys ...string) *IntCmd {
  1382. args := make([]interface{}, 2+len(keys))
  1383. args[0] = "sinterstore"
  1384. args[1] = destination
  1385. for i, key := range keys {
  1386. args[2+i] = key
  1387. }
  1388. cmd := NewIntCmd(ctx, args...)
  1389. _ = c(ctx, cmd)
  1390. return cmd
  1391. }
  1392. func (c cmdable) SIsMember(ctx context.Context, key string, member interface{}) *BoolCmd {
  1393. cmd := NewBoolCmd(ctx, "sismember", key, member)
  1394. _ = c(ctx, cmd)
  1395. return cmd
  1396. }
  1397. // SMIsMember Redis `SMISMEMBER key member [member ...]` command.
  1398. func (c cmdable) SMIsMember(ctx context.Context, key string, members ...interface{}) *BoolSliceCmd {
  1399. args := make([]interface{}, 2, 2+len(members))
  1400. args[0] = "smismember"
  1401. args[1] = key
  1402. args = appendArgs(args, members)
  1403. cmd := NewBoolSliceCmd(ctx, args...)
  1404. _ = c(ctx, cmd)
  1405. return cmd
  1406. }
  1407. // SMembers Redis `SMEMBERS key` command output as a slice.
  1408. func (c cmdable) SMembers(ctx context.Context, key string) *StringSliceCmd {
  1409. cmd := NewStringSliceCmd(ctx, "smembers", key)
  1410. _ = c(ctx, cmd)
  1411. return cmd
  1412. }
  1413. // SMembersMap Redis `SMEMBERS key` command output as a map.
  1414. func (c cmdable) SMembersMap(ctx context.Context, key string) *StringStructMapCmd {
  1415. cmd := NewStringStructMapCmd(ctx, "smembers", key)
  1416. _ = c(ctx, cmd)
  1417. return cmd
  1418. }
  1419. func (c cmdable) SMove(ctx context.Context, source, destination string, member interface{}) *BoolCmd {
  1420. cmd := NewBoolCmd(ctx, "smove", source, destination, member)
  1421. _ = c(ctx, cmd)
  1422. return cmd
  1423. }
  1424. // SPop Redis `SPOP key` command.
  1425. func (c cmdable) SPop(ctx context.Context, key string) *StringCmd {
  1426. cmd := NewStringCmd(ctx, "spop", key)
  1427. _ = c(ctx, cmd)
  1428. return cmd
  1429. }
  1430. // SPopN Redis `SPOP key count` command.
  1431. func (c cmdable) SPopN(ctx context.Context, key string, count int64) *StringSliceCmd {
  1432. cmd := NewStringSliceCmd(ctx, "spop", key, count)
  1433. _ = c(ctx, cmd)
  1434. return cmd
  1435. }
  1436. // SRandMember Redis `SRANDMEMBER key` command.
  1437. func (c cmdable) SRandMember(ctx context.Context, key string) *StringCmd {
  1438. cmd := NewStringCmd(ctx, "srandmember", key)
  1439. _ = c(ctx, cmd)
  1440. return cmd
  1441. }
  1442. // SRandMemberN Redis `SRANDMEMBER key count` command.
  1443. func (c cmdable) SRandMemberN(ctx context.Context, key string, count int64) *StringSliceCmd {
  1444. cmd := NewStringSliceCmd(ctx, "srandmember", key, count)
  1445. _ = c(ctx, cmd)
  1446. return cmd
  1447. }
  1448. func (c cmdable) SRem(ctx context.Context, key string, members ...interface{}) *IntCmd {
  1449. args := make([]interface{}, 2, 2+len(members))
  1450. args[0] = "srem"
  1451. args[1] = key
  1452. args = appendArgs(args, members)
  1453. cmd := NewIntCmd(ctx, args...)
  1454. _ = c(ctx, cmd)
  1455. return cmd
  1456. }
  1457. func (c cmdable) SUnion(ctx context.Context, keys ...string) *StringSliceCmd {
  1458. args := make([]interface{}, 1+len(keys))
  1459. args[0] = "sunion"
  1460. for i, key := range keys {
  1461. args[1+i] = key
  1462. }
  1463. cmd := NewStringSliceCmd(ctx, args...)
  1464. _ = c(ctx, cmd)
  1465. return cmd
  1466. }
  1467. func (c cmdable) SUnionStore(ctx context.Context, destination string, keys ...string) *IntCmd {
  1468. args := make([]interface{}, 2+len(keys))
  1469. args[0] = "sunionstore"
  1470. args[1] = destination
  1471. for i, key := range keys {
  1472. args[2+i] = key
  1473. }
  1474. cmd := NewIntCmd(ctx, args...)
  1475. _ = c(ctx, cmd)
  1476. return cmd
  1477. }
  1478. //------------------------------------------------------------------------------
  1479. // XAddArgs accepts values in the following formats:
  1480. // - XAddArgs.Values = []interface{}{"key1", "value1", "key2", "value2"}
  1481. // - XAddArgs.Values = []string("key1", "value1", "key2", "value2")
  1482. // - XAddArgs.Values = map[string]interface{}{"key1": "value1", "key2": "value2"}
  1483. //
  1484. // Note that map will not preserve the order of key-value pairs.
  1485. // MaxLen/MaxLenApprox and MinID are in conflict, only one of them can be used.
  1486. type XAddArgs struct {
  1487. Stream string
  1488. NoMkStream bool
  1489. MaxLen int64 // MAXLEN N
  1490. // Deprecated: use MaxLen+Approx, remove in v9.
  1491. MaxLenApprox int64 // MAXLEN ~ N
  1492. MinID string
  1493. // Approx causes MaxLen and MinID to use "~" matcher (instead of "=").
  1494. Approx bool
  1495. Limit int64
  1496. ID string
  1497. Values interface{}
  1498. }
  1499. // XAdd a.Limit has a bug, please confirm it and use it.
  1500. // issue: https://github.com/redis/redis/issues/9046
  1501. func (c cmdable) XAdd(ctx context.Context, a *XAddArgs) *StringCmd {
  1502. args := make([]interface{}, 0, 11)
  1503. args = append(args, "xadd", a.Stream)
  1504. if a.NoMkStream {
  1505. args = append(args, "nomkstream")
  1506. }
  1507. switch {
  1508. case a.MaxLen > 0:
  1509. if a.Approx {
  1510. args = append(args, "maxlen", "~", a.MaxLen)
  1511. } else {
  1512. args = append(args, "maxlen", a.MaxLen)
  1513. }
  1514. case a.MaxLenApprox > 0:
  1515. // TODO remove in v9.
  1516. args = append(args, "maxlen", "~", a.MaxLenApprox)
  1517. case a.MinID != "":
  1518. if a.Approx {
  1519. args = append(args, "minid", "~", a.MinID)
  1520. } else {
  1521. args = append(args, "minid", a.MinID)
  1522. }
  1523. }
  1524. if a.Limit > 0 {
  1525. args = append(args, "limit", a.Limit)
  1526. }
  1527. if a.ID != "" {
  1528. args = append(args, a.ID)
  1529. } else {
  1530. args = append(args, "*")
  1531. }
  1532. args = appendArg(args, a.Values)
  1533. cmd := NewStringCmd(ctx, args...)
  1534. _ = c(ctx, cmd)
  1535. return cmd
  1536. }
  1537. func (c cmdable) XDel(ctx context.Context, stream string, ids ...string) *IntCmd {
  1538. args := []interface{}{"xdel", stream}
  1539. for _, id := range ids {
  1540. args = append(args, id)
  1541. }
  1542. cmd := NewIntCmd(ctx, args...)
  1543. _ = c(ctx, cmd)
  1544. return cmd
  1545. }
  1546. func (c cmdable) XLen(ctx context.Context, stream string) *IntCmd {
  1547. cmd := NewIntCmd(ctx, "xlen", stream)
  1548. _ = c(ctx, cmd)
  1549. return cmd
  1550. }
  1551. func (c cmdable) XRange(ctx context.Context, stream, start, stop string) *XMessageSliceCmd {
  1552. cmd := NewXMessageSliceCmd(ctx, "xrange", stream, start, stop)
  1553. _ = c(ctx, cmd)
  1554. return cmd
  1555. }
  1556. func (c cmdable) XRangeN(ctx context.Context, stream, start, stop string, count int64) *XMessageSliceCmd {
  1557. cmd := NewXMessageSliceCmd(ctx, "xrange", stream, start, stop, "count", count)
  1558. _ = c(ctx, cmd)
  1559. return cmd
  1560. }
  1561. func (c cmdable) XRevRange(ctx context.Context, stream, start, stop string) *XMessageSliceCmd {
  1562. cmd := NewXMessageSliceCmd(ctx, "xrevrange", stream, start, stop)
  1563. _ = c(ctx, cmd)
  1564. return cmd
  1565. }
  1566. func (c cmdable) XRevRangeN(ctx context.Context, stream, start, stop string, count int64) *XMessageSliceCmd {
  1567. cmd := NewXMessageSliceCmd(ctx, "xrevrange", stream, start, stop, "count", count)
  1568. _ = c(ctx, cmd)
  1569. return cmd
  1570. }
  1571. type XReadArgs struct {
  1572. Streams []string // list of streams and ids, e.g. stream1 stream2 id1 id2
  1573. Count int64
  1574. Block time.Duration
  1575. }
  1576. func (c cmdable) XRead(ctx context.Context, a *XReadArgs) *XStreamSliceCmd {
  1577. args := make([]interface{}, 0, 5+len(a.Streams))
  1578. args = append(args, "xread")
  1579. keyPos := int8(1)
  1580. if a.Count > 0 {
  1581. args = append(args, "count")
  1582. args = append(args, a.Count)
  1583. keyPos += 2
  1584. }
  1585. if a.Block >= 0 {
  1586. args = append(args, "block")
  1587. args = append(args, int64(a.Block/time.Millisecond))
  1588. keyPos += 2
  1589. }
  1590. args = append(args, "streams")
  1591. keyPos++
  1592. for _, s := range a.Streams {
  1593. args = append(args, s)
  1594. }
  1595. cmd := NewXStreamSliceCmd(ctx, args...)
  1596. if a.Block >= 0 {
  1597. cmd.setReadTimeout(a.Block)
  1598. }
  1599. cmd.setFirstKeyPos(keyPos)
  1600. _ = c(ctx, cmd)
  1601. return cmd
  1602. }
  1603. func (c cmdable) XReadStreams(ctx context.Context, streams ...string) *XStreamSliceCmd {
  1604. return c.XRead(ctx, &XReadArgs{
  1605. Streams: streams,
  1606. Block: -1,
  1607. })
  1608. }
  1609. func (c cmdable) XGroupCreate(ctx context.Context, stream, group, start string) *StatusCmd {
  1610. cmd := NewStatusCmd(ctx, "xgroup", "create", stream, group, start)
  1611. _ = c(ctx, cmd)
  1612. return cmd
  1613. }
  1614. func (c cmdable) XGroupCreateMkStream(ctx context.Context, stream, group, start string) *StatusCmd {
  1615. cmd := NewStatusCmd(ctx, "xgroup", "create", stream, group, start, "mkstream")
  1616. _ = c(ctx, cmd)
  1617. return cmd
  1618. }
  1619. func (c cmdable) XGroupSetID(ctx context.Context, stream, group, start string) *StatusCmd {
  1620. cmd := NewStatusCmd(ctx, "xgroup", "setid", stream, group, start)
  1621. _ = c(ctx, cmd)
  1622. return cmd
  1623. }
  1624. func (c cmdable) XGroupDestroy(ctx context.Context, stream, group string) *IntCmd {
  1625. cmd := NewIntCmd(ctx, "xgroup", "destroy", stream, group)
  1626. _ = c(ctx, cmd)
  1627. return cmd
  1628. }
  1629. func (c cmdable) XGroupCreateConsumer(ctx context.Context, stream, group, consumer string) *IntCmd {
  1630. cmd := NewIntCmd(ctx, "xgroup", "createconsumer", stream, group, consumer)
  1631. _ = c(ctx, cmd)
  1632. return cmd
  1633. }
  1634. func (c cmdable) XGroupDelConsumer(ctx context.Context, stream, group, consumer string) *IntCmd {
  1635. cmd := NewIntCmd(ctx, "xgroup", "delconsumer", stream, group, consumer)
  1636. _ = c(ctx, cmd)
  1637. return cmd
  1638. }
  1639. type XReadGroupArgs struct {
  1640. Group string
  1641. Consumer string
  1642. Streams []string // list of streams and ids, e.g. stream1 stream2 id1 id2
  1643. Count int64
  1644. Block time.Duration
  1645. NoAck bool
  1646. }
  1647. func (c cmdable) XReadGroup(ctx context.Context, a *XReadGroupArgs) *XStreamSliceCmd {
  1648. args := make([]interface{}, 0, 8+len(a.Streams))
  1649. args = append(args, "xreadgroup", "group", a.Group, a.Consumer)
  1650. keyPos := int8(4)
  1651. if a.Count > 0 {
  1652. args = append(args, "count", a.Count)
  1653. keyPos += 2
  1654. }
  1655. if a.Block >= 0 {
  1656. args = append(args, "block", int64(a.Block/time.Millisecond))
  1657. keyPos += 2
  1658. }
  1659. if a.NoAck {
  1660. args = append(args, "noack")
  1661. keyPos++
  1662. }
  1663. args = append(args, "streams")
  1664. keyPos++
  1665. for _, s := range a.Streams {
  1666. args = append(args, s)
  1667. }
  1668. cmd := NewXStreamSliceCmd(ctx, args...)
  1669. if a.Block >= 0 {
  1670. cmd.setReadTimeout(a.Block)
  1671. }
  1672. cmd.setFirstKeyPos(keyPos)
  1673. _ = c(ctx, cmd)
  1674. return cmd
  1675. }
  1676. func (c cmdable) XAck(ctx context.Context, stream, group string, ids ...string) *IntCmd {
  1677. args := []interface{}{"xack", stream, group}
  1678. for _, id := range ids {
  1679. args = append(args, id)
  1680. }
  1681. cmd := NewIntCmd(ctx, args...)
  1682. _ = c(ctx, cmd)
  1683. return cmd
  1684. }
  1685. func (c cmdable) XPending(ctx context.Context, stream, group string) *XPendingCmd {
  1686. cmd := NewXPendingCmd(ctx, "xpending", stream, group)
  1687. _ = c(ctx, cmd)
  1688. return cmd
  1689. }
  1690. type XPendingExtArgs struct {
  1691. Stream string
  1692. Group string
  1693. Idle time.Duration
  1694. Start string
  1695. End string
  1696. Count int64
  1697. Consumer string
  1698. }
  1699. func (c cmdable) XPendingExt(ctx context.Context, a *XPendingExtArgs) *XPendingExtCmd {
  1700. args := make([]interface{}, 0, 9)
  1701. args = append(args, "xpending", a.Stream, a.Group)
  1702. if a.Idle != 0 {
  1703. args = append(args, "idle", formatMs(ctx, a.Idle))
  1704. }
  1705. args = append(args, a.Start, a.End, a.Count)
  1706. if a.Consumer != "" {
  1707. args = append(args, a.Consumer)
  1708. }
  1709. cmd := NewXPendingExtCmd(ctx, args...)
  1710. _ = c(ctx, cmd)
  1711. return cmd
  1712. }
  1713. type XAutoClaimArgs struct {
  1714. Stream string
  1715. Group string
  1716. MinIdle time.Duration
  1717. Start string
  1718. Count int64
  1719. Consumer string
  1720. }
  1721. func (c cmdable) XAutoClaim(ctx context.Context, a *XAutoClaimArgs) *XAutoClaimCmd {
  1722. args := xAutoClaimArgs(ctx, a)
  1723. cmd := NewXAutoClaimCmd(ctx, args...)
  1724. _ = c(ctx, cmd)
  1725. return cmd
  1726. }
  1727. func (c cmdable) XAutoClaimJustID(ctx context.Context, a *XAutoClaimArgs) *XAutoClaimJustIDCmd {
  1728. args := xAutoClaimArgs(ctx, a)
  1729. args = append(args, "justid")
  1730. cmd := NewXAutoClaimJustIDCmd(ctx, args...)
  1731. _ = c(ctx, cmd)
  1732. return cmd
  1733. }
  1734. func xAutoClaimArgs(ctx context.Context, a *XAutoClaimArgs) []interface{} {
  1735. args := make([]interface{}, 0, 9)
  1736. args = append(args, "xautoclaim", a.Stream, a.Group, a.Consumer, formatMs(ctx, a.MinIdle), a.Start)
  1737. if a.Count > 0 {
  1738. args = append(args, "count", a.Count)
  1739. }
  1740. return args
  1741. }
  1742. type XClaimArgs struct {
  1743. Stream string
  1744. Group string
  1745. Consumer string
  1746. MinIdle time.Duration
  1747. Messages []string
  1748. }
  1749. func (c cmdable) XClaim(ctx context.Context, a *XClaimArgs) *XMessageSliceCmd {
  1750. args := xClaimArgs(a)
  1751. cmd := NewXMessageSliceCmd(ctx, args...)
  1752. _ = c(ctx, cmd)
  1753. return cmd
  1754. }
  1755. func (c cmdable) XClaimJustID(ctx context.Context, a *XClaimArgs) *StringSliceCmd {
  1756. args := xClaimArgs(a)
  1757. args = append(args, "justid")
  1758. cmd := NewStringSliceCmd(ctx, args...)
  1759. _ = c(ctx, cmd)
  1760. return cmd
  1761. }
  1762. func xClaimArgs(a *XClaimArgs) []interface{} {
  1763. args := make([]interface{}, 0, 4+len(a.Messages))
  1764. args = append(args,
  1765. "xclaim",
  1766. a.Stream,
  1767. a.Group, a.Consumer,
  1768. int64(a.MinIdle/time.Millisecond))
  1769. for _, id := range a.Messages {
  1770. args = append(args, id)
  1771. }
  1772. return args
  1773. }
  1774. // xTrim If approx is true, add the "~" parameter, otherwise it is the default "=" (redis default).
  1775. // example:
  1776. // XTRIM key MAXLEN/MINID threshold LIMIT limit.
  1777. // XTRIM key MAXLEN/MINID ~ threshold LIMIT limit.
  1778. // The redis-server version is lower than 6.2, please set limit to 0.
  1779. func (c cmdable) xTrim(
  1780. ctx context.Context, key, strategy string,
  1781. approx bool, threshold interface{}, limit int64,
  1782. ) *IntCmd {
  1783. args := make([]interface{}, 0, 7)
  1784. args = append(args, "xtrim", key, strategy)
  1785. if approx {
  1786. args = append(args, "~")
  1787. }
  1788. args = append(args, threshold)
  1789. if limit > 0 {
  1790. args = append(args, "limit", limit)
  1791. }
  1792. cmd := NewIntCmd(ctx, args...)
  1793. _ = c(ctx, cmd)
  1794. return cmd
  1795. }
  1796. // Deprecated: use XTrimMaxLen, remove in v9.
  1797. func (c cmdable) XTrim(ctx context.Context, key string, maxLen int64) *IntCmd {
  1798. return c.xTrim(ctx, key, "maxlen", false, maxLen, 0)
  1799. }
  1800. // Deprecated: use XTrimMaxLenApprox, remove in v9.
  1801. func (c cmdable) XTrimApprox(ctx context.Context, key string, maxLen int64) *IntCmd {
  1802. return c.xTrim(ctx, key, "maxlen", true, maxLen, 0)
  1803. }
  1804. // XTrimMaxLen No `~` rules are used, `limit` cannot be used.
  1805. // cmd: XTRIM key MAXLEN maxLen
  1806. func (c cmdable) XTrimMaxLen(ctx context.Context, key string, maxLen int64) *IntCmd {
  1807. return c.xTrim(ctx, key, "maxlen", false, maxLen, 0)
  1808. }
  1809. // XTrimMaxLenApprox LIMIT has a bug, please confirm it and use it.
  1810. // issue: https://github.com/redis/redis/issues/9046
  1811. // cmd: XTRIM key MAXLEN ~ maxLen LIMIT limit
  1812. func (c cmdable) XTrimMaxLenApprox(ctx context.Context, key string, maxLen, limit int64) *IntCmd {
  1813. return c.xTrim(ctx, key, "maxlen", true, maxLen, limit)
  1814. }
  1815. // XTrimMinID No `~` rules are used, `limit` cannot be used.
  1816. // cmd: XTRIM key MINID minID
  1817. func (c cmdable) XTrimMinID(ctx context.Context, key string, minID string) *IntCmd {
  1818. return c.xTrim(ctx, key, "minid", false, minID, 0)
  1819. }
  1820. // XTrimMinIDApprox LIMIT has a bug, please confirm it and use it.
  1821. // issue: https://github.com/redis/redis/issues/9046
  1822. // cmd: XTRIM key MINID ~ minID LIMIT limit
  1823. func (c cmdable) XTrimMinIDApprox(ctx context.Context, key string, minID string, limit int64) *IntCmd {
  1824. return c.xTrim(ctx, key, "minid", true, minID, limit)
  1825. }
  1826. func (c cmdable) XInfoConsumers(ctx context.Context, key string, group string) *XInfoConsumersCmd {
  1827. cmd := NewXInfoConsumersCmd(ctx, key, group)
  1828. _ = c(ctx, cmd)
  1829. return cmd
  1830. }
  1831. func (c cmdable) XInfoGroups(ctx context.Context, key string) *XInfoGroupsCmd {
  1832. cmd := NewXInfoGroupsCmd(ctx, key)
  1833. _ = c(ctx, cmd)
  1834. return cmd
  1835. }
  1836. func (c cmdable) XInfoStream(ctx context.Context, key string) *XInfoStreamCmd {
  1837. cmd := NewXInfoStreamCmd(ctx, key)
  1838. _ = c(ctx, cmd)
  1839. return cmd
  1840. }
  1841. // XInfoStreamFull XINFO STREAM FULL [COUNT count]
  1842. // redis-server >= 6.0.
  1843. func (c cmdable) XInfoStreamFull(ctx context.Context, key string, count int) *XInfoStreamFullCmd {
  1844. args := make([]interface{}, 0, 6)
  1845. args = append(args, "xinfo", "stream", key, "full")
  1846. if count > 0 {
  1847. args = append(args, "count", count)
  1848. }
  1849. cmd := NewXInfoStreamFullCmd(ctx, args...)
  1850. _ = c(ctx, cmd)
  1851. return cmd
  1852. }
  1853. //------------------------------------------------------------------------------
  1854. // Z represents sorted set member.
  1855. type Z struct {
  1856. Score float64
  1857. Member interface{}
  1858. }
  1859. // ZWithKey represents sorted set member including the name of the key where it was popped.
  1860. type ZWithKey struct {
  1861. Z
  1862. Key string
  1863. }
  1864. // ZStore is used as an arg to ZInter/ZInterStore and ZUnion/ZUnionStore.
  1865. type ZStore struct {
  1866. Keys []string
  1867. Weights []float64
  1868. // Can be SUM, MIN or MAX.
  1869. Aggregate string
  1870. }
  1871. func (z ZStore) len() (n int) {
  1872. n = len(z.Keys)
  1873. if len(z.Weights) > 0 {
  1874. n += 1 + len(z.Weights)
  1875. }
  1876. if z.Aggregate != "" {
  1877. n += 2
  1878. }
  1879. return n
  1880. }
  1881. func (z ZStore) appendArgs(args []interface{}) []interface{} {
  1882. for _, key := range z.Keys {
  1883. args = append(args, key)
  1884. }
  1885. if len(z.Weights) > 0 {
  1886. args = append(args, "weights")
  1887. for _, weights := range z.Weights {
  1888. args = append(args, weights)
  1889. }
  1890. }
  1891. if z.Aggregate != "" {
  1892. args = append(args, "aggregate", z.Aggregate)
  1893. }
  1894. return args
  1895. }
  1896. // BZPopMax Redis `BZPOPMAX key [key ...] timeout` command.
  1897. func (c cmdable) BZPopMax(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd {
  1898. args := make([]interface{}, 1+len(keys)+1)
  1899. args[0] = "bzpopmax"
  1900. for i, key := range keys {
  1901. args[1+i] = key
  1902. }
  1903. args[len(args)-1] = formatSec(ctx, timeout)
  1904. cmd := NewZWithKeyCmd(ctx, args...)
  1905. cmd.setReadTimeout(timeout)
  1906. _ = c(ctx, cmd)
  1907. return cmd
  1908. }
  1909. // BZPopMin Redis `BZPOPMIN key [key ...] timeout` command.
  1910. func (c cmdable) BZPopMin(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd {
  1911. args := make([]interface{}, 1+len(keys)+1)
  1912. args[0] = "bzpopmin"
  1913. for i, key := range keys {
  1914. args[1+i] = key
  1915. }
  1916. args[len(args)-1] = formatSec(ctx, timeout)
  1917. cmd := NewZWithKeyCmd(ctx, args...)
  1918. cmd.setReadTimeout(timeout)
  1919. _ = c(ctx, cmd)
  1920. return cmd
  1921. }
  1922. // ZAddArgs WARN: The GT, LT and NX options are mutually exclusive.
  1923. type ZAddArgs struct {
  1924. NX bool
  1925. XX bool
  1926. LT bool
  1927. GT bool
  1928. Ch bool
  1929. Members []Z
  1930. }
  1931. func (c cmdable) zAddArgs(key string, args ZAddArgs, incr bool) []interface{} {
  1932. a := make([]interface{}, 0, 6+2*len(args.Members))
  1933. a = append(a, "zadd", key)
  1934. // The GT, LT and NX options are mutually exclusive.
  1935. if args.NX {
  1936. a = append(a, "nx")
  1937. } else {
  1938. if args.XX {
  1939. a = append(a, "xx")
  1940. }
  1941. if args.GT {
  1942. a = append(a, "gt")
  1943. } else if args.LT {
  1944. a = append(a, "lt")
  1945. }
  1946. }
  1947. if args.Ch {
  1948. a = append(a, "ch")
  1949. }
  1950. if incr {
  1951. a = append(a, "incr")
  1952. }
  1953. for _, m := range args.Members {
  1954. a = append(a, m.Score)
  1955. a = append(a, m.Member)
  1956. }
  1957. return a
  1958. }
  1959. func (c cmdable) ZAddArgs(ctx context.Context, key string, args ZAddArgs) *IntCmd {
  1960. cmd := NewIntCmd(ctx, c.zAddArgs(key, args, false)...)
  1961. _ = c(ctx, cmd)
  1962. return cmd
  1963. }
  1964. func (c cmdable) ZAddArgsIncr(ctx context.Context, key string, args ZAddArgs) *FloatCmd {
  1965. cmd := NewFloatCmd(ctx, c.zAddArgs(key, args, true)...)
  1966. _ = c(ctx, cmd)
  1967. return cmd
  1968. }
  1969. // TODO: Compatible with v8 api, will be removed in v9.
  1970. func (c cmdable) zAdd(ctx context.Context, key string, args ZAddArgs, members ...*Z) *IntCmd {
  1971. args.Members = make([]Z, len(members))
  1972. for i, m := range members {
  1973. args.Members[i] = *m
  1974. }
  1975. cmd := NewIntCmd(ctx, c.zAddArgs(key, args, false)...)
  1976. _ = c(ctx, cmd)
  1977. return cmd
  1978. }
  1979. // ZAdd Redis `ZADD key score member [score member ...]` command.
  1980. func (c cmdable) ZAdd(ctx context.Context, key string, members ...*Z) *IntCmd {
  1981. return c.zAdd(ctx, key, ZAddArgs{}, members...)
  1982. }
  1983. // ZAddNX Redis `ZADD key NX score member [score member ...]` command.
  1984. func (c cmdable) ZAddNX(ctx context.Context, key string, members ...*Z) *IntCmd {
  1985. return c.zAdd(ctx, key, ZAddArgs{
  1986. NX: true,
  1987. }, members...)
  1988. }
  1989. // ZAddXX Redis `ZADD key XX score member [score member ...]` command.
  1990. func (c cmdable) ZAddXX(ctx context.Context, key string, members ...*Z) *IntCmd {
  1991. return c.zAdd(ctx, key, ZAddArgs{
  1992. XX: true,
  1993. }, members...)
  1994. }
  1995. // ZAddCh Redis `ZADD key CH score member [score member ...]` command.
  1996. // Deprecated: Use
  1997. // client.ZAddArgs(ctx, ZAddArgs{
  1998. // Ch: true,
  1999. // Members: []Z,
  2000. // })
  2001. // remove in v9.
  2002. func (c cmdable) ZAddCh(ctx context.Context, key string, members ...*Z) *IntCmd {
  2003. return c.zAdd(ctx, key, ZAddArgs{
  2004. Ch: true,
  2005. }, members...)
  2006. }
  2007. // ZAddNXCh Redis `ZADD key NX CH score member [score member ...]` command.
  2008. // Deprecated: Use
  2009. // client.ZAddArgs(ctx, ZAddArgs{
  2010. // NX: true,
  2011. // Ch: true,
  2012. // Members: []Z,
  2013. // })
  2014. // remove in v9.
  2015. func (c cmdable) ZAddNXCh(ctx context.Context, key string, members ...*Z) *IntCmd {
  2016. return c.zAdd(ctx, key, ZAddArgs{
  2017. NX: true,
  2018. Ch: true,
  2019. }, members...)
  2020. }
  2021. // ZAddXXCh Redis `ZADD key XX CH score member [score member ...]` command.
  2022. // Deprecated: Use
  2023. // client.ZAddArgs(ctx, ZAddArgs{
  2024. // XX: true,
  2025. // Ch: true,
  2026. // Members: []Z,
  2027. // })
  2028. // remove in v9.
  2029. func (c cmdable) ZAddXXCh(ctx context.Context, key string, members ...*Z) *IntCmd {
  2030. return c.zAdd(ctx, key, ZAddArgs{
  2031. XX: true,
  2032. Ch: true,
  2033. }, members...)
  2034. }
  2035. // ZIncr Redis `ZADD key INCR score member` command.
  2036. // Deprecated: Use
  2037. // client.ZAddArgsIncr(ctx, ZAddArgs{
  2038. // Members: []Z,
  2039. // })
  2040. // remove in v9.
  2041. func (c cmdable) ZIncr(ctx context.Context, key string, member *Z) *FloatCmd {
  2042. return c.ZAddArgsIncr(ctx, key, ZAddArgs{
  2043. Members: []Z{*member},
  2044. })
  2045. }
  2046. // ZIncrNX Redis `ZADD key NX INCR score member` command.
  2047. // Deprecated: Use
  2048. // client.ZAddArgsIncr(ctx, ZAddArgs{
  2049. // NX: true,
  2050. // Members: []Z,
  2051. // })
  2052. // remove in v9.
  2053. func (c cmdable) ZIncrNX(ctx context.Context, key string, member *Z) *FloatCmd {
  2054. return c.ZAddArgsIncr(ctx, key, ZAddArgs{
  2055. NX: true,
  2056. Members: []Z{*member},
  2057. })
  2058. }
  2059. // ZIncrXX Redis `ZADD key XX INCR score member` command.
  2060. // Deprecated: Use
  2061. // client.ZAddArgsIncr(ctx, ZAddArgs{
  2062. // XX: true,
  2063. // Members: []Z,
  2064. // })
  2065. // remove in v9.
  2066. func (c cmdable) ZIncrXX(ctx context.Context, key string, member *Z) *FloatCmd {
  2067. return c.ZAddArgsIncr(ctx, key, ZAddArgs{
  2068. XX: true,
  2069. Members: []Z{*member},
  2070. })
  2071. }
  2072. func (c cmdable) ZCard(ctx context.Context, key string) *IntCmd {
  2073. cmd := NewIntCmd(ctx, "zcard", key)
  2074. _ = c(ctx, cmd)
  2075. return cmd
  2076. }
  2077. func (c cmdable) ZCount(ctx context.Context, key, min, max string) *IntCmd {
  2078. cmd := NewIntCmd(ctx, "zcount", key, min, max)
  2079. _ = c(ctx, cmd)
  2080. return cmd
  2081. }
  2082. func (c cmdable) ZLexCount(ctx context.Context, key, min, max string) *IntCmd {
  2083. cmd := NewIntCmd(ctx, "zlexcount", key, min, max)
  2084. _ = c(ctx, cmd)
  2085. return cmd
  2086. }
  2087. func (c cmdable) ZIncrBy(ctx context.Context, key string, increment float64, member string) *FloatCmd {
  2088. cmd := NewFloatCmd(ctx, "zincrby", key, increment, member)
  2089. _ = c(ctx, cmd)
  2090. return cmd
  2091. }
  2092. func (c cmdable) ZInterStore(ctx context.Context, destination string, store *ZStore) *IntCmd {
  2093. args := make([]interface{}, 0, 3+store.len())
  2094. args = append(args, "zinterstore", destination, len(store.Keys))
  2095. args = store.appendArgs(args)
  2096. cmd := NewIntCmd(ctx, args...)
  2097. cmd.setFirstKeyPos(3)
  2098. _ = c(ctx, cmd)
  2099. return cmd
  2100. }
  2101. func (c cmdable) ZInter(ctx context.Context, store *ZStore) *StringSliceCmd {
  2102. args := make([]interface{}, 0, 2+store.len())
  2103. args = append(args, "zinter", len(store.Keys))
  2104. args = store.appendArgs(args)
  2105. cmd := NewStringSliceCmd(ctx, args...)
  2106. cmd.setFirstKeyPos(2)
  2107. _ = c(ctx, cmd)
  2108. return cmd
  2109. }
  2110. func (c cmdable) ZInterWithScores(ctx context.Context, store *ZStore) *ZSliceCmd {
  2111. args := make([]interface{}, 0, 3+store.len())
  2112. args = append(args, "zinter", len(store.Keys))
  2113. args = store.appendArgs(args)
  2114. args = append(args, "withscores")
  2115. cmd := NewZSliceCmd(ctx, args...)
  2116. cmd.setFirstKeyPos(2)
  2117. _ = c(ctx, cmd)
  2118. return cmd
  2119. }
  2120. func (c cmdable) ZMScore(ctx context.Context, key string, members ...string) *FloatSliceCmd {
  2121. args := make([]interface{}, 2+len(members))
  2122. args[0] = "zmscore"
  2123. args[1] = key
  2124. for i, member := range members {
  2125. args[2+i] = member
  2126. }
  2127. cmd := NewFloatSliceCmd(ctx, args...)
  2128. _ = c(ctx, cmd)
  2129. return cmd
  2130. }
  2131. func (c cmdable) ZPopMax(ctx context.Context, key string, count ...int64) *ZSliceCmd {
  2132. args := []interface{}{
  2133. "zpopmax",
  2134. key,
  2135. }
  2136. switch len(count) {
  2137. case 0:
  2138. break
  2139. case 1:
  2140. args = append(args, count[0])
  2141. default:
  2142. panic("too many arguments")
  2143. }
  2144. cmd := NewZSliceCmd(ctx, args...)
  2145. _ = c(ctx, cmd)
  2146. return cmd
  2147. }
  2148. func (c cmdable) ZPopMin(ctx context.Context, key string, count ...int64) *ZSliceCmd {
  2149. args := []interface{}{
  2150. "zpopmin",
  2151. key,
  2152. }
  2153. switch len(count) {
  2154. case 0:
  2155. break
  2156. case 1:
  2157. args = append(args, count[0])
  2158. default:
  2159. panic("too many arguments")
  2160. }
  2161. cmd := NewZSliceCmd(ctx, args...)
  2162. _ = c(ctx, cmd)
  2163. return cmd
  2164. }
  2165. // ZRangeArgs is all the options of the ZRange command.
  2166. // In version> 6.2.0, you can replace the(cmd):
  2167. // ZREVRANGE,
  2168. // ZRANGEBYSCORE,
  2169. // ZREVRANGEBYSCORE,
  2170. // ZRANGEBYLEX,
  2171. // ZREVRANGEBYLEX.
  2172. // Please pay attention to your redis-server version.
  2173. //
  2174. // Rev, ByScore, ByLex and Offset+Count options require redis-server 6.2.0 and higher.
  2175. type ZRangeArgs struct {
  2176. Key string
  2177. // When the ByScore option is provided, the open interval(exclusive) can be set.
  2178. // By default, the score intervals specified by <Start> and <Stop> are closed (inclusive).
  2179. // It is similar to the deprecated(6.2.0+) ZRangeByScore command.
  2180. // For example:
  2181. // ZRangeArgs{
  2182. // Key: "example-key",
  2183. // Start: "(3",
  2184. // Stop: 8,
  2185. // ByScore: true,
  2186. // }
  2187. // cmd: "ZRange example-key (3 8 ByScore" (3 < score <= 8).
  2188. //
  2189. // For the ByLex option, it is similar to the deprecated(6.2.0+) ZRangeByLex command.
  2190. // You can set the <Start> and <Stop> options as follows:
  2191. // ZRangeArgs{
  2192. // Key: "example-key",
  2193. // Start: "[abc",
  2194. // Stop: "(def",
  2195. // ByLex: true,
  2196. // }
  2197. // cmd: "ZRange example-key [abc (def ByLex"
  2198. //
  2199. // For normal cases (ByScore==false && ByLex==false), <Start> and <Stop> should be set to the index range (int).
  2200. // You can read the documentation for more information: https://redis.io/commands/zrange
  2201. Start interface{}
  2202. Stop interface{}
  2203. // The ByScore and ByLex options are mutually exclusive.
  2204. ByScore bool
  2205. ByLex bool
  2206. Rev bool
  2207. // limit offset count.
  2208. Offset int64
  2209. Count int64
  2210. }
  2211. func (z ZRangeArgs) appendArgs(args []interface{}) []interface{} {
  2212. // For Rev+ByScore/ByLex, we need to adjust the position of <Start> and <Stop>.
  2213. if z.Rev && (z.ByScore || z.ByLex) {
  2214. args = append(args, z.Key, z.Stop, z.Start)
  2215. } else {
  2216. args = append(args, z.Key, z.Start, z.Stop)
  2217. }
  2218. if z.ByScore {
  2219. args = append(args, "byscore")
  2220. } else if z.ByLex {
  2221. args = append(args, "bylex")
  2222. }
  2223. if z.Rev {
  2224. args = append(args, "rev")
  2225. }
  2226. if z.Offset != 0 || z.Count != 0 {
  2227. args = append(args, "limit", z.Offset, z.Count)
  2228. }
  2229. return args
  2230. }
  2231. func (c cmdable) ZRangeArgs(ctx context.Context, z ZRangeArgs) *StringSliceCmd {
  2232. args := make([]interface{}, 0, 9)
  2233. args = append(args, "zrange")
  2234. args = z.appendArgs(args)
  2235. cmd := NewStringSliceCmd(ctx, args...)
  2236. _ = c(ctx, cmd)
  2237. return cmd
  2238. }
  2239. func (c cmdable) ZRangeArgsWithScores(ctx context.Context, z ZRangeArgs) *ZSliceCmd {
  2240. args := make([]interface{}, 0, 10)
  2241. args = append(args, "zrange")
  2242. args = z.appendArgs(args)
  2243. args = append(args, "withscores")
  2244. cmd := NewZSliceCmd(ctx, args...)
  2245. _ = c(ctx, cmd)
  2246. return cmd
  2247. }
  2248. func (c cmdable) ZRange(ctx context.Context, key string, start, stop int64) *StringSliceCmd {
  2249. return c.ZRangeArgs(ctx, ZRangeArgs{
  2250. Key: key,
  2251. Start: start,
  2252. Stop: stop,
  2253. })
  2254. }
  2255. func (c cmdable) ZRangeWithScores(ctx context.Context, key string, start, stop int64) *ZSliceCmd {
  2256. return c.ZRangeArgsWithScores(ctx, ZRangeArgs{
  2257. Key: key,
  2258. Start: start,
  2259. Stop: stop,
  2260. })
  2261. }
  2262. type ZRangeBy struct {
  2263. Min, Max string
  2264. Offset, Count int64
  2265. }
  2266. func (c cmdable) zRangeBy(ctx context.Context, zcmd, key string, opt *ZRangeBy, withScores bool) *StringSliceCmd {
  2267. args := []interface{}{zcmd, key, opt.Min, opt.Max}
  2268. if withScores {
  2269. args = append(args, "withscores")
  2270. }
  2271. if opt.Offset != 0 || opt.Count != 0 {
  2272. args = append(
  2273. args,
  2274. "limit",
  2275. opt.Offset,
  2276. opt.Count,
  2277. )
  2278. }
  2279. cmd := NewStringSliceCmd(ctx, args...)
  2280. _ = c(ctx, cmd)
  2281. return cmd
  2282. }
  2283. func (c cmdable) ZRangeByScore(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd {
  2284. return c.zRangeBy(ctx, "zrangebyscore", key, opt, false)
  2285. }
  2286. func (c cmdable) ZRangeByLex(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd {
  2287. return c.zRangeBy(ctx, "zrangebylex", key, opt, false)
  2288. }
  2289. func (c cmdable) ZRangeByScoreWithScores(ctx context.Context, key string, opt *ZRangeBy) *ZSliceCmd {
  2290. args := []interface{}{"zrangebyscore", key, opt.Min, opt.Max, "withscores"}
  2291. if opt.Offset != 0 || opt.Count != 0 {
  2292. args = append(
  2293. args,
  2294. "limit",
  2295. opt.Offset,
  2296. opt.Count,
  2297. )
  2298. }
  2299. cmd := NewZSliceCmd(ctx, args...)
  2300. _ = c(ctx, cmd)
  2301. return cmd
  2302. }
  2303. func (c cmdable) ZRangeStore(ctx context.Context, dst string, z ZRangeArgs) *IntCmd {
  2304. args := make([]interface{}, 0, 10)
  2305. args = append(args, "zrangestore", dst)
  2306. args = z.appendArgs(args)
  2307. cmd := NewIntCmd(ctx, args...)
  2308. _ = c(ctx, cmd)
  2309. return cmd
  2310. }
  2311. func (c cmdable) ZRank(ctx context.Context, key, member string) *IntCmd {
  2312. cmd := NewIntCmd(ctx, "zrank", key, member)
  2313. _ = c(ctx, cmd)
  2314. return cmd
  2315. }
  2316. func (c cmdable) ZRem(ctx context.Context, key string, members ...interface{}) *IntCmd {
  2317. args := make([]interface{}, 2, 2+len(members))
  2318. args[0] = "zrem"
  2319. args[1] = key
  2320. args = appendArgs(args, members)
  2321. cmd := NewIntCmd(ctx, args...)
  2322. _ = c(ctx, cmd)
  2323. return cmd
  2324. }
  2325. func (c cmdable) ZRemRangeByRank(ctx context.Context, key string, start, stop int64) *IntCmd {
  2326. cmd := NewIntCmd(
  2327. ctx,
  2328. "zremrangebyrank",
  2329. key,
  2330. start,
  2331. stop,
  2332. )
  2333. _ = c(ctx, cmd)
  2334. return cmd
  2335. }
  2336. func (c cmdable) ZRemRangeByScore(ctx context.Context, key, min, max string) *IntCmd {
  2337. cmd := NewIntCmd(ctx, "zremrangebyscore", key, min, max)
  2338. _ = c(ctx, cmd)
  2339. return cmd
  2340. }
  2341. func (c cmdable) ZRemRangeByLex(ctx context.Context, key, min, max string) *IntCmd {
  2342. cmd := NewIntCmd(ctx, "zremrangebylex", key, min, max)
  2343. _ = c(ctx, cmd)
  2344. return cmd
  2345. }
  2346. func (c cmdable) ZRevRange(ctx context.Context, key string, start, stop int64) *StringSliceCmd {
  2347. cmd := NewStringSliceCmd(ctx, "zrevrange", key, start, stop)
  2348. _ = c(ctx, cmd)
  2349. return cmd
  2350. }
  2351. func (c cmdable) ZRevRangeWithScores(ctx context.Context, key string, start, stop int64) *ZSliceCmd {
  2352. cmd := NewZSliceCmd(ctx, "zrevrange", key, start, stop, "withscores")
  2353. _ = c(ctx, cmd)
  2354. return cmd
  2355. }
  2356. func (c cmdable) zRevRangeBy(ctx context.Context, zcmd, key string, opt *ZRangeBy) *StringSliceCmd {
  2357. args := []interface{}{zcmd, key, opt.Max, opt.Min}
  2358. if opt.Offset != 0 || opt.Count != 0 {
  2359. args = append(
  2360. args,
  2361. "limit",
  2362. opt.Offset,
  2363. opt.Count,
  2364. )
  2365. }
  2366. cmd := NewStringSliceCmd(ctx, args...)
  2367. _ = c(ctx, cmd)
  2368. return cmd
  2369. }
  2370. func (c cmdable) ZRevRangeByScore(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd {
  2371. return c.zRevRangeBy(ctx, "zrevrangebyscore", key, opt)
  2372. }
  2373. func (c cmdable) ZRevRangeByLex(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd {
  2374. return c.zRevRangeBy(ctx, "zrevrangebylex", key, opt)
  2375. }
  2376. func (c cmdable) ZRevRangeByScoreWithScores(ctx context.Context, key string, opt *ZRangeBy) *ZSliceCmd {
  2377. args := []interface{}{"zrevrangebyscore", key, opt.Max, opt.Min, "withscores"}
  2378. if opt.Offset != 0 || opt.Count != 0 {
  2379. args = append(
  2380. args,
  2381. "limit",
  2382. opt.Offset,
  2383. opt.Count,
  2384. )
  2385. }
  2386. cmd := NewZSliceCmd(ctx, args...)
  2387. _ = c(ctx, cmd)
  2388. return cmd
  2389. }
  2390. func (c cmdable) ZRevRank(ctx context.Context, key, member string) *IntCmd {
  2391. cmd := NewIntCmd(ctx, "zrevrank", key, member)
  2392. _ = c(ctx, cmd)
  2393. return cmd
  2394. }
  2395. func (c cmdable) ZScore(ctx context.Context, key, member string) *FloatCmd {
  2396. cmd := NewFloatCmd(ctx, "zscore", key, member)
  2397. _ = c(ctx, cmd)
  2398. return cmd
  2399. }
  2400. func (c cmdable) ZUnion(ctx context.Context, store ZStore) *StringSliceCmd {
  2401. args := make([]interface{}, 0, 2+store.len())
  2402. args = append(args, "zunion", len(store.Keys))
  2403. args = store.appendArgs(args)
  2404. cmd := NewStringSliceCmd(ctx, args...)
  2405. cmd.setFirstKeyPos(2)
  2406. _ = c(ctx, cmd)
  2407. return cmd
  2408. }
  2409. func (c cmdable) ZUnionWithScores(ctx context.Context, store ZStore) *ZSliceCmd {
  2410. args := make([]interface{}, 0, 3+store.len())
  2411. args = append(args, "zunion", len(store.Keys))
  2412. args = store.appendArgs(args)
  2413. args = append(args, "withscores")
  2414. cmd := NewZSliceCmd(ctx, args...)
  2415. cmd.setFirstKeyPos(2)
  2416. _ = c(ctx, cmd)
  2417. return cmd
  2418. }
  2419. func (c cmdable) ZUnionStore(ctx context.Context, dest string, store *ZStore) *IntCmd {
  2420. args := make([]interface{}, 0, 3+store.len())
  2421. args = append(args, "zunionstore", dest, len(store.Keys))
  2422. args = store.appendArgs(args)
  2423. cmd := NewIntCmd(ctx, args...)
  2424. cmd.setFirstKeyPos(3)
  2425. _ = c(ctx, cmd)
  2426. return cmd
  2427. }
  2428. // ZRandMember redis-server version >= 6.2.0.
  2429. func (c cmdable) ZRandMember(ctx context.Context, key string, count int, withScores bool) *StringSliceCmd {
  2430. args := make([]interface{}, 0, 4)
  2431. // Although count=0 is meaningless, redis accepts count=0.
  2432. args = append(args, "zrandmember", key, count)
  2433. if withScores {
  2434. args = append(args, "withscores")
  2435. }
  2436. cmd := NewStringSliceCmd(ctx, args...)
  2437. _ = c(ctx, cmd)
  2438. return cmd
  2439. }
  2440. // ZDiff redis-server version >= 6.2.0.
  2441. func (c cmdable) ZDiff(ctx context.Context, keys ...string) *StringSliceCmd {
  2442. args := make([]interface{}, 2+len(keys))
  2443. args[0] = "zdiff"
  2444. args[1] = len(keys)
  2445. for i, key := range keys {
  2446. args[i+2] = key
  2447. }
  2448. cmd := NewStringSliceCmd(ctx, args...)
  2449. cmd.setFirstKeyPos(2)
  2450. _ = c(ctx, cmd)
  2451. return cmd
  2452. }
  2453. // ZDiffWithScores redis-server version >= 6.2.0.
  2454. func (c cmdable) ZDiffWithScores(ctx context.Context, keys ...string) *ZSliceCmd {
  2455. args := make([]interface{}, 3+len(keys))
  2456. args[0] = "zdiff"
  2457. args[1] = len(keys)
  2458. for i, key := range keys {
  2459. args[i+2] = key
  2460. }
  2461. args[len(keys)+2] = "withscores"
  2462. cmd := NewZSliceCmd(ctx, args...)
  2463. cmd.setFirstKeyPos(2)
  2464. _ = c(ctx, cmd)
  2465. return cmd
  2466. }
  2467. // ZDiffStore redis-server version >=6.2.0.
  2468. func (c cmdable) ZDiffStore(ctx context.Context, destination string, keys ...string) *IntCmd {
  2469. args := make([]interface{}, 0, 3+len(keys))
  2470. args = append(args, "zdiffstore", destination, len(keys))
  2471. for _, key := range keys {
  2472. args = append(args, key)
  2473. }
  2474. cmd := NewIntCmd(ctx, args...)
  2475. _ = c(ctx, cmd)
  2476. return cmd
  2477. }
  2478. //------------------------------------------------------------------------------
  2479. func (c cmdable) PFAdd(ctx context.Context, key string, els ...interface{}) *IntCmd {
  2480. args := make([]interface{}, 2, 2+len(els))
  2481. args[0] = "pfadd"
  2482. args[1] = key
  2483. args = appendArgs(args, els)
  2484. cmd := NewIntCmd(ctx, args...)
  2485. _ = c(ctx, cmd)
  2486. return cmd
  2487. }
  2488. func (c cmdable) PFCount(ctx context.Context, keys ...string) *IntCmd {
  2489. args := make([]interface{}, 1+len(keys))
  2490. args[0] = "pfcount"
  2491. for i, key := range keys {
  2492. args[1+i] = key
  2493. }
  2494. cmd := NewIntCmd(ctx, args...)
  2495. _ = c(ctx, cmd)
  2496. return cmd
  2497. }
  2498. func (c cmdable) PFMerge(ctx context.Context, dest string, keys ...string) *StatusCmd {
  2499. args := make([]interface{}, 2+len(keys))
  2500. args[0] = "pfmerge"
  2501. args[1] = dest
  2502. for i, key := range keys {
  2503. args[2+i] = key
  2504. }
  2505. cmd := NewStatusCmd(ctx, args...)
  2506. _ = c(ctx, cmd)
  2507. return cmd
  2508. }
  2509. //------------------------------------------------------------------------------
  2510. func (c cmdable) BgRewriteAOF(ctx context.Context) *StatusCmd {
  2511. cmd := NewStatusCmd(ctx, "bgrewriteaof")
  2512. _ = c(ctx, cmd)
  2513. return cmd
  2514. }
  2515. func (c cmdable) BgSave(ctx context.Context) *StatusCmd {
  2516. cmd := NewStatusCmd(ctx, "bgsave")
  2517. _ = c(ctx, cmd)
  2518. return cmd
  2519. }
  2520. func (c cmdable) ClientKill(ctx context.Context, ipPort string) *StatusCmd {
  2521. cmd := NewStatusCmd(ctx, "client", "kill", ipPort)
  2522. _ = c(ctx, cmd)
  2523. return cmd
  2524. }
  2525. // ClientKillByFilter is new style syntax, while the ClientKill is old
  2526. //
  2527. // CLIENT KILL <option> [value] ... <option> [value]
  2528. func (c cmdable) ClientKillByFilter(ctx context.Context, keys ...string) *IntCmd {
  2529. args := make([]interface{}, 2+len(keys))
  2530. args[0] = "client"
  2531. args[1] = "kill"
  2532. for i, key := range keys {
  2533. args[2+i] = key
  2534. }
  2535. cmd := NewIntCmd(ctx, args...)
  2536. _ = c(ctx, cmd)
  2537. return cmd
  2538. }
  2539. func (c cmdable) ClientList(ctx context.Context) *StringCmd {
  2540. cmd := NewStringCmd(ctx, "client", "list")
  2541. _ = c(ctx, cmd)
  2542. return cmd
  2543. }
  2544. func (c cmdable) ClientPause(ctx context.Context, dur time.Duration) *BoolCmd {
  2545. cmd := NewBoolCmd(ctx, "client", "pause", formatMs(ctx, dur))
  2546. _ = c(ctx, cmd)
  2547. return cmd
  2548. }
  2549. func (c cmdable) ClientID(ctx context.Context) *IntCmd {
  2550. cmd := NewIntCmd(ctx, "client", "id")
  2551. _ = c(ctx, cmd)
  2552. return cmd
  2553. }
  2554. func (c cmdable) ClientUnblock(ctx context.Context, id int64) *IntCmd {
  2555. cmd := NewIntCmd(ctx, "client", "unblock", id)
  2556. _ = c(ctx, cmd)
  2557. return cmd
  2558. }
  2559. func (c cmdable) ClientUnblockWithError(ctx context.Context, id int64) *IntCmd {
  2560. cmd := NewIntCmd(ctx, "client", "unblock", id, "error")
  2561. _ = c(ctx, cmd)
  2562. return cmd
  2563. }
  2564. func (c cmdable) ConfigGet(ctx context.Context, parameter string) *SliceCmd {
  2565. cmd := NewSliceCmd(ctx, "config", "get", parameter)
  2566. _ = c(ctx, cmd)
  2567. return cmd
  2568. }
  2569. func (c cmdable) ConfigResetStat(ctx context.Context) *StatusCmd {
  2570. cmd := NewStatusCmd(ctx, "config", "resetstat")
  2571. _ = c(ctx, cmd)
  2572. return cmd
  2573. }
  2574. func (c cmdable) ConfigSet(ctx context.Context, parameter, value string) *StatusCmd {
  2575. cmd := NewStatusCmd(ctx, "config", "set", parameter, value)
  2576. _ = c(ctx, cmd)
  2577. return cmd
  2578. }
  2579. func (c cmdable) ConfigRewrite(ctx context.Context) *StatusCmd {
  2580. cmd := NewStatusCmd(ctx, "config", "rewrite")
  2581. _ = c(ctx, cmd)
  2582. return cmd
  2583. }
  2584. func (c cmdable) DBSize(ctx context.Context) *IntCmd {
  2585. cmd := NewIntCmd(ctx, "dbsize")
  2586. _ = c(ctx, cmd)
  2587. return cmd
  2588. }
  2589. func (c cmdable) FlushAll(ctx context.Context) *StatusCmd {
  2590. cmd := NewStatusCmd(ctx, "flushall")
  2591. _ = c(ctx, cmd)
  2592. return cmd
  2593. }
  2594. func (c cmdable) FlushAllAsync(ctx context.Context) *StatusCmd {
  2595. cmd := NewStatusCmd(ctx, "flushall", "async")
  2596. _ = c(ctx, cmd)
  2597. return cmd
  2598. }
  2599. func (c cmdable) FlushDB(ctx context.Context) *StatusCmd {
  2600. cmd := NewStatusCmd(ctx, "flushdb")
  2601. _ = c(ctx, cmd)
  2602. return cmd
  2603. }
  2604. func (c cmdable) FlushDBAsync(ctx context.Context) *StatusCmd {
  2605. cmd := NewStatusCmd(ctx, "flushdb", "async")
  2606. _ = c(ctx, cmd)
  2607. return cmd
  2608. }
  2609. func (c cmdable) Info(ctx context.Context, section ...string) *StringCmd {
  2610. args := []interface{}{"info"}
  2611. if len(section) > 0 {
  2612. args = append(args, section[0])
  2613. }
  2614. cmd := NewStringCmd(ctx, args...)
  2615. _ = c(ctx, cmd)
  2616. return cmd
  2617. }
  2618. func (c cmdable) LastSave(ctx context.Context) *IntCmd {
  2619. cmd := NewIntCmd(ctx, "lastsave")
  2620. _ = c(ctx, cmd)
  2621. return cmd
  2622. }
  2623. func (c cmdable) Save(ctx context.Context) *StatusCmd {
  2624. cmd := NewStatusCmd(ctx, "save")
  2625. _ = c(ctx, cmd)
  2626. return cmd
  2627. }
  2628. func (c cmdable) shutdown(ctx context.Context, modifier string) *StatusCmd {
  2629. var args []interface{}
  2630. if modifier == "" {
  2631. args = []interface{}{"shutdown"}
  2632. } else {
  2633. args = []interface{}{"shutdown", modifier}
  2634. }
  2635. cmd := NewStatusCmd(ctx, args...)
  2636. _ = c(ctx, cmd)
  2637. if err := cmd.Err(); err != nil {
  2638. if err == io.EOF {
  2639. // Server quit as expected.
  2640. cmd.err = nil
  2641. }
  2642. } else {
  2643. // Server did not quit. String reply contains the reason.
  2644. cmd.err = errors.New(cmd.val)
  2645. cmd.val = ""
  2646. }
  2647. return cmd
  2648. }
  2649. func (c cmdable) Shutdown(ctx context.Context) *StatusCmd {
  2650. return c.shutdown(ctx, "")
  2651. }
  2652. func (c cmdable) ShutdownSave(ctx context.Context) *StatusCmd {
  2653. return c.shutdown(ctx, "save")
  2654. }
  2655. func (c cmdable) ShutdownNoSave(ctx context.Context) *StatusCmd {
  2656. return c.shutdown(ctx, "nosave")
  2657. }
  2658. func (c cmdable) SlaveOf(ctx context.Context, host, port string) *StatusCmd {
  2659. cmd := NewStatusCmd(ctx, "slaveof", host, port)
  2660. _ = c(ctx, cmd)
  2661. return cmd
  2662. }
  2663. func (c cmdable) SlowLogGet(ctx context.Context, num int64) *SlowLogCmd {
  2664. cmd := NewSlowLogCmd(context.Background(), "slowlog", "get", num)
  2665. _ = c(ctx, cmd)
  2666. return cmd
  2667. }
  2668. func (c cmdable) Sync(_ context.Context) {
  2669. panic("not implemented")
  2670. }
  2671. func (c cmdable) Time(ctx context.Context) *TimeCmd {
  2672. cmd := NewTimeCmd(ctx, "time")
  2673. _ = c(ctx, cmd)
  2674. return cmd
  2675. }
  2676. func (c cmdable) DebugObject(ctx context.Context, key string) *StringCmd {
  2677. cmd := NewStringCmd(ctx, "debug", "object", key)
  2678. _ = c(ctx, cmd)
  2679. return cmd
  2680. }
  2681. func (c cmdable) ReadOnly(ctx context.Context) *StatusCmd {
  2682. cmd := NewStatusCmd(ctx, "readonly")
  2683. _ = c(ctx, cmd)
  2684. return cmd
  2685. }
  2686. func (c cmdable) ReadWrite(ctx context.Context) *StatusCmd {
  2687. cmd := NewStatusCmd(ctx, "readwrite")
  2688. _ = c(ctx, cmd)
  2689. return cmd
  2690. }
  2691. func (c cmdable) MemoryUsage(ctx context.Context, key string, samples ...int) *IntCmd {
  2692. args := []interface{}{"memory", "usage", key}
  2693. if len(samples) > 0 {
  2694. if len(samples) != 1 {
  2695. panic("MemoryUsage expects single sample count")
  2696. }
  2697. args = append(args, "SAMPLES", samples[0])
  2698. }
  2699. cmd := NewIntCmd(ctx, args...)
  2700. cmd.setFirstKeyPos(2)
  2701. _ = c(ctx, cmd)
  2702. return cmd
  2703. }
  2704. //------------------------------------------------------------------------------
  2705. func (c cmdable) Eval(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd {
  2706. cmdArgs := make([]interface{}, 3+len(keys), 3+len(keys)+len(args))
  2707. cmdArgs[0] = "eval"
  2708. cmdArgs[1] = script
  2709. cmdArgs[2] = len(keys)
  2710. for i, key := range keys {
  2711. cmdArgs[3+i] = key
  2712. }
  2713. cmdArgs = appendArgs(cmdArgs, args)
  2714. cmd := NewCmd(ctx, cmdArgs...)
  2715. cmd.setFirstKeyPos(3)
  2716. _ = c(ctx, cmd)
  2717. return cmd
  2718. }
  2719. func (c cmdable) EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd {
  2720. cmdArgs := make([]interface{}, 3+len(keys), 3+len(keys)+len(args))
  2721. cmdArgs[0] = "evalsha"
  2722. cmdArgs[1] = sha1
  2723. cmdArgs[2] = len(keys)
  2724. for i, key := range keys {
  2725. cmdArgs[3+i] = key
  2726. }
  2727. cmdArgs = appendArgs(cmdArgs, args)
  2728. cmd := NewCmd(ctx, cmdArgs...)
  2729. cmd.setFirstKeyPos(3)
  2730. _ = c(ctx, cmd)
  2731. return cmd
  2732. }
  2733. func (c cmdable) ScriptExists(ctx context.Context, hashes ...string) *BoolSliceCmd {
  2734. args := make([]interface{}, 2+len(hashes))
  2735. args[0] = "script"
  2736. args[1] = "exists"
  2737. for i, hash := range hashes {
  2738. args[2+i] = hash
  2739. }
  2740. cmd := NewBoolSliceCmd(ctx, args...)
  2741. _ = c(ctx, cmd)
  2742. return cmd
  2743. }
  2744. func (c cmdable) ScriptFlush(ctx context.Context) *StatusCmd {
  2745. cmd := NewStatusCmd(ctx, "script", "flush")
  2746. _ = c(ctx, cmd)
  2747. return cmd
  2748. }
  2749. func (c cmdable) ScriptKill(ctx context.Context) *StatusCmd {
  2750. cmd := NewStatusCmd(ctx, "script", "kill")
  2751. _ = c(ctx, cmd)
  2752. return cmd
  2753. }
  2754. func (c cmdable) ScriptLoad(ctx context.Context, script string) *StringCmd {
  2755. cmd := NewStringCmd(ctx, "script", "load", script)
  2756. _ = c(ctx, cmd)
  2757. return cmd
  2758. }
  2759. //------------------------------------------------------------------------------
  2760. // Publish posts the message to the channel.
  2761. func (c cmdable) Publish(ctx context.Context, channel string, message interface{}) *IntCmd {
  2762. cmd := NewIntCmd(ctx, "publish", channel, message)
  2763. _ = c(ctx, cmd)
  2764. return cmd
  2765. }
  2766. func (c cmdable) PubSubChannels(ctx context.Context, pattern string) *StringSliceCmd {
  2767. args := []interface{}{"pubsub", "channels"}
  2768. if pattern != "*" {
  2769. args = append(args, pattern)
  2770. }
  2771. cmd := NewStringSliceCmd(ctx, args...)
  2772. _ = c(ctx, cmd)
  2773. return cmd
  2774. }
  2775. func (c cmdable) PubSubNumSub(ctx context.Context, channels ...string) *StringIntMapCmd {
  2776. args := make([]interface{}, 2+len(channels))
  2777. args[0] = "pubsub"
  2778. args[1] = "numsub"
  2779. for i, channel := range channels {
  2780. args[2+i] = channel
  2781. }
  2782. cmd := NewStringIntMapCmd(ctx, args...)
  2783. _ = c(ctx, cmd)
  2784. return cmd
  2785. }
  2786. func (c cmdable) PubSubNumPat(ctx context.Context) *IntCmd {
  2787. cmd := NewIntCmd(ctx, "pubsub", "numpat")
  2788. _ = c(ctx, cmd)
  2789. return cmd
  2790. }
  2791. //------------------------------------------------------------------------------
  2792. func (c cmdable) ClusterSlots(ctx context.Context) *ClusterSlotsCmd {
  2793. cmd := NewClusterSlotsCmd(ctx, "cluster", "slots")
  2794. _ = c(ctx, cmd)
  2795. return cmd
  2796. }
  2797. func (c cmdable) ClusterNodes(ctx context.Context) *StringCmd {
  2798. cmd := NewStringCmd(ctx, "cluster", "nodes")
  2799. _ = c(ctx, cmd)
  2800. return cmd
  2801. }
  2802. func (c cmdable) ClusterMeet(ctx context.Context, host, port string) *StatusCmd {
  2803. cmd := NewStatusCmd(ctx, "cluster", "meet", host, port)
  2804. _ = c(ctx, cmd)
  2805. return cmd
  2806. }
  2807. func (c cmdable) ClusterForget(ctx context.Context, nodeID string) *StatusCmd {
  2808. cmd := NewStatusCmd(ctx, "cluster", "forget", nodeID)
  2809. _ = c(ctx, cmd)
  2810. return cmd
  2811. }
  2812. func (c cmdable) ClusterReplicate(ctx context.Context, nodeID string) *StatusCmd {
  2813. cmd := NewStatusCmd(ctx, "cluster", "replicate", nodeID)
  2814. _ = c(ctx, cmd)
  2815. return cmd
  2816. }
  2817. func (c cmdable) ClusterResetSoft(ctx context.Context) *StatusCmd {
  2818. cmd := NewStatusCmd(ctx, "cluster", "reset", "soft")
  2819. _ = c(ctx, cmd)
  2820. return cmd
  2821. }
  2822. func (c cmdable) ClusterResetHard(ctx context.Context) *StatusCmd {
  2823. cmd := NewStatusCmd(ctx, "cluster", "reset", "hard")
  2824. _ = c(ctx, cmd)
  2825. return cmd
  2826. }
  2827. func (c cmdable) ClusterInfo(ctx context.Context) *StringCmd {
  2828. cmd := NewStringCmd(ctx, "cluster", "info")
  2829. _ = c(ctx, cmd)
  2830. return cmd
  2831. }
  2832. func (c cmdable) ClusterKeySlot(ctx context.Context, key string) *IntCmd {
  2833. cmd := NewIntCmd(ctx, "cluster", "keyslot", key)
  2834. _ = c(ctx, cmd)
  2835. return cmd
  2836. }
  2837. func (c cmdable) ClusterGetKeysInSlot(ctx context.Context, slot int, count int) *StringSliceCmd {
  2838. cmd := NewStringSliceCmd(ctx, "cluster", "getkeysinslot", slot, count)
  2839. _ = c(ctx, cmd)
  2840. return cmd
  2841. }
  2842. func (c cmdable) ClusterCountFailureReports(ctx context.Context, nodeID string) *IntCmd {
  2843. cmd := NewIntCmd(ctx, "cluster", "count-failure-reports", nodeID)
  2844. _ = c(ctx, cmd)
  2845. return cmd
  2846. }
  2847. func (c cmdable) ClusterCountKeysInSlot(ctx context.Context, slot int) *IntCmd {
  2848. cmd := NewIntCmd(ctx, "cluster", "countkeysinslot", slot)
  2849. _ = c(ctx, cmd)
  2850. return cmd
  2851. }
  2852. func (c cmdable) ClusterDelSlots(ctx context.Context, slots ...int) *StatusCmd {
  2853. args := make([]interface{}, 2+len(slots))
  2854. args[0] = "cluster"
  2855. args[1] = "delslots"
  2856. for i, slot := range slots {
  2857. args[2+i] = slot
  2858. }
  2859. cmd := NewStatusCmd(ctx, args...)
  2860. _ = c(ctx, cmd)
  2861. return cmd
  2862. }
  2863. func (c cmdable) ClusterDelSlotsRange(ctx context.Context, min, max int) *StatusCmd {
  2864. size := max - min + 1
  2865. slots := make([]int, size)
  2866. for i := 0; i < size; i++ {
  2867. slots[i] = min + i
  2868. }
  2869. return c.ClusterDelSlots(ctx, slots...)
  2870. }
  2871. func (c cmdable) ClusterSaveConfig(ctx context.Context) *StatusCmd {
  2872. cmd := NewStatusCmd(ctx, "cluster", "saveconfig")
  2873. _ = c(ctx, cmd)
  2874. return cmd
  2875. }
  2876. func (c cmdable) ClusterSlaves(ctx context.Context, nodeID string) *StringSliceCmd {
  2877. cmd := NewStringSliceCmd(ctx, "cluster", "slaves", nodeID)
  2878. _ = c(ctx, cmd)
  2879. return cmd
  2880. }
  2881. func (c cmdable) ClusterFailover(ctx context.Context) *StatusCmd {
  2882. cmd := NewStatusCmd(ctx, "cluster", "failover")
  2883. _ = c(ctx, cmd)
  2884. return cmd
  2885. }
  2886. func (c cmdable) ClusterAddSlots(ctx context.Context, slots ...int) *StatusCmd {
  2887. args := make([]interface{}, 2+len(slots))
  2888. args[0] = "cluster"
  2889. args[1] = "addslots"
  2890. for i, num := range slots {
  2891. args[2+i] = num
  2892. }
  2893. cmd := NewStatusCmd(ctx, args...)
  2894. _ = c(ctx, cmd)
  2895. return cmd
  2896. }
  2897. func (c cmdable) ClusterAddSlotsRange(ctx context.Context, min, max int) *StatusCmd {
  2898. size := max - min + 1
  2899. slots := make([]int, size)
  2900. for i := 0; i < size; i++ {
  2901. slots[i] = min + i
  2902. }
  2903. return c.ClusterAddSlots(ctx, slots...)
  2904. }
  2905. //------------------------------------------------------------------------------
  2906. func (c cmdable) GeoAdd(ctx context.Context, key string, geoLocation ...*GeoLocation) *IntCmd {
  2907. args := make([]interface{}, 2+3*len(geoLocation))
  2908. args[0] = "geoadd"
  2909. args[1] = key
  2910. for i, eachLoc := range geoLocation {
  2911. args[2+3*i] = eachLoc.Longitude
  2912. args[2+3*i+1] = eachLoc.Latitude
  2913. args[2+3*i+2] = eachLoc.Name
  2914. }
  2915. cmd := NewIntCmd(ctx, args...)
  2916. _ = c(ctx, cmd)
  2917. return cmd
  2918. }
  2919. // GeoRadius is a read-only GEORADIUS_RO command.
  2920. func (c cmdable) GeoRadius(
  2921. ctx context.Context, key string, longitude, latitude float64, query *GeoRadiusQuery,
  2922. ) *GeoLocationCmd {
  2923. cmd := NewGeoLocationCmd(ctx, query, "georadius_ro", key, longitude, latitude)
  2924. if query.Store != "" || query.StoreDist != "" {
  2925. cmd.SetErr(errors.New("GeoRadius does not support Store or StoreDist"))
  2926. return cmd
  2927. }
  2928. _ = c(ctx, cmd)
  2929. return cmd
  2930. }
  2931. // GeoRadiusStore is a writing GEORADIUS command.
  2932. func (c cmdable) GeoRadiusStore(
  2933. ctx context.Context, key string, longitude, latitude float64, query *GeoRadiusQuery,
  2934. ) *IntCmd {
  2935. args := geoLocationArgs(query, "georadius", key, longitude, latitude)
  2936. cmd := NewIntCmd(ctx, args...)
  2937. if query.Store == "" && query.StoreDist == "" {
  2938. cmd.SetErr(errors.New("GeoRadiusStore requires Store or StoreDist"))
  2939. return cmd
  2940. }
  2941. _ = c(ctx, cmd)
  2942. return cmd
  2943. }
  2944. // GeoRadiusByMember is a read-only GEORADIUSBYMEMBER_RO command.
  2945. func (c cmdable) GeoRadiusByMember(
  2946. ctx context.Context, key, member string, query *GeoRadiusQuery,
  2947. ) *GeoLocationCmd {
  2948. cmd := NewGeoLocationCmd(ctx, query, "georadiusbymember_ro", key, member)
  2949. if query.Store != "" || query.StoreDist != "" {
  2950. cmd.SetErr(errors.New("GeoRadiusByMember does not support Store or StoreDist"))
  2951. return cmd
  2952. }
  2953. _ = c(ctx, cmd)
  2954. return cmd
  2955. }
  2956. // GeoRadiusByMemberStore is a writing GEORADIUSBYMEMBER command.
  2957. func (c cmdable) GeoRadiusByMemberStore(
  2958. ctx context.Context, key, member string, query *GeoRadiusQuery,
  2959. ) *IntCmd {
  2960. args := geoLocationArgs(query, "georadiusbymember", key, member)
  2961. cmd := NewIntCmd(ctx, args...)
  2962. if query.Store == "" && query.StoreDist == "" {
  2963. cmd.SetErr(errors.New("GeoRadiusByMemberStore requires Store or StoreDist"))
  2964. return cmd
  2965. }
  2966. _ = c(ctx, cmd)
  2967. return cmd
  2968. }
  2969. func (c cmdable) GeoSearch(ctx context.Context, key string, q *GeoSearchQuery) *StringSliceCmd {
  2970. args := make([]interface{}, 0, 13)
  2971. args = append(args, "geosearch", key)
  2972. args = geoSearchArgs(q, args)
  2973. cmd := NewStringSliceCmd(ctx, args...)
  2974. _ = c(ctx, cmd)
  2975. return cmd
  2976. }
  2977. func (c cmdable) GeoSearchLocation(
  2978. ctx context.Context, key string, q *GeoSearchLocationQuery,
  2979. ) *GeoSearchLocationCmd {
  2980. args := make([]interface{}, 0, 16)
  2981. args = append(args, "geosearch", key)
  2982. args = geoSearchLocationArgs(q, args)
  2983. cmd := NewGeoSearchLocationCmd(ctx, q, args...)
  2984. _ = c(ctx, cmd)
  2985. return cmd
  2986. }
  2987. func (c cmdable) GeoSearchStore(ctx context.Context, key, store string, q *GeoSearchStoreQuery) *IntCmd {
  2988. args := make([]interface{}, 0, 15)
  2989. args = append(args, "geosearchstore", store, key)
  2990. args = geoSearchArgs(&q.GeoSearchQuery, args)
  2991. if q.StoreDist {
  2992. args = append(args, "storedist")
  2993. }
  2994. cmd := NewIntCmd(ctx, args...)
  2995. _ = c(ctx, cmd)
  2996. return cmd
  2997. }
  2998. func (c cmdable) GeoDist(
  2999. ctx context.Context, key string, member1, member2, unit string,
  3000. ) *FloatCmd {
  3001. if unit == "" {
  3002. unit = "km"
  3003. }
  3004. cmd := NewFloatCmd(ctx, "geodist", key, member1, member2, unit)
  3005. _ = c(ctx, cmd)
  3006. return cmd
  3007. }
  3008. func (c cmdable) GeoHash(ctx context.Context, key string, members ...string) *StringSliceCmd {
  3009. args := make([]interface{}, 2+len(members))
  3010. args[0] = "geohash"
  3011. args[1] = key
  3012. for i, member := range members {
  3013. args[2+i] = member
  3014. }
  3015. cmd := NewStringSliceCmd(ctx, args...)
  3016. _ = c(ctx, cmd)
  3017. return cmd
  3018. }
  3019. func (c cmdable) GeoPos(ctx context.Context, key string, members ...string) *GeoPosCmd {
  3020. args := make([]interface{}, 2+len(members))
  3021. args[0] = "geopos"
  3022. args[1] = key
  3023. for i, member := range members {
  3024. args[2+i] = member
  3025. }
  3026. cmd := NewGeoPosCmd(ctx, args...)
  3027. _ = c(ctx, cmd)
  3028. return cmd
  3029. }