You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kvrocks.apache.org by tw...@apache.org on 2023/03/24 16:36:48 UTC

[incubator-kvrocks] branch unstable updated: Round expire time for seconds to improve precision for 32bit-common-field encoding (#1352)

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

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


The following commit(s) were added to refs/heads/unstable by this push:
     new 95301c5a Round expire time for seconds to improve precision for 32bit-common-field encoding (#1352)
95301c5a is described below

commit 95301c5a673af83ad85e6dfb63da4db41d83afb8
Author: Twice <tw...@gmail.com>
AuthorDate: Sat Mar 25 00:36:41 2023 +0800

    Round expire time for seconds to improve precision for 32bit-common-field encoding (#1352)
---
 src/commands/cmd_key.cc                 | 6 +++---
 src/storage/redis_db.cc                 | 4 ++--
 src/storage/redis_db.h                  | 2 ++
 src/storage/redis_metadata.cc           | 3 ++-
 tests/cppunit/types/string_test.cc      | 8 ++++----
 tests/gocase/unit/expire/expire_test.go | 2 +-
 6 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/src/commands/cmd_key.cc b/src/commands/cmd_key.cc
index 8a75b2db..efd0cc57 100644
--- a/src/commands/cmd_key.cc
+++ b/src/commands/cmd_key.cc
@@ -115,13 +115,13 @@ class CommandExists : public Commander {
 class CommandExpire : public Commander {
  public:
   Status Parse(const std::vector<std::string> &args) override {
-    seconds_ = GET_OR_RET(ParseInt<int64_t>(args[2], 10)) + Util::GetTimeStamp();
+    ttl_ = GET_OR_RET(ParseInt<int64_t>(args[2], 10));
     return Status::OK();
   }
 
   Status Execute(Server *svr, Connection *conn, std::string *output) override {
     Redis::Database redis(svr->storage_, conn->GetNamespace());
-    auto s = redis.Expire(args_[1], seconds_ * 1000);
+    auto s = redis.Expire(args_[1], ttl_ * 1000 + Util::GetTimeStampMS());
     if (s.ok()) {
       *output = Redis::Integer(1);
     } else {
@@ -131,7 +131,7 @@ class CommandExpire : public Commander {
   }
 
  private:
-  uint64_t seconds_ = 0;
+  uint64_t ttl_ = 0;
 };
 
 class CommandPExpire : public Commander {
diff --git a/src/storage/redis_db.cc b/src/storage/redis_db.cc
index c347caa4..6d2a2d1b 100644
--- a/src/storage/redis_db.cc
+++ b/src/storage/redis_db.cc
@@ -324,13 +324,13 @@ rocksdb::Status Database::RandomKey(const std::string &cursor, std::string *key)
 
   std::string end_cursor;
   std::vector<std::string> keys;
-  auto s = Scan(cursor, 60, "", &keys, &end_cursor);
+  auto s = Scan(cursor, RANDOM_KEY_SCAN_LIMIT, "", &keys, &end_cursor);
   if (!s.ok()) {
     return s;
   }
   if (keys.empty() && !cursor.empty()) {
     // if reach the end, restart from beginning
-    s = Scan("", 60, "", &keys, &end_cursor);
+    s = Scan("", RANDOM_KEY_SCAN_LIMIT, "", &keys, &end_cursor);
     if (!s.ok()) {
       return s;
     }
diff --git a/src/storage/redis_db.h b/src/storage/redis_db.h
index 18012bf5..437ef825 100644
--- a/src/storage/redis_db.h
+++ b/src/storage/redis_db.h
@@ -31,6 +31,8 @@
 namespace Redis {
 class Database {
  public:
+  static constexpr uint64_t RANDOM_KEY_SCAN_LIMIT = 60;
+
   explicit Database(Engine::Storage *storage, std::string ns = "");
   rocksdb::Status GetMetadata(RedisType type, const Slice &ns_key, Metadata *metadata);
   rocksdb::Status GetRawMetadata(const Slice &ns_key, std::string *bytes);
diff --git a/src/storage/redis_metadata.cc b/src/storage/redis_metadata.cc
index 73580abd..aa5b26fe 100644
--- a/src/storage/redis_metadata.cc
+++ b/src/storage/redis_metadata.cc
@@ -233,7 +233,8 @@ uint64_t Metadata::ExpireMsToS(uint64_t ms) {
     return 1;
   }
 
-  return ms / 1000;
+  // We use rounding to get closer to the original value
+  return (ms + 499) / 1000;
 }
 
 bool Metadata::Is64BitEncoded() const { return flags & METADATA_64BIT_ENCODING_MASK; }
diff --git a/tests/cppunit/types/string_test.cc b/tests/cppunit/types/string_test.cc
index b2b4b26a..61755b9b 100644
--- a/tests/cppunit/types/string_test.cc
+++ b/tests/cppunit/types/string_test.cc
@@ -179,7 +179,7 @@ TEST_F(RedisStringTest, MSetXX) {
   EXPECT_EQ(ret, 1);
   int64_t ttl = 0;
   string->TTL(key_, &ttl);
-  EXPECT_TRUE(ttl >= 2000 && ttl <= 3000);
+  EXPECT_TRUE(ttl >= 2000 && ttl <= 4000);
   string->Del(key_);
 }
 
@@ -214,7 +214,7 @@ TEST_F(RedisStringTest, MSetNXWithTTL) {
   string->SetNX(key_, "test-value", 3000, &ret);
   int64_t ttl = 0;
   string->TTL(key_, &ttl);
-  EXPECT_TRUE(ttl >= 2000 && ttl <= 3000);
+  EXPECT_TRUE(ttl >= 2000 && ttl <= 4000);
   string->Del(key_);
 }
 
@@ -222,7 +222,7 @@ TEST_F(RedisStringTest, SetEX) {
   string->SetEX(key_, "test-value", 3000);
   int64_t ttl = 0;
   string->TTL(key_, &ttl);
-  EXPECT_TRUE(ttl >= 2000 && ttl <= 3000);
+  EXPECT_TRUE(ttl >= 2000 && ttl <= 4000);
   string->Del(key_);
 }
 
@@ -277,7 +277,7 @@ TEST_F(RedisStringTest, CAS) {
 
   int64_t ttl = 0;
   string->TTL(key, &ttl);
-  EXPECT_TRUE(ttl >= 9000 && ttl <= 10000);
+  EXPECT_TRUE(ttl >= 9000 && ttl <= 11000);
 
   string->Del(key);
 }
diff --git a/tests/gocase/unit/expire/expire_test.go b/tests/gocase/unit/expire/expire_test.go
index d35b84d8..8a691966 100644
--- a/tests/gocase/unit/expire/expire_test.go
+++ b/tests/gocase/unit/expire/expire_test.go
@@ -168,7 +168,7 @@ func TestExpire(t *testing.T) {
 	t.Run("PTTL returns time to live in milliseconds", func(t *testing.T) {
 		require.NoError(t, rdb.Del(ctx, "x").Err())
 		require.NoError(t, rdb.SetEx(ctx, "x", "somevalue", 2*time.Second).Err())
-		util.BetweenValues(t, rdb.PTTL(ctx, "x").Val(), 50*time.Millisecond, 2000*time.Millisecond)
+		util.BetweenValues(t, rdb.PTTL(ctx, "x").Val(), 500*time.Millisecond, 2500*time.Millisecond)
 	})
 
 	t.Run("TTL / PTTL return -1 if key has no expire", func(t *testing.T) {