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/kvrocks.git


The following commit(s) were added to refs/heads/unstable by this push:
     new 941e20d48 feat(function): support subcommand FUNCTION FLUSH (#3119)
941e20d48 is described below

commit 941e20d48e748f79f25166d101de257abc3b191a
Author: Twice <[email protected]>
AuthorDate: Sat Aug 16 12:55:31 2025 +0800

    feat(function): support subcommand FUNCTION FLUSH (#3119)
---
 src/commands/cmd_function.cc                 |  6 ++++++
 src/storage/scripting.cc                     | 17 +++++++++++++++++
 src/storage/scripting.h                      |  1 +
 src/storage/storage.cc                       |  6 ++----
 tests/gocase/unit/scripting/function_test.go | 13 +++++++++++--
 5 files changed, 37 insertions(+), 6 deletions(-)

diff --git a/src/commands/cmd_function.cc b/src/commands/cmd_function.cc
index 1d5ef8461..7d2934d86 100644
--- a/src/commands/cmd_function.cc
+++ b/src/commands/cmd_function.cc
@@ -75,6 +75,12 @@ struct CommandFunction : Commander {
       auto s = lua::FunctionDelete(ctx, conn, libname);
       if (!s) return s;
 
+      *output = RESP_OK;
+      return Status::OK();
+    } else if (parser.EatEqICase("flush")) {
+      auto s = lua::FunctionFlush(conn, &ctx);
+      if (!s) return s;
+
       *output = RESP_OK;
       return Status::OK();
     } else {
diff --git a/src/storage/scripting.cc b/src/storage/scripting.cc
index d4b9a2546..c9d88270e 100644
--- a/src/storage/scripting.cc
+++ b/src/storage/scripting.cc
@@ -42,6 +42,7 @@
 #include "server/server.h"
 #include "sha1.h"
 #include "storage/storage.h"
+#include "string_util.h"
 
 /* The maximum number of characters needed to represent a long double
  * as a string (long double has a huge range).
@@ -613,6 +614,22 @@ Status FunctionDelete(engine::Context &ctx, 
redis::Connection *conn, const std::
   return Status::OK();
 }
 
+Status FunctionFlush(redis::Connection *conn, engine::Context *ctx) {
+  auto storage = conn->GetServer()->storage;
+  auto cf = storage->GetCFHandle(ColumnFamilyID::Propagate);
+
+  auto s = storage->DeleteRange(*ctx, rocksdb::WriteOptions(), cf, 
engine::kLuaLibCodePrefix,
+                                util::StringNext(engine::kLuaLibCodePrefix));
+  if (!s.ok()) return {Status::NotOK, s.ToString()};
+
+  s = storage->DeleteRange(*ctx, rocksdb::WriteOptions(), cf, 
engine::kLuaFuncLibPrefix,
+                           util::StringNext(engine::kLuaFuncLibPrefix));
+  if (!s.ok()) return {Status::NotOK, s.ToString()};
+
+  conn->GetServer()->ScriptReset();
+  return Status::OK();
+}
+
 Status EvalGenericCommand(redis::Connection *conn, engine::Context *ctx, const 
std::string &body_or_sha,
                           const std::vector<std::string> &keys, const 
std::vector<std::string> &argv, bool evalsha,
                           std::string *output, bool read_only) {
diff --git a/src/storage/scripting.h b/src/storage/scripting.h
index 86130aac4..c28ab6689 100644
--- a/src/storage/scripting.h
+++ b/src/storage/scripting.h
@@ -82,6 +82,7 @@ Status FunctionListLib(redis::Connection *conn, const 
std::string &libname, std:
 Status FunctionDelete(engine::Context &ctx, redis::Connection *conn, const 
std::string &name);
 bool FunctionIsLibExist(redis::Connection *conn, engine::Context *ctx, const 
std::string &libname,
                         bool need_check_storage = true);
+Status FunctionFlush(redis::Connection *conn, engine::Context *ctx);
 
 const char *RedisProtocolToLuaType(lua_State *lua, const char *reply);
 const char *RedisProtocolToLuaTypeInt(lua_State *lua, const char *reply);
diff --git a/src/storage/storage.cc b/src/storage/storage.cc
index b1f9856b0..551b0ec3b 100644
--- a/src/storage/storage.cc
+++ b/src/storage/storage.cc
@@ -48,6 +48,7 @@
 #include "rocksdb_crc32c.h"
 #include "server/server.h"
 #include "storage/batch_indexer.h"
+#include "string_util.h"
 #include "table_properties_collector.h"
 #include "time_util.h"
 #include "unique_fd.h"
@@ -760,10 +761,7 @@ rocksdb::Status Storage::DeleteRange(engine::Context &ctx, 
Slice begin, Slice en
 
 rocksdb::Status Storage::FlushScripts(engine::Context &ctx, const 
rocksdb::WriteOptions &options,
                                       rocksdb::ColumnFamilyHandle *cf_handle) {
-  std::string begin_key = kLuaFuncSHAPrefix, end_key = begin_key;
-  // we need to increase one here since the DeleteRange api
-  // didn't contain the end key.
-  end_key[end_key.size() - 1] += 1;
+  std::string begin_key = kLuaFuncSHAPrefix, end_key = 
util::StringNext(kLuaFuncSHAPrefix);
 
   auto batch = GetWriteBatchBase();
   auto s = batch->DeleteRange(cf_handle, begin_key, end_key);
diff --git a/tests/gocase/unit/scripting/function_test.go 
b/tests/gocase/unit/scripting/function_test.go
index f58934952..98c92fe1a 100644
--- a/tests/gocase/unit/scripting/function_test.go
+++ b/tests/gocase/unit/scripting/function_test.go
@@ -302,8 +302,17 @@ var testFunctions = func(t *testing.T, config 
util.KvrocksServerConfigs) {
                util.ErrorRegexp(t, rdb.Do(ctx, "FCALL", "reverse", 0, 
"abc").Err(), ".*No such function name.*")
                util.ErrorRegexp(t, rdb2.Do(ctx, "FCALL", "reverse", 0, 
"abc").Err(), ".*No such function name.*")
 
-               require.NoError(t, rdb.Do(ctx, "FCALL", "myset", 1, 
"func-test-tmp-a", 1).Err())
-               require.NoError(t, rdb2.Do(ctx, "FCALL", "myget", 1, 
"func-test-tmp-a").Err())
+               require.NoError(t, rdb.Do(ctx, "FCALL", "myset", 1, 
"func-test-tmp-a", 123).Err())
+               require.Equal(t, rdb2.Do(ctx, "FCALL", "myget", 1, 
"func-test-tmp-a").Val(), "123")
+       })
+
+       t.Run("FUNCTION FLUSH", func(t *testing.T) {
+               require.NoError(t, rdb.Do(ctx, "FUNCTION", "FLUSH").Err())
+
+               // After flush, all functions should be gone
+               util.ErrorRegexp(t, rdb.Do(ctx, "FCALL", "inc", 0, 1).Err(), 
".*No such function name.*")
+               util.ErrorRegexp(t, rdb.Do(ctx, "FCALL", "hello", 0, 
"x").Err(), ".*No such function name.*")
+               util.ErrorRegexp(t, rdb.Do(ctx, "FCALL", "myget", 1, 
"func-test-tmp-b").Err(), ".*No such function name.*")
        })
 }
 

Reply via email to