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.*")
})
}