diff --git a/rocks/include/userver/storages/rocks/client.hpp b/rocks/include/userver/storages/rocks/client.hpp index 3f2237e0070a..4750b9ea2d50 100644 --- a/rocks/include/userver/storages/rocks/client.hpp +++ b/rocks/include/userver/storages/rocks/client.hpp @@ -64,10 +64,17 @@ class Client final { */ void CheckStatus(rocksdb::Status status, std::string_view method_name); + /** + * MakeSnapshot — creates a checkpoint of the RocksDB database. Checkpoints can be used as a point in time snapshot. + * @param checkpoint_path — the path to the file where the snapshot will be saved. + */ + Client MakeSnapshot(const std::string& checkpoint_path); + private: std::unique_ptr db_; engine::TaskProcessor& blocking_task_processor_; }; + } // namespace storages::rocks USERVER_NAMESPACE_END diff --git a/rocks/src/storages/rocks/client.cpp b/rocks/src/storages/rocks/client.cpp index d4d4f5f958a8..95c80a4d3fec 100644 --- a/rocks/src/storages/rocks/client.cpp +++ b/rocks/src/storages/rocks/client.cpp @@ -2,6 +2,8 @@ #include +#include + #include #include @@ -56,6 +58,22 @@ void Client::CheckStatus(rocksdb::Status status, std::string_view method_name) { method_name, status.ToString()); } } + +Client Client::MakeSnapshot(const std::string& checkpoint_path) { + return engine::AsyncNoSpan(blocking_task_processor_, [this, checkpoint_path] { + rocksdb::Checkpoint* checkpoint{}; + rocksdb::Status status = rocksdb::Checkpoint::Create(db_.get(), &checkpoint); + + std::unique_ptr checkpoint_smart_ptr(checkpoint); + CheckStatus(status, "Create Checkpoint"); + + status = checkpoint_smart_ptr->CreateCheckpoint(checkpoint_path); + + CheckStatus(status, "Bind Checkpoint to the path"); + return Client(checkpoint_path, blocking_task_processor_); + }).Get(); +} + } // namespace storages::rocks USERVER_NAMESPACE_END diff --git a/rocks/src/storages/rocks/client_test.cpp b/rocks/src/storages/rocks/client_test.cpp index 10a40849263f..e632cdf3eaa8 100644 --- a/rocks/src/storages/rocks/client_test.cpp +++ b/rocks/src/storages/rocks/client_test.cpp @@ -23,6 +23,39 @@ UTEST(Rocks, CheckCRUD) { client.Delete(key); res = client.Get(key); EXPECT_EQ("", res); + +} + +UTEST(RocksSnapshot, CheckCRUD) { + storages::rocks::Client client{"/tmp/rocksdb_simple_snapshot", + engine::current_task::GetTaskProcessor()}; + std::string key = "key"; + std::string value = "value"; + + client.Put(key, value); + std::string res = client.Get(key); + EXPECT_EQ(value, res); + + storages::rocks::Client snapshot(client.MakeSnapshot("/tmp/snapshot")); + res = snapshot.Get(key); + EXPECT_EQ(value, res); + + + std::string new_value = "new value"; + snapshot.Put(key, new_value); + res = snapshot.Get(key); + EXPECT_EQ(new_value, res); + + res = client.Get(key); + EXPECT_EQ(value, res); + + + snapshot.Delete(key); + res = snapshot.Get(key); + EXPECT_EQ("", res); + + res = client.Get(key); + EXPECT_EQ(value, res); } } // namespace