mirror of https://github.com/go-redis/redis.git
feature: add support for set keepttl (#1499)
* feature: add support for set keepttl
This commit is contained in:
parent
bae2f9cc64
commit
10e779f856
|
@ -120,6 +120,9 @@ Some corner cases:
|
||||||
// SET key value EX 10 NX
|
// SET key value EX 10 NX
|
||||||
set, err := rdb.SetNX(ctx, "key", "value", 10*time.Second).Result()
|
set, err := rdb.SetNX(ctx, "key", "value", 10*time.Second).Result()
|
||||||
|
|
||||||
|
// SET key value keepttl NX
|
||||||
|
set, err := rdb.SetNX(ctx, "key", "value", redis.KeepTTL).Result()
|
||||||
|
|
||||||
// SORT list LIMIT 0 2 ASC
|
// SORT list LIMIT 0 2 ASC
|
||||||
vals, err := rdb.Sort(ctx, "list", &redis.Sort{Offset: 0, Count: 2, Order: "ASC"}).Result()
|
vals, err := rdb.Sort(ctx, "list", &redis.Sort{Offset: 0, Count: 2, Order: "ASC"}).Result()
|
||||||
|
|
||||||
|
|
26
commands.go
26
commands.go
|
@ -9,6 +9,10 @@ import (
|
||||||
"github.com/go-redis/redis/v8/internal"
|
"github.com/go-redis/redis/v8/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// KeepTTL used when set with keepttl option
|
||||||
|
// Example: Set(ctx, key, value, redis.KeepTTL).
|
||||||
|
const KeepTTL = -1
|
||||||
|
|
||||||
func usePrecise(dur time.Duration) bool {
|
func usePrecise(dur time.Duration) bool {
|
||||||
return dur < time.Second || dur%time.Second != 0
|
return dur < time.Second || dur%time.Second != 0
|
||||||
}
|
}
|
||||||
|
@ -756,6 +760,7 @@ func (c cmdable) MSetNX(ctx context.Context, values ...interface{}) *BoolCmd {
|
||||||
//
|
//
|
||||||
// Use expiration for `SETEX`-like behavior.
|
// Use expiration for `SETEX`-like behavior.
|
||||||
// Zero expiration means the key has no expiration time.
|
// Zero expiration means the key has no expiration time.
|
||||||
|
// KeepTTL(-1) expiration means command set adds keepttl option.
|
||||||
func (c cmdable) Set(ctx context.Context, key string, value interface{}, expiration time.Duration) *StatusCmd {
|
func (c cmdable) Set(ctx context.Context, key string, value interface{}, expiration time.Duration) *StatusCmd {
|
||||||
args := make([]interface{}, 3, 5)
|
args := make([]interface{}, 3, 5)
|
||||||
args[0] = "set"
|
args[0] = "set"
|
||||||
|
@ -767,7 +772,10 @@ func (c cmdable) Set(ctx context.Context, key string, value interface{}, expirat
|
||||||
} else {
|
} else {
|
||||||
args = append(args, "ex", formatSec(ctx, expiration))
|
args = append(args, "ex", formatSec(ctx, expiration))
|
||||||
}
|
}
|
||||||
|
} else if expiration == KeepTTL {
|
||||||
|
args = append(args, "keepttl")
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := NewStatusCmd(ctx, args...)
|
cmd := NewStatusCmd(ctx, args...)
|
||||||
_ = c(ctx, cmd)
|
_ = c(ctx, cmd)
|
||||||
return cmd
|
return cmd
|
||||||
|
@ -776,18 +784,23 @@ func (c cmdable) Set(ctx context.Context, key string, value interface{}, expirat
|
||||||
// Redis `SET key value [expiration] NX` command.
|
// Redis `SET key value [expiration] NX` command.
|
||||||
//
|
//
|
||||||
// Zero expiration means the key has no expiration time.
|
// Zero expiration means the key has no expiration time.
|
||||||
|
// KeepTTL(-1) expiration means set command adds keepttl option.
|
||||||
func (c cmdable) SetNX(ctx context.Context, key string, value interface{}, expiration time.Duration) *BoolCmd {
|
func (c cmdable) SetNX(ctx context.Context, key string, value interface{}, expiration time.Duration) *BoolCmd {
|
||||||
var cmd *BoolCmd
|
var cmd *BoolCmd
|
||||||
if expiration == 0 {
|
switch {
|
||||||
|
case expiration == 0:
|
||||||
// Use old `SETNX` to support old Redis versions.
|
// Use old `SETNX` to support old Redis versions.
|
||||||
cmd = NewBoolCmd(ctx, "setnx", key, value)
|
cmd = NewBoolCmd(ctx, "setnx", key, value)
|
||||||
} else {
|
case expiration == KeepTTL:
|
||||||
|
cmd = NewBoolCmd(ctx, "set", key, value, "keepttl", "nx")
|
||||||
|
default:
|
||||||
if usePrecise(expiration) {
|
if usePrecise(expiration) {
|
||||||
cmd = NewBoolCmd(ctx, "set", key, value, "px", formatMs(ctx, expiration), "nx")
|
cmd = NewBoolCmd(ctx, "set", key, value, "px", formatMs(ctx, expiration), "nx")
|
||||||
} else {
|
} else {
|
||||||
cmd = NewBoolCmd(ctx, "set", key, value, "ex", formatSec(ctx, expiration), "nx")
|
cmd = NewBoolCmd(ctx, "set", key, value, "ex", formatSec(ctx, expiration), "nx")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = c(ctx, cmd)
|
_ = c(ctx, cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
@ -795,17 +808,22 @@ func (c cmdable) SetNX(ctx context.Context, key string, value interface{}, expir
|
||||||
// Redis `SET key value [expiration] XX` command.
|
// Redis `SET key value [expiration] XX` command.
|
||||||
//
|
//
|
||||||
// Zero expiration means the key has no expiration time.
|
// Zero expiration means the key has no expiration time.
|
||||||
|
// KeepTTL(-1) expiration means set command adds keepttl option.
|
||||||
func (c cmdable) SetXX(ctx context.Context, key string, value interface{}, expiration time.Duration) *BoolCmd {
|
func (c cmdable) SetXX(ctx context.Context, key string, value interface{}, expiration time.Duration) *BoolCmd {
|
||||||
var cmd *BoolCmd
|
var cmd *BoolCmd
|
||||||
if expiration == 0 {
|
switch {
|
||||||
|
case expiration == 0:
|
||||||
cmd = NewBoolCmd(ctx, "set", key, value, "xx")
|
cmd = NewBoolCmd(ctx, "set", key, value, "xx")
|
||||||
} else {
|
case expiration == KeepTTL:
|
||||||
|
cmd = NewBoolCmd(ctx, "set", key, value, "keepttl", "xx")
|
||||||
|
default:
|
||||||
if usePrecise(expiration) {
|
if usePrecise(expiration) {
|
||||||
cmd = NewBoolCmd(ctx, "set", key, value, "px", formatMs(ctx, expiration), "xx")
|
cmd = NewBoolCmd(ctx, "set", key, value, "px", formatMs(ctx, expiration), "xx")
|
||||||
} else {
|
} else {
|
||||||
cmd = NewBoolCmd(ctx, "set", key, value, "ex", formatSec(ctx, expiration), "xx")
|
cmd = NewBoolCmd(ctx, "set", key, value, "ex", formatSec(ctx, expiration), "xx")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = c(ctx, cmd)
|
_ = c(ctx, cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
|
@ -1145,6 +1145,23 @@ var _ = Describe("Commands", func() {
|
||||||
}, "1s", "100ms").Should(Equal(redis.Nil))
|
}, "1s", "100ms").Should(Equal(redis.Nil))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("should Set with keepttl", func() {
|
||||||
|
// set with ttl
|
||||||
|
set := client.Set(ctx, "key", "hello", 5 * time.Second)
|
||||||
|
Expect(set.Err()).NotTo(HaveOccurred())
|
||||||
|
Expect(set.Val()).To(Equal("OK"))
|
||||||
|
|
||||||
|
// set with keepttl
|
||||||
|
set = client.Set(ctx, "key", "hello1", redis.KeepTTL)
|
||||||
|
Expect(set.Err()).NotTo(HaveOccurred())
|
||||||
|
Expect(set.Val()).To(Equal("OK"))
|
||||||
|
|
||||||
|
ttl := client.TTL(ctx, "key")
|
||||||
|
Expect(ttl.Err()).NotTo(HaveOccurred())
|
||||||
|
// set keepttl will Retain the ttl associated with the key
|
||||||
|
Expect(ttl.Val().Nanoseconds()).NotTo(Equal(-1))
|
||||||
|
})
|
||||||
|
|
||||||
It("should SetGet", func() {
|
It("should SetGet", func() {
|
||||||
set := client.Set(ctx, "key", "hello", 0)
|
set := client.Set(ctx, "key", "hello", 0)
|
||||||
Expect(set.Err()).NotTo(HaveOccurred())
|
Expect(set.Err()).NotTo(HaveOccurred())
|
||||||
|
@ -1183,6 +1200,16 @@ var _ = Describe("Commands", func() {
|
||||||
Expect(val).To(Equal("hello"))
|
Expect(val).To(Equal("hello"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("should SetNX with keepttl", func() {
|
||||||
|
isSet, err := client.SetNX(ctx, "key", "hello1", redis.KeepTTL).Result()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(isSet).To(Equal(true))
|
||||||
|
|
||||||
|
ttl := client.TTL(ctx, "key")
|
||||||
|
Expect(ttl.Err()).NotTo(HaveOccurred())
|
||||||
|
Expect(ttl.Val().Nanoseconds()).To(Equal(int64(-1)))
|
||||||
|
})
|
||||||
|
|
||||||
It("should SetXX", func() {
|
It("should SetXX", func() {
|
||||||
isSet, err := client.SetXX(ctx, "key", "hello2", 0).Result()
|
isSet, err := client.SetXX(ctx, "key", "hello2", 0).Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
@ -1217,6 +1244,32 @@ var _ = Describe("Commands", func() {
|
||||||
Expect(val).To(Equal("hello2"))
|
Expect(val).To(Equal("hello2"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("should SetXX with keepttl", func() {
|
||||||
|
isSet, err := client.SetXX(ctx, "key", "hello2", time.Second).Result()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(isSet).To(Equal(false))
|
||||||
|
|
||||||
|
err = client.Set(ctx, "key", "hello", time.Second).Err()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
isSet, err = client.SetXX(ctx, "key", "hello2", 5*time.Second).Result()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(isSet).To(Equal(true))
|
||||||
|
|
||||||
|
isSet, err = client.SetXX(ctx, "key", "hello3", redis.KeepTTL).Result()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(isSet).To(Equal(true))
|
||||||
|
|
||||||
|
val, err := client.Get(ctx, "key").Result()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(val).To(Equal("hello3"))
|
||||||
|
|
||||||
|
// set keepttl will Retain the ttl associated with the key
|
||||||
|
ttl, err := client.TTL(ctx, "key").Result()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(ttl).NotTo(Equal(-1))
|
||||||
|
})
|
||||||
|
|
||||||
It("should SetRange", func() {
|
It("should SetRange", func() {
|
||||||
set := client.Set(ctx, "key", "Hello World", 0)
|
set := client.Set(ctx, "key", "Hello World", 0)
|
||||||
Expect(set.Err()).NotTo(HaveOccurred())
|
Expect(set.Err()).NotTo(HaveOccurred())
|
||||||
|
|
Loading…
Reference in New Issue