diff --git a/commands_test.go b/commands_test.go index 5256a6fbf..dbce8f9de 100644 --- a/commands_test.go +++ b/commands_test.go @@ -819,6 +819,74 @@ var _ = Describe("Commands", func() { Expect(ttl.Val()).To(Equal(time.Duration(-2))) }) + It("should ExpireNX", func() { + set := client.Set(ctx, "key", "Hello", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + expire := client.ExpireNX(ctx, "key", 10*time.Second) + Expect(expire.Err()).NotTo(HaveOccurred()) + Expect(expire.Val()).To(Equal(true)) + }) + + It("should ExpireXX", func() { + set := client.Set(ctx, "key", "Hello", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + expire := client.ExpireXX(ctx, "key", 10*time.Second) + Expect(expire.Err()).NotTo(HaveOccurred()) + Expect(expire.Val()).To(Equal(false)) + + expire = client.Expire(ctx, "key", 10*time.Second) + Expect(expire.Err()).NotTo(HaveOccurred()) + Expect(expire.Val()).To(Equal(true)) + + expire = client.ExpireXX(ctx, "key", 20*time.Second) + Expect(expire.Err()).NotTo(HaveOccurred()) + Expect(expire.Val()).To(Equal(true)) + + ttl := client.TTL(ctx, "key") + Expect(ttl.Err()).NotTo(HaveOccurred()) + Expect(ttl.Val()).To(BeNumerically("~", 20*time.Second, 10*time.Second)) + }) + + It("should ExpireGT", func() { + set := client.Set(ctx, "key", "Hello", 10*time.Second) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + expire := client.ExpireGT(ctx, "key", 5*time.Second) + Expect(expire.Err()).NotTo(HaveOccurred()) + Expect(expire.Val()).To(Equal(false)) + + expire = client.ExpireGT(ctx, "key", 20*time.Second) + Expect(expire.Err()).NotTo(HaveOccurred()) + Expect(expire.Val()).To(Equal(true)) + + ttl := client.TTL(ctx, "key") + Expect(ttl.Err()).NotTo(HaveOccurred()) + Expect(ttl.Val()).To(BeNumerically("~", 20*time.Second, 10*time.Second)) + }) + + It("should ExpireLT", func() { + set := client.Set(ctx, "key", "Hello", 10*time.Second) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + expire := client.ExpireLT(ctx, "key", 20*time.Second) + Expect(expire.Err()).NotTo(HaveOccurred()) + Expect(expire.Val()).To(Equal(false)) + + expire = client.ExpireLT(ctx, "key", 5*time.Second) + Expect(expire.Err()).NotTo(HaveOccurred()) + Expect(expire.Val()).To(Equal(true)) + + ttl := client.TTL(ctx, "key") + Expect(ttl.Err()).NotTo(HaveOccurred()) + Expect(ttl.Val()).To(BeNumerically("~", 5*time.Second, time.Second)) + }) + It("should ExpireAt", func() { setCmd := client.Set(ctx, "key", "Hello", 0) Expect(setCmd.Err()).NotTo(HaveOccurred()) @@ -848,6 +916,124 @@ var _ = Describe("Commands", func() { Expect(n).To(Equal(int64(0))) }) + It("should ExpireAtNX", func() { + set := client.Set(ctx, "key", "Hello", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + n, err := client.Exists(ctx, "key").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(n).To(Equal(int64(1))) + + expireAt := time.Now().Add(time.Minute) + expireAtCmd := client.ExpireAtNX(ctx, "key", expireAt) + Expect(expireAtCmd.Err()).NotTo(HaveOccurred()) + Expect(expireAtCmd.Val()).To(Equal(true)) + + timeCmd := client.ExpireTime(ctx, "key") + Expect(timeCmd.Err()).NotTo(HaveOccurred()) + Expect(timeCmd.Val().Seconds()).To(BeNumerically("==", expireAt.Unix())) + + expireAt2 := expireAt.Add(time.Minute) + expireAtCmd = client.ExpireAtNX(ctx, "key", expireAt2) + Expect(expireAtCmd.Err()).NotTo(HaveOccurred()) + Expect(expireAtCmd.Val()).To(Equal(false)) + }) + + It("should ExpireAtXX", func() { + set := client.Set(ctx, "key", "Hello", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + n, err := client.Exists(ctx, "key").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(n).To(Equal(int64(1))) + + expireAt := time.Now().Add(time.Minute) + expireAtCmd := client.ExpireAtXX(ctx, "key", expireAt) + Expect(expireAtCmd.Err()).NotTo(HaveOccurred()) + Expect(expireAtCmd.Val()).To(Equal(false)) + + expireAtCmd = client.ExpireAt(ctx, "key", expireAt) + Expect(expireAtCmd.Err()).NotTo(HaveOccurred()) + Expect(expireAtCmd.Val()).To(Equal(true)) + + expireAt2 := expireAt.Add(time.Minute) + expireAtCmd = client.ExpireAtXX(ctx, "key", expireAt2) + Expect(expireAtCmd.Err()).NotTo(HaveOccurred()) + Expect(expireAtCmd.Val()).To(Equal(true)) + + timeCmd := client.ExpireTime(ctx, "key") + Expect(timeCmd.Err()).NotTo(HaveOccurred()) + Expect(timeCmd.Val().Seconds()).To(BeNumerically("==", expireAt2.Unix())) + }) + + It("should ExpireAtGT", func() { + set := client.Set(ctx, "key", "Hello", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + n, err := client.Exists(ctx, "key").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(n).To(Equal(int64(1))) + + expireAt := time.Now().Add(2 * time.Minute) + expireAtCmd := client.ExpireAt(ctx, "key", expireAt) + Expect(expireAtCmd.Err()).NotTo(HaveOccurred()) + Expect(expireAtCmd.Val()).To(Equal(true)) + + timeCmd := client.ExpireTime(ctx, "key") + Expect(timeCmd.Err()).NotTo(HaveOccurred()) + Expect(timeCmd.Val().Seconds()).To(BeNumerically("==", expireAt.Unix())) + + expireAt2 := expireAt.Add(-time.Minute) + expireAtCmd = client.ExpireAtGT(ctx, "key", expireAt2) + Expect(expireAtCmd.Err()).NotTo(HaveOccurred()) + Expect(expireAtCmd.Val()).To(Equal(false)) + + expireAt3 := expireAt.Add(time.Minute) + expireAtCmd = client.ExpireAtGT(ctx, "key", expireAt3) + Expect(expireAtCmd.Err()).NotTo(HaveOccurred()) + Expect(expireAtCmd.Val()).To(Equal(true)) + + timeCmd = client.ExpireTime(ctx, "key") + Expect(timeCmd.Err()).NotTo(HaveOccurred()) + Expect(timeCmd.Val().Seconds()).To(BeNumerically("==", expireAt3.Unix())) + }) + + It("should ExpireAtLT", func() { + set := client.Set(ctx, "key", "Hello", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + n, err := client.Exists(ctx, "key").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(n).To(Equal(int64(1))) + + expireAt := time.Now().Add(2 * time.Minute) + expireAtCmd := client.ExpireAt(ctx, "key", expireAt) + Expect(expireAtCmd.Err()).NotTo(HaveOccurred()) + Expect(expireAtCmd.Val()).To(Equal(true)) + + timeCmd := client.ExpireTime(ctx, "key") + Expect(timeCmd.Err()).NotTo(HaveOccurred()) + Expect(timeCmd.Val().Seconds()).To(BeNumerically("==", expireAt.Unix())) + + expireAt2 := expireAt.Add(time.Minute) + expireAtCmd = client.ExpireAtLT(ctx, "key", expireAt2) + Expect(expireAtCmd.Err()).NotTo(HaveOccurred()) + Expect(expireAtCmd.Val()).To(Equal(false)) + + expireAt3 := expireAt.Add(-1 * time.Minute) + expireAtCmd = client.ExpireAtLT(ctx, "key", expireAt3) + Expect(expireAtCmd.Err()).NotTo(HaveOccurred()) + Expect(expireAtCmd.Val()).To(Equal(true)) + + timeCmd = client.ExpireTime(ctx, "key") + Expect(timeCmd.Err()).NotTo(HaveOccurred()) + Expect(timeCmd.Val().Seconds()).To(BeNumerically("==", expireAt3.Unix())) + }) + It("should Keys", func() { mset := client.MSet(ctx, "one", "1", "two", "2", "three", "3", "four", "4") Expect(mset.Err()).NotTo(HaveOccurred()) @@ -977,6 +1163,116 @@ var _ = Describe("Commands", func() { Expect(pttl.Val()).To(BeNumerically("~", expiration, 100*time.Millisecond)) }) + It("should PExpireNX", func() { + set := client.Set(ctx, "key", "Hello", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + expiration := 5000 * time.Millisecond + pexpire := client.PExpireNX(ctx, "key", expiration) + Expect(pexpire.Err()).NotTo(HaveOccurred()) + Expect(pexpire.Val()).To(Equal(true)) + + pttl := client.PTTL(ctx, "key") + Expect(pttl.Err()).NotTo(HaveOccurred()) + Expect(pttl.Val()).To(BeNumerically("~", expiration, 100*time.Millisecond)) + + expiration2 := 1900 * time.Millisecond + pexpire = client.PExpireNX(ctx, "key", expiration2) + Expect(pexpire.Err()).NotTo(HaveOccurred()) + Expect(pexpire.Val()).To(Equal(false)) + + pttl = client.PTTL(ctx, "key") + Expect(pttl.Err()).NotTo(HaveOccurred()) + Expect(pttl.Val()).To(BeNumerically("~", expiration, expiration2)) + }) + + It("should PExpireXX", func() { + set := client.Set(ctx, "key", "Hello", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + expiration := 2000 * time.Millisecond + pexpire := client.PExpireXX(ctx, "key", expiration) + Expect(pexpire.Err()).NotTo(HaveOccurred()) + Expect(pexpire.Val()).To(Equal(false)) + + pexpire = client.PExpire(ctx, "key", expiration) + Expect(pexpire.Err()).NotTo(HaveOccurred()) + Expect(pexpire.Val()).To(Equal(true)) + + pttl := client.PTTL(ctx, "key") + Expect(pttl.Err()).NotTo(HaveOccurred()) + Expect(pttl.Val()).To(BeNumerically("~", expiration, 100*time.Millisecond)) + + expiration2 := 5000 * time.Millisecond + pexpire = client.PExpireXX(ctx, "key", expiration2) + Expect(pexpire.Err()).NotTo(HaveOccurred()) + Expect(pexpire.Val()).To(Equal(true)) + + pttl = client.PTTL(ctx, "key") + Expect(pttl.Err()).NotTo(HaveOccurred()) + Expect(pttl.Val()).To(BeNumerically("~", expiration2, expiration)) + }) + + It("should PExpireGT", func() { + set := client.Set(ctx, "key", "Hello", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + expiration := 10000 * time.Millisecond + pexpire := client.PExpire(ctx, "key", expiration) + Expect(pexpire.Err()).NotTo(HaveOccurred()) + Expect(pexpire.Val()).To(Equal(true)) + + pttl := client.PTTL(ctx, "key") + Expect(pttl.Err()).NotTo(HaveOccurred()) + Expect(pttl.Val()).To(BeNumerically("~", expiration, 100*time.Millisecond)) + + expiration2 := 5000 * time.Millisecond + pexpire = client.PExpireGT(ctx, "key", expiration2) + Expect(pexpire.Err()).NotTo(HaveOccurred()) + Expect(pexpire.Val()).To(Equal(false)) + + expiration3 := 20000 * time.Millisecond + pexpire = client.PExpireGT(ctx, "key", expiration3) + Expect(pexpire.Err()).NotTo(HaveOccurred()) + Expect(pexpire.Val()).To(Equal(true)) + + pttl = client.PTTL(ctx, "key") + Expect(pttl.Err()).NotTo(HaveOccurred()) + Expect(pttl.Val()).To(BeNumerically("~", expiration3, expiration)) + }) + + It("should PExpireLT", func() { + set := client.Set(ctx, "key", "Hello", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + expiration := 10000 * time.Millisecond + pexpire := client.PExpire(ctx, "key", expiration) + Expect(pexpire.Err()).NotTo(HaveOccurred()) + Expect(pexpire.Val()).To(Equal(true)) + + pttl := client.PTTL(ctx, "key") + Expect(pttl.Err()).NotTo(HaveOccurred()) + Expect(pttl.Val()).To(BeNumerically("~", expiration, 100*time.Millisecond)) + + expiration2 := 20000 * time.Millisecond + pexpire = client.PExpireLT(ctx, "key", expiration2) + Expect(pexpire.Err()).NotTo(HaveOccurred()) + Expect(pexpire.Val()).To(Equal(false)) + + expiration3 := 5000 * time.Millisecond + pexpire = client.PExpireLT(ctx, "key", expiration3) + Expect(pexpire.Err()).NotTo(HaveOccurred()) + Expect(pexpire.Val()).To(Equal(true)) + + pttl = client.PTTL(ctx, "key") + Expect(pttl.Err()).NotTo(HaveOccurred()) + Expect(pttl.Val()).To(BeNumerically("~", expiration3, 100*time.Millisecond)) + }) + It("should PExpireAt", func() { set := client.Set(ctx, "key", "Hello", 0) Expect(set.Err()).NotTo(HaveOccurred()) @@ -996,6 +1292,129 @@ var _ = Describe("Commands", func() { Expect(pttl.Val()).To(BeNumerically("~", expiration, 100*time.Millisecond)) }) + It("should PExpireAtNX", func() { + set := client.Set(ctx, "key", "Hello", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + expiration := 5000 * time.Millisecond + pexpireAt := time.Now().Add(expiration) + pexpireAtCmd := client.PExpireAtNX(ctx, "key", pexpireAt) + Expect(pexpireAtCmd.Err()).NotTo(HaveOccurred()) + Expect(pexpireAtCmd.Val()).To(Equal(true)) + + pttl := client.PTTL(ctx, "key") + Expect(pttl.Err()).NotTo(HaveOccurred()) + Expect(pttl.Val()).To(BeNumerically("~", expiration, 100*time.Millisecond)) + + expiration2 := 3000 * time.Millisecond + pexpireAt2 := pexpireAt.Add(expiration2) + pexpireAtCmd = client.PExpireAtNX(ctx, "key", pexpireAt2) + Expect(pexpireAtCmd.Err()).NotTo(HaveOccurred()) + Expect(pexpireAtCmd.Val()).To(Equal(false)) + + pttl = client.PTTL(ctx, "key") + Expect(pttl.Err()).NotTo(HaveOccurred()) + Expect(pttl.Val()).To(BeNumerically("~", expiration, 100*time.Millisecond)) + }) + + It("should PExpireAtXX", func() { + set := client.Set(ctx, "key", "Hello", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + now := time.Now() + expiration := 900 * time.Millisecond + pexpireAt := now.Add(expiration) + pexpireAtCmd := client.PExpireAtXX(ctx, "key", pexpireAt) + Expect(pexpireAtCmd.Err()).NotTo(HaveOccurred()) + Expect(pexpireAtCmd.Val()).To(Equal(false)) + + pexpireAtCmd = client.PExpireAt(ctx, "key", pexpireAt) + Expect(pexpireAtCmd.Err()).NotTo(HaveOccurred()) + Expect(pexpireAtCmd.Val()).To(Equal(true)) + + pttl := client.PTTL(ctx, "key") + Expect(pttl.Err()).NotTo(HaveOccurred()) + Expect(pttl.Val()).To(BeNumerically("~", expiration, 100*time.Millisecond)) + + expiration2 := 1900 * time.Millisecond + pexpireAt2 := now.Add(expiration2) + pexpireAtCmd = client.PExpireAtXX(ctx, "key", pexpireAt2) + Expect(pexpireAtCmd.Err()).NotTo(HaveOccurred()) + Expect(pexpireAtCmd.Val()).To(Equal(true)) + + pttl = client.PTTL(ctx, "key") + Expect(pttl.Err()).NotTo(HaveOccurred()) + Expect(pttl.Val()).To(BeNumerically("~", expiration2, expiration)) + }) + + It("should PExpireAtGT", func() { + set := client.Set(ctx, "key", "Hello", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + now := time.Now() + expiration := 10000 * time.Millisecond + pexpireAt := now.Add(expiration) + pexpireAtCmd := client.PExpireAt(ctx, "key", pexpireAt) + Expect(pexpireAtCmd.Err()).NotTo(HaveOccurred()) + Expect(pexpireAtCmd.Val()).To(Equal(true)) + + pttl := client.PTTL(ctx, "key") + Expect(pttl.Err()).NotTo(HaveOccurred()) + Expect(pttl.Val()).To(BeNumerically("~", expiration, 100*time.Millisecond)) + + expiration2 := 5000 * time.Millisecond + pexpireAt2 := now.Add(expiration2) + pexpireAtCmd = client.PExpireAtGT(ctx, "key", pexpireAt2) + Expect(pexpireAtCmd.Err()).NotTo(HaveOccurred()) + Expect(pexpireAtCmd.Val()).To(Equal(false)) + + expiration3 := 15000 * time.Millisecond + pexpireAt3 := now.Add(expiration3) + pexpireAtCmd = client.PExpireAtGT(ctx, "key", pexpireAt3) + Expect(pexpireAtCmd.Err()).NotTo(HaveOccurred()) + Expect(pexpireAtCmd.Val()).To(Equal(true)) + + pttl = client.PTTL(ctx, "key") + Expect(pttl.Err()).NotTo(HaveOccurred()) + Expect(pttl.Val()).To(BeNumerically("~", expiration3, expiration)) + }) + + It("should PExpireAtLT", func() { + set := client.Set(ctx, "key", "Hello", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + now := time.Now() + expiration := 10000 * time.Millisecond + pexpireAt := now.Add(expiration) + pexpireAtCmd := client.PExpireAt(ctx, "key", pexpireAt) + Expect(pexpireAtCmd.Err()).NotTo(HaveOccurred()) + Expect(pexpireAtCmd.Val()).To(Equal(true)) + + pttl := client.PTTL(ctx, "key") + Expect(pttl.Err()).NotTo(HaveOccurred()) + Expect(pttl.Val()).To(BeNumerically("~", expiration, 100*time.Millisecond)) + + expiration2 := 15000 * time.Millisecond + pexpireAt2 := now.Add(expiration2) + pexpireAtCmd = client.PExpireAtLT(ctx, "key", pexpireAt2) + Expect(pexpireAtCmd.Err()).NotTo(HaveOccurred()) + Expect(pexpireAtCmd.Val()).To(Equal(false)) + + expiration3 := 5000 * time.Millisecond + pexpireAt3 := now.Add(expiration3) + pexpireAtCmd = client.PExpireAtLT(ctx, "key", pexpireAt3) + Expect(pexpireAtCmd.Err()).NotTo(HaveOccurred()) + Expect(pexpireAtCmd.Val()).To(Equal(true)) + + pttl = client.PTTL(ctx, "key") + Expect(pttl.Err()).NotTo(HaveOccurred()) + Expect(pttl.Val()).To(BeNumerically("~", expiration3, 100*time.Millisecond)) + }) + It("should PExpireTime", func() { // The command returns -1 if the key exists but has no associated expiration time. // The command returns -2 if the key does not exist. diff --git a/generic_commands.go b/generic_commands.go index dc6c3fe01..1251fa377 100644 --- a/generic_commands.go +++ b/generic_commands.go @@ -10,12 +10,16 @@ type GenericCmdable interface { Dump(ctx context.Context, key string) *StringCmd Exists(ctx context.Context, keys ...string) *IntCmd Expire(ctx context.Context, key string, expiration time.Duration) *BoolCmd - ExpireAt(ctx context.Context, key string, tm time.Time) *BoolCmd - ExpireTime(ctx context.Context, key string) *DurationCmd ExpireNX(ctx context.Context, key string, expiration time.Duration) *BoolCmd ExpireXX(ctx context.Context, key string, expiration time.Duration) *BoolCmd ExpireGT(ctx context.Context, key string, expiration time.Duration) *BoolCmd ExpireLT(ctx context.Context, key string, expiration time.Duration) *BoolCmd + ExpireAt(ctx context.Context, key string, tm time.Time) *BoolCmd + ExpireAtNX(ctx context.Context, key string, tm time.Time) *BoolCmd + ExpireAtXX(ctx context.Context, key string, tm time.Time) *BoolCmd + ExpireAtGT(ctx context.Context, key string, tm time.Time) *BoolCmd + ExpireAtLT(ctx context.Context, key string, tm time.Time) *BoolCmd + ExpireTime(ctx context.Context, key string) *DurationCmd Keys(ctx context.Context, pattern string) *StringSliceCmd Migrate(ctx context.Context, host, port, key string, db int, timeout time.Duration) *StatusCmd Move(ctx context.Context, key string, db int) *BoolCmd @@ -25,7 +29,15 @@ type GenericCmdable interface { ObjectIdleTime(ctx context.Context, key string) *DurationCmd Persist(ctx context.Context, key string) *BoolCmd PExpire(ctx context.Context, key string, expiration time.Duration) *BoolCmd + PExpireNX(ctx context.Context, key string, expiration time.Duration) *BoolCmd + PExpireXX(ctx context.Context, key string, expiration time.Duration) *BoolCmd + PExpireGT(ctx context.Context, key string, expiration time.Duration) *BoolCmd + PExpireLT(ctx context.Context, key string, expiration time.Duration) *BoolCmd PExpireAt(ctx context.Context, key string, tm time.Time) *BoolCmd + PExpireAtNX(ctx context.Context, key string, tm time.Time) *BoolCmd + PExpireAtXX(ctx context.Context, key string, tm time.Time) *BoolCmd + PExpireAtGT(ctx context.Context, key string, tm time.Time) *BoolCmd + PExpireAtLT(ctx context.Context, key string, tm time.Time) *BoolCmd PExpireTime(ctx context.Context, key string) *DurationCmd PTTL(ctx context.Context, key string) *DurationCmd RandomKey(ctx context.Context) *StringCmd @@ -122,9 +134,39 @@ func (c cmdable) expire( } func (c cmdable) ExpireAt(ctx context.Context, key string, tm time.Time) *BoolCmd { - cmd := NewBoolCmd(ctx, "expireat", key, tm.Unix()) - _ = c(ctx, cmd) - return cmd + return c.expireAt(ctx, key, tm, "") +} + +func (c cmdable) ExpireAtNX(ctx context.Context, key string, tm time.Time) *BoolCmd { + return c.expireAt(ctx, key, tm, "NX") +} + +func (c cmdable) ExpireAtXX(ctx context.Context, key string, tm time.Time) *BoolCmd { + return c.expireAt(ctx, key, tm, "XX") +} + +func (c cmdable) ExpireAtGT(ctx context.Context, key string, tm time.Time) *BoolCmd { + return c.expireAt(ctx, key, tm, "GT") +} + +func (c cmdable) ExpireAtLT(ctx context.Context, key string, tm time.Time) *BoolCmd { + return c.expireAt(ctx, key, tm, "LT") +} + +func (c cmdable) expireAt( + ctx context.Context, key string, tm time.Time, mode string, +) *BoolCmd { + args := make([]interface{}, 3, 4) + args[0] = "expireat" + args[1] = key + args[2] = tm.Unix() + if mode != "" { + args = append(args, mode) + } + + cmd := NewBoolCmd(ctx, args...) + _ = c(ctx, cmd) + return cmd } func (c cmdable) ExpireTime(ctx context.Context, key string) *DurationCmd { @@ -191,20 +233,75 @@ func (c cmdable) Persist(ctx context.Context, key string) *BoolCmd { } func (c cmdable) PExpire(ctx context.Context, key string, expiration time.Duration) *BoolCmd { - cmd := NewBoolCmd(ctx, "pexpire", key, formatMs(ctx, expiration)) - _ = c(ctx, cmd) - return cmd + return c.pexpire(ctx, key, expiration, "") +} + +func (c cmdable) PExpireNX(ctx context.Context, key string, expiration time.Duration) *BoolCmd { + return c.pexpire(ctx, key, expiration, "NX") +} + +func (c cmdable) PExpireXX(ctx context.Context, key string, expiration time.Duration) *BoolCmd { + return c.pexpire(ctx, key, expiration, "XX") +} + +func (c cmdable) PExpireGT(ctx context.Context, key string, expiration time.Duration) *BoolCmd { + return c.pexpire(ctx, key, expiration, "GT") +} + +func (c cmdable) PExpireLT(ctx context.Context, key string, expiration time.Duration) *BoolCmd { + return c.pexpire(ctx, key, expiration, "LT") +} + +func (c cmdable) pexpire( + ctx context.Context, key string, expiration time.Duration, mode string, +) *BoolCmd { + args := make([]interface{}, 3, 4) + args[0] = "pexpire" + args[1] = key + args[2] = formatMs(ctx, expiration) + if mode != "" { + args = append(args, mode) + } + + cmd := NewBoolCmd(ctx, args...) + _ = c(ctx, cmd) + return cmd } func (c cmdable) PExpireAt(ctx context.Context, key string, tm time.Time) *BoolCmd { - cmd := NewBoolCmd( - ctx, - "pexpireat", - key, - tm.UnixNano()/int64(time.Millisecond), - ) - _ = c(ctx, cmd) - return cmd + return c.pexpireAt(ctx, key, tm, "") +} + +func (c cmdable) PExpireAtNX(ctx context.Context, key string, tm time.Time) *BoolCmd { + return c.pexpireAt(ctx, key, tm, "NX") +} + +func (c cmdable) PExpireAtXX(ctx context.Context, key string, tm time.Time) *BoolCmd { + return c.pexpireAt(ctx, key, tm, "XX") +} + +func (c cmdable) PExpireAtGT(ctx context.Context, key string, tm time.Time) *BoolCmd { + return c.pexpireAt(ctx, key, tm, "GT") +} + +func (c cmdable) PExpireAtLT(ctx context.Context, key string, tm time.Time) *BoolCmd { + return c.pexpireAt(ctx, key, tm, "LT") +} + +func (c cmdable) pexpireAt( + ctx context.Context, key string, tm time.Time, mode string, +) *BoolCmd { + args := make([]interface{}, 3, 4) + args[0] = "pexpireat" + args[1] = key + args[2] = tm.UnixNano() / int64(time.Millisecond) + if mode != "" { + args = append(args, mode) + } + + cmd := NewBoolCmd(ctx, args...) + _ = c(ctx, cmd) + return cmd } func (c cmdable) PExpireTime(ctx context.Context, key string) *DurationCmd {