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())