@@ -9,11 +9,18 @@ import (
99 "github.com/go-redis/redis/v8/internal"
1010)
1111
12- // KeepTTL is an option for Set command to keep key's existing TTL.
13- // For example:
14- //
15- // rdb.Set(ctx, key, value, redis.KeepTTL)
16- const KeepTTL = - 1
12+ const (
13+ // KeepTTL is an option for Set command to keep key's existing TTL.
14+ // For example:
15+ //
16+ // rdb.Set(ctx, key, value, redis.KeepTTL)
17+ KeepTTL = - 1
18+
19+ // Persist is remove the time to live associated with the key.
20+ // For example:
21+ // rdb.GetEX(ctx, key, redis.Persist)
22+ Persist = - 2
23+ )
1724
1825func usePrecise (dur time.Duration ) bool {
1926 return dur < time .Second || dur % time .Second != 0
@@ -117,7 +124,7 @@ type Cmdable interface {
117124 Get (ctx context.Context , key string ) * StringCmd
118125 GetRange (ctx context.Context , key string , start , end int64 ) * StringCmd
119126 GetSet (ctx context.Context , key string , value interface {}) * StringCmd
120- GetEX (ctx context.Context , key string , ttl * SetTTL ) * StringCmd
127+ GetEX (ctx context.Context , key string , expiration time. Duration ) * StringCmd
121128 GetDel (ctx context.Context , key string ) * StringCmd
122129 Incr (ctx context.Context , key string ) * IntCmd
123130 IncrBy (ctx context.Context , key string , value int64 ) * IntCmd
@@ -162,6 +169,7 @@ type Cmdable interface {
162169 HMSet (ctx context.Context , key string , values ... interface {}) * BoolCmd
163170 HSetNX (ctx context.Context , key , field string , value interface {}) * BoolCmd
164171 HVals (ctx context.Context , key string ) * StringSliceCmd
172+ HRandField (ctx context.Context , key string , count int , withValues bool ) * StringSliceCmd
165173
166174 BLPop (ctx context.Context , timeout time.Duration , keys ... string ) * StringSliceCmd
167175 BRPop (ctx context.Context , timeout time.Duration , keys ... string ) * StringSliceCmd
@@ -265,6 +273,7 @@ type Cmdable interface {
265273 ZRevRank (ctx context.Context , key , member string ) * IntCmd
266274 ZScore (ctx context.Context , key , member string ) * FloatCmd
267275 ZUnionStore (ctx context.Context , dest string , store * ZStore ) * IntCmd
276+ ZRandMember (ctx context.Context , key string , count int , withScores bool ) * StringSliceCmd
268277
269278 PFAdd (ctx context.Context , key string , els ... interface {}) * IntCmd
270279 PFCount (ctx context.Context , keys ... string ) * IntCmd
@@ -363,58 +372,6 @@ type statefulCmdable func(ctx context.Context, cmd Cmder) error
363372
364373//------------------------------------------------------------------------------
365374
366- type ttlAttr int
367-
368- const (
369- TExpire ttlAttr = 1 << iota
370- TExpireAT
371- TKeepTTL
372- TPersist
373- )
374-
375- // TTL related parameters, not all commands support all ttl attributes.
376- // priority: Expire > ExpireAt > KeepTTL > Persist
377- type SetTTL struct {
378- // set the specified expire time.
379- // Expire > time.Second AND Expire % time.Second == 0: set key EX Expire/time.Second
380- // Expire < time.Second OR Expire % time.Second != 0: set key PX Expire/time.Millisecond
381- Expire time.Duration
382-
383- // set the specified Unix time at which the key will expire.
384- // Example: set key EXAT ExpireAt.Unix()
385- // Don't consider milliseconds for now(PXAT)
386- ExpireAt time.Time
387-
388- // Retain the time to live associated with the key.
389- KeepTTL bool
390-
391- // Remove the time to live associated with the key, Change to never expire
392- Persist bool
393- }
394-
395- func appendTTL (ctx context.Context , args []interface {}, t * SetTTL , attr ttlAttr ) []interface {} {
396- if t == nil {
397- return args
398- }
399-
400- switch {
401- case attr & TExpire == 1 && t .Expire > 0 :
402- if usePrecise (t .Expire ) {
403- args = append (args , "px" , formatMs (ctx , t .Expire ))
404- } else {
405- args = append (args , "ex" , formatSec (ctx , t .Expire ))
406- }
407- case attr & TExpireAT == 1 && ! t .ExpireAt .IsZero ():
408- args = append (args , "exat" , t .ExpireAt .Unix ())
409- case attr & TKeepTTL == 1 && t .KeepTTL :
410- args = append (args , "keepttl" )
411- case attr & TPersist == 1 && t .Persist :
412- args = append (args , "persist" )
413- }
414-
415- return args
416- }
417-
418375func (c statefulCmdable ) Auth (ctx context.Context , password string ) * StatusCmd {
419376 cmd := NewStatusCmd (ctx , "auth" , password )
420377 _ = c (ctx , cmd )
@@ -764,17 +721,29 @@ func (c cmdable) GetSet(ctx context.Context, key string, value interface{}) *Str
764721 return cmd
765722}
766723
767- // redis-server version >= 6.2.0
768- func (c cmdable ) GetEX (ctx context.Context , key string , ttl * SetTTL ) * StringCmd {
769- args := make ([]interface {}, 2 , 4 )
724+ // redis-server version >= 6.2.0.
725+ //
726+ // A value of zero means that the expiration time will not be changed.
727+ // Persist(-2) Remove the time to live associated with the key.
728+ func (c cmdable ) GetEX (ctx context.Context , key string , expiration time.Duration ) * StringCmd {
729+ args := make ([]interface {}, 0 , 4 )
770730 args = append (args , "getex" , key )
771- args = appendTTL (ctx , args , ttl , TExpire | TExpireAT | TPersist )
731+ if expiration > 0 {
732+ if usePrecise (expiration ) {
733+ args = append (args , "px" , formatMs (ctx , expiration ))
734+ } else {
735+ args = append (args , "ex" , formatSec (ctx , expiration ))
736+ }
737+ } else if expiration == Persist {
738+ args = append (args , "persist" )
739+ }
740+
772741 cmd := NewStringCmd (ctx , args ... )
773742 _ = c (ctx , cmd )
774743 return cmd
775744}
776745
777- // redis-server version >= 6.2.0
746+ // redis-server version >= 6.2.0.
778747func (c cmdable ) GetDel (ctx context.Context , key string ) * StringCmd {
779748 cmd := NewStringCmd (ctx , "getdel" , key )
780749 _ = c (ctx , cmd )
@@ -1253,6 +1222,20 @@ func (c cmdable) HVals(ctx context.Context, key string) *StringSliceCmd {
12531222 return cmd
12541223}
12551224
1225+ func (c cmdable ) HRandField (ctx context.Context , key string , count int , withValues bool ) * StringSliceCmd {
1226+ args := make ([]interface {}, 0 , 4 )
1227+
1228+ // Although count=0 is meaningless, redis accepts count=0.
1229+ args = append (args , "hrandfield" , key , count )
1230+ if withValues {
1231+ args = append (args , "withvalues" )
1232+ }
1233+
1234+ cmd := NewStringSliceCmd (ctx , args ... )
1235+ _ = c (ctx , cmd )
1236+ return cmd
1237+ }
1238+
12561239//------------------------------------------------------------------------------
12571240
12581241func (c cmdable ) BLPop (ctx context.Context , timeout time.Duration , keys ... string ) * StringSliceCmd {
@@ -2327,6 +2310,18 @@ func (c cmdable) ZUnionStore(ctx context.Context, dest string, store *ZStore) *I
23272310 return cmd
23282311}
23292312
2313+ func (c cmdable ) ZRandMember (ctx context.Context , key string , count int , withScores bool ) * StringSliceCmd {
2314+ args := make ([]interface {}, 0 , 4 )
2315+ args = append (args , "zrandmember" , key , count )
2316+ if withScores {
2317+ args = append (args , "withscores" )
2318+ }
2319+
2320+ cmd := NewStringSliceCmd (ctx , args ... )
2321+ _ = c (ctx , cmd )
2322+ return cmd
2323+ }
2324+
23302325//------------------------------------------------------------------------------
23312326
23322327func (c cmdable ) PFAdd (ctx context.Context , key string , els ... interface {}) * IntCmd {
0 commit comments