Skip to content

Commit cb1be72

Browse files
committed
add new cmd: getEX getDel
Signed-off-by: monkey <[email protected]>
1 parent 55db07d commit cb1be72

File tree

2 files changed

+103
-1
lines changed

2 files changed

+103
-1
lines changed

commands.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ type Cmdable interface {
117117
Get(ctx context.Context, key string) *StringCmd
118118
GetRange(ctx context.Context, key string, start, end int64) *StringCmd
119119
GetSet(ctx context.Context, key string, value interface{}) *StringCmd
120+
GetEX(ctx context.Context, key string, ttl *SetTTL) *StringCmd
121+
GetDel(ctx context.Context, key string) *StringCmd
120122
Incr(ctx context.Context, key string) *IntCmd
121123
IncrBy(ctx context.Context, key string, value int64) *IntCmd
122124
IncrByFloat(ctx context.Context, key string, value float64) *FloatCmd
@@ -361,6 +363,58 @@ type statefulCmdable func(ctx context.Context, cmd Cmder) error
361363

362364
//------------------------------------------------------------------------------
363365

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+
364418
func (c statefulCmdable) Auth(ctx context.Context, password string) *StatusCmd {
365419
cmd := NewStatusCmd(ctx, "auth", password)
366420
_ = c(ctx, cmd)
@@ -710,6 +764,23 @@ func (c cmdable) GetSet(ctx context.Context, key string, value interface{}) *Str
710764
return cmd
711765
}
712766

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)
770+
args = append(args, "getex", key)
771+
args = appendTTL(ctx, args, ttl, TExpire|TExpireAT|TPersist)
772+
cmd := NewStringCmd(ctx, args...)
773+
_ = c(ctx, cmd)
774+
return cmd
775+
}
776+
777+
// redis-server version >= 6.2.0
778+
func (c cmdable) GetDel(ctx context.Context, key string) *StringCmd {
779+
cmd := NewStringCmd(ctx, "getdel", key)
780+
_ = c(ctx, cmd)
781+
return cmd
782+
}
783+
713784
func (c cmdable) Incr(ctx context.Context, key string) *IntCmd {
714785
cmd := NewIntCmd(ctx, "incr", key)
715786
_ = c(ctx, cmd)

commands_test.go

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ var _ = Describe("Commands", func() {
477477
//if too much time (>1s) is used during command execution, it may also cause the test to fail.
478478
//so the ObjectIdleTime result should be <=now-start+1s
479479
//link: https://github.com/redis/redis/blob/5b48d900498c85bbf4772c1d466c214439888115/src/object.c#L1265-L1272
480-
Expect(idleTime.Val()).To(BeNumerically("<=", time.Now().Sub(start) + time.Second))
480+
Expect(idleTime.Val()).To(BeNumerically("<=", time.Now().Sub(start)+time.Second))
481481
})
482482

483483
It("should Persist", func() {
@@ -1083,6 +1083,37 @@ var _ = Describe("Commands", func() {
10831083
Expect(get.Val()).To(Equal("0"))
10841084
})
10851085

1086+
It("should GetEX", func() {
1087+
set := client.Set(ctx, "key", "value", 100*time.Second)
1088+
Expect(set.Err()).NotTo(HaveOccurred())
1089+
Expect(set.Val()).To(Equal("OK"))
1090+
1091+
ttl := client.TTL(ctx, "key")
1092+
Expect(ttl.Err()).NotTo(HaveOccurred())
1093+
Expect(ttl.Val()).To(BeNumerically("~", 100*time.Second, 3*time.Second))
1094+
1095+
getEX := client.GetEX(ctx, "key", &redis.SetTTL{Expire: 200 * time.Second})
1096+
Expect(getEX.Err()).NotTo(HaveOccurred())
1097+
Expect(getEX.Val()).To(Equal("value"))
1098+
1099+
ttl = client.TTL(ctx, "key")
1100+
Expect(ttl.Err()).NotTo(HaveOccurred())
1101+
Expect(ttl.Val()).To(BeNumerically("~", 200*time.Second, 3*time.Second))
1102+
})
1103+
1104+
It("should GetDel", func() {
1105+
set := client.Set(ctx, "key", "value", 0)
1106+
Expect(set.Err()).NotTo(HaveOccurred())
1107+
Expect(set.Val()).To(Equal("OK"))
1108+
1109+
getDel := client.GetDel(ctx, "key")
1110+
Expect(getDel.Err()).NotTo(HaveOccurred())
1111+
Expect(getDel.Val()).To(Equal("value"))
1112+
1113+
get := client.Get(ctx, "key")
1114+
Expect(get.Err()).To(Equal(redis.Nil))
1115+
})
1116+
10861117
It("should Incr", func() {
10871118
set := client.Set(ctx, "key", "10", 0)
10881119
Expect(set.Err()).NotTo(HaveOccurred())

0 commit comments

Comments
 (0)