This is an automated email from the ASF dual-hosted git repository.

hulk pushed a commit to branch unstable
in repository https://gitbox.apache.org/repos/asf/kvrocks.git


The following commit(s) were added to refs/heads/unstable by this push:
     new 59012ac3 Fix `GETEX` not working correctly on `Redis::Bitmap` (#1743)
59012ac3 is described below

commit 59012ac37389d1b4aa55d7382be7db800c4cdf84
Author: Jinze Wu <[email protected]>
AuthorDate: Thu Sep 7 16:30:28 2023 +0800

    Fix `GETEX` not working correctly on `Redis::Bitmap` (#1743)
---
 src/commands/cmd_string.cc                   |  8 +++++
 tests/gocase/unit/type/bitmap/bitmap_test.go | 47 ++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+)

diff --git a/src/commands/cmd_string.cc b/src/commands/cmd_string.cc
index b32d9db3..5950d6a7 100644
--- a/src/commands/cmd_string.cc
+++ b/src/commands/cmd_string.cc
@@ -25,6 +25,7 @@
 #include "commands/command_parser.h"
 #include "error_constants.h"
 #include "server/server.h"
+#include "storage/redis_db.h"
 #include "time_util.h"
 #include "ttl_util.h"
 #include "types/redis_bitmap.h"
@@ -86,6 +87,13 @@ class CommandGetEx : public Commander {
       uint32_t max_btos_size = 
static_cast<uint32_t>(config->max_bitmap_to_string_mb) * MiB;
       redis::Bitmap bitmap_db(svr->storage, conn->GetNamespace());
       s = bitmap_db.GetString(args_[1], max_btos_size, &value);
+      if (s.ok()) {
+        if (ttl_ > 0) {
+          s = bitmap_db.Expire(args_[1], ttl_ + util::GetTimeStampMS());
+        } else if (persist_) {
+          s = bitmap_db.Expire(args_[1], 0);
+        }
+      }
     }
     if (!s.ok() && !s.IsNotFound()) {
       return {Status::RedisExecErr, s.ToString()};
diff --git a/tests/gocase/unit/type/bitmap/bitmap_test.go 
b/tests/gocase/unit/type/bitmap/bitmap_test.go
index 192f638a..5b23389c 100644
--- a/tests/gocase/unit/type/bitmap/bitmap_test.go
+++ b/tests/gocase/unit/type/bitmap/bitmap_test.go
@@ -29,6 +29,7 @@ import (
        "strconv"
        "strings"
        "testing"
+       "time"
 
        "github.com/apache/kvrocks/tests/gocase/util"
        "github.com/redis/go-redis/v9"
@@ -139,6 +140,52 @@ func TestBitmap(t *testing.T) {
                util.ErrorRegexp(t, rdb.Get(ctx, "b0").Err(), "ERR Operation 
aborted: The size of the bitmap .*")
        })
 
+       t.Run("GETEX bitmap no option", func(t *testing.T) {
+               require.NoError(t, rdb.Del(ctx, "foo").Err())
+               require.NoError(t, rdb.SetBit(ctx, "foo", 0, 0).Err())
+               require.Equal(t, "\x00", rdb.GetEx(ctx, "foo", 0).Val())
+
+               // Make sure the expiration time is not erased by plain GETEX.
+               require.NoError(t, rdb.Expire(ctx, "foo", 10*time.Second).Err())
+               require.Equal(t, "\x00", rdb.Do(ctx, "getex", "foo").Val())
+               util.BetweenValues(t, rdb.TTL(ctx, "foo").Val(), 5*time.Second, 
10*time.Second)
+       })
+
+       t.Run("GETEX bitmap EX/EXAT/PX/PXAT option", func(t *testing.T) {
+               require.NoError(t, rdb.Del(ctx, "foo").Err())
+               require.NoError(t, rdb.SetBit(ctx, "foo", 0, 0).Err())
+               require.NoError(t, rdb.Do(ctx, "getex", "foo", "ex", 10).Err())
+               util.BetweenValues(t, rdb.TTL(ctx, "foo").Val(), 5*time.Second, 
10*time.Second)
+
+               require.NoError(t, rdb.Del(ctx, "foo").Err())
+               require.NoError(t, rdb.SetBit(ctx, "foo", 0, 0).Err())
+               require.NoError(t, rdb.Do(ctx, "getex", "foo", "exat", 
time.Now().Add(10*time.Second).Unix()).Err())
+               util.BetweenValues(t, rdb.TTL(ctx, "foo").Val(), 5*time.Second, 
10*time.Second)
+
+               require.NoError(t, rdb.Del(ctx, "foo").Err())
+               require.NoError(t, rdb.SetBit(ctx, "foo", 0, 0).Err())
+               require.NoError(t, rdb.Do(ctx, "getex", "foo", "px", 
10*1000).Err())
+               util.BetweenValues(t, rdb.TTL(ctx, "foo").Val(), 5*time.Second, 
10*time.Second)
+
+               require.NoError(t, rdb.Del(ctx, "foo").Err())
+               require.NoError(t, rdb.SetBit(ctx, "foo", 0, 0).Err())
+               require.NoError(t, rdb.Do(ctx, "getex", "foo", "pxat", 
time.Now().Add(10*time.Second).UnixMilli()).Err())
+               util.BetweenValues(t, rdb.TTL(ctx, "foo").Val(), 5*time.Second, 
10*time.Second)
+       })
+
+       t.Run("GETEX bitmap PERSIST option", func(t *testing.T) {
+               require.NoError(t, rdb.Del(ctx, "foo").Err())
+               require.NoError(t, rdb.SetBit(ctx, "foo", 0, 0).Err())
+               require.EqualValues(t, -1, rdb.TTL(ctx, "foo").Val())
+               require.NoError(t, rdb.Do(ctx, "getex", "foo", "persist").Err())
+               require.EqualValues(t, -1, rdb.TTL(ctx, "foo").Val())
+
+               require.NoError(t, rdb.Expire(ctx, "foo", 10*time.Second).Err())
+               util.BetweenValues(t, rdb.TTL(ctx, "foo").Val(), 5*time.Second, 
10*time.Second)
+               require.NoError(t, rdb.Do(ctx, "getex", "foo", "persist").Err())
+               require.EqualValues(t, -1, rdb.TTL(ctx, "foo").Val())
+       })
+
        t.Run("SETBIT/GETBIT/BITCOUNT/BITPOS boundary check (type bitmap)", 
func(t *testing.T) {
                cmd := rdb.Del(ctx, "b0")
                require.NoError(t, cmd.Err())

Reply via email to