From a64cabf4b091fe48b85fa7bdc74d74cf775f6011 Mon Sep 17 00:00:00 2001 From: xq2010 <122602529+xq2010@users.noreply.github.com> Date: Mon, 28 Aug 2023 21:06:02 +0800 Subject: [PATCH] Add support for LASTSAVE command (#1702) Co-authored-by: xuqing Co-authored-by: Twice Co-authored-by: Binbin --- src/commands/cmd_server.cc | 14 ++++++++++++++ src/server/server.cc | 7 ++++++- src/server/server.h | 1 + tests/gocase/unit/info/info_test.go | 1 - 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/commands/cmd_server.cc b/src/commands/cmd_server.cc index 760adaed60f..d9b972de17c 100644 --- a/src/commands/cmd_server.cc +++ b/src/commands/cmd_server.cc @@ -980,6 +980,19 @@ static uint64_t GenerateConfigFlag(const std::vector &args) { return 0; } +class CommandLastSave : public Commander { + public: + Status Execute(Server *svr, Connection *conn, std::string *output) override { + if (!conn->IsAdmin()) { + return {Status::RedisExecErr, errAdminPermissionRequired}; + } + + int64_t unix_sec = svr->GetLastBgsaveTime(); + *output = redis::Integer(unix_sec); + return Status::OK(); + } +}; + class CommandRestore : public Commander { public: Status Parse(const std::vector &args) override { @@ -1080,6 +1093,7 @@ REDIS_REGISTER_COMMANDS(MakeCmdAttr("auth", 2, "read-only ok-loadin MakeCmdAttr("compact", 1, "read-only no-script", 0, 0, 0), MakeCmdAttr("bgsave", 1, "read-only no-script", 0, 0, 0), + MakeCmdAttr("lastsave", 1, "read-only no-script", 0, 0, 0), MakeCmdAttr("flushbackup", 1, "read-only no-script", 0, 0, 0), MakeCmdAttr("slaveof", 3, "read-only exclusive no-script", 0, 0, 0), MakeCmdAttr("stats", 1, "read-only", 0, 0, 0), ) diff --git a/src/server/server.cc b/src/server/server.cc index b00decf6ddf..3b583cbed1d 100644 --- a/src/server/server.cc +++ b/src/server/server.cc @@ -986,6 +986,11 @@ int64_t Server::GetCachedUnixTime() { return unix_time.load(); } +int64_t Server::GetLastBgsaveTime() { + std::lock_guard lg(db_job_mu_); + return last_bgsave_time_ == -1 ? start_time_ : last_bgsave_time_; +} + void Server::GetStatsInfo(std::string *info) { std::ostringstream string_stream; string_stream << "# Stats\r\n"; @@ -1074,7 +1079,7 @@ void Server::GetInfo(const std::string &ns, const std::string §ion, std::str std::lock_guard lg(db_job_mu_); string_stream << "bgsave_in_progress:" << (is_bgsave_in_progress_ ? 1 : 0) << "\r\n"; - string_stream << "last_bgsave_time:" << last_bgsave_time_ << "\r\n"; + string_stream << "last_bgsave_time:" << (last_bgsave_time_ == -1 ? start_time_ : last_bgsave_time_) << "\r\n"; string_stream << "last_bgsave_status:" << last_bgsave_status_ << "\r\n"; string_stream << "last_bgsave_time_sec:" << last_bgsave_time_sec_ << "\r\n"; } diff --git a/src/server/server.h b/src/server/server.h index b598e5208b0..953cbbbcd78 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -211,6 +211,7 @@ class Server { void SetLastRandomKeyCursor(const std::string &cursor); static int64_t GetCachedUnixTime(); + int64_t GetLastBgsaveTime(); void GetStatsInfo(std::string *info); void GetServerInfo(std::string *info); void GetMemoryInfo(std::string *info); diff --git a/tests/gocase/unit/info/info_test.go b/tests/gocase/unit/info/info_test.go index b0078a59bed..136be197bc3 100644 --- a/tests/gocase/unit/info/info_test.go +++ b/tests/gocase/unit/info/info_test.go @@ -72,7 +72,6 @@ func TestInfo(t *testing.T) { t.Run("get bgsave information by INFO", func(t *testing.T) { require.Equal(t, "0", util.FindInfoEntry(rdb, "bgsave_in_progress", "persistence")) - require.Equal(t, "-1", util.FindInfoEntry(rdb, "last_bgsave_time", "persistence")) require.Equal(t, "ok", util.FindInfoEntry(rdb, "last_bgsave_status", "persistence")) require.Equal(t, "-1", util.FindInfoEntry(rdb, "last_bgsave_time_sec", "persistence"))