33#include " util.h"
44
55#include < ydb/public/api/protos/ydb_table.pb.h>
6+ #include < ydb/public/lib/ydb_cli/commands/ydb_common.h>
67#include < ydb/public/lib/ydb_cli/common/recursive_remove.h>
8+ #include < ydb/public/lib/ydb_cli/common/retry_func.h>
79#include < ydb/public/lib/ydb_cli/dump/util/util.h>
810#include < ydb/public/lib/yson_value/ydb_yson_value.h>
11+ #include < ydb/public/sdk/cpp/client/ydb_proto/accessor.h>
912#include < ydb/public/sdk/cpp/client/ydb_driver/driver.h>
1013#include < ydb/public/sdk/cpp/client/ydb_result/result.h>
1114#include < ydb/public/sdk/cpp/client/ydb_table/table.h>
@@ -34,6 +37,8 @@ namespace NYdb::NBackup {
3437
3538static constexpr const char *SCHEME_FILE_NAME = " scheme.pb" ;
3639static constexpr const char *PERMISSIONS_FILE_NAME = " permissions.pb" ;
40+ static constexpr const char *CHANGEFEED_DESCRIPTION_FILE_NAME = " changefeed_description.pb" ;
41+ static constexpr const char *TOPIC_DESCRIPTION_FILE_NAME = " topic_description.pb" ;
3742static constexpr const char *INCOMPLETE_DATA_FILE_NAME = " incomplete.csv" ;
3843static constexpr const char *INCOMPLETE_FILE_NAME = " incomplete" ;
3944static constexpr const char *EMPTY_FILE_NAME = " empty_dir" ;
@@ -471,6 +476,53 @@ void BackupPermissions(TDriver driver, const TString& dbPrefix, const TString& p
471476 outFile.Write (permissionsStr.data (), permissionsStr.size ());
472477}
473478
479+ TFsPath CreateDirectory (const TFsPath& folderPath, const TString& name) {
480+ TFsPath childFolderPath = folderPath.Child (name);
481+ LOG_D (" Process " << childFolderPath.GetPath ().Quote ());
482+ childFolderPath.MkDir ();
483+ return childFolderPath;
484+ }
485+
486+ Ydb::Table::ChangefeedDescription ProtoFromChangefeedDesc (const NTable::TChangefeedDescription& changefeedDesc) {
487+ Ydb::Table::ChangefeedDescription protoChangeFeedDesc;
488+ changefeedDesc.SerializeTo (protoChangeFeedDesc);
489+ return protoChangeFeedDesc;
490+ }
491+
492+ NTopic::TDescribeTopicResult GetTopicDescription (TDriver driver, const TString& path) {
493+ NYdb::NTopic::TTopicClient client (driver);
494+ return NConsoleClient::RetryFunction ([&]() {
495+ return client.DescribeTopic (path).GetValueSync ();
496+ });
497+ }
498+
499+ void WriteProtoToFile (const google::protobuf::Message& proto, const TFsPath& folderPath, const TString& fileName) {
500+ TString changefeedStr;
501+ google::protobuf::TextFormat::PrintToString (proto, &changefeedStr);
502+ LOG_D (" Write changefeed into " << folderPath.Child (fileName).GetPath ().Quote ());
503+ TFile outFile (folderPath.Child (fileName), CreateAlways | WrOnly);
504+ outFile.Write (changefeedStr.data (), changefeedStr.size ());
505+ }
506+
507+ void BackupChangefeeds (TDriver driver, const TString& dbPrefix, const TString& path, const TFsPath& folderPath) {
508+
509+ const auto dirPath = JoinDatabasePath (dbPrefix, path);
510+ auto desc = DescribeTable (driver, dirPath);
511+
512+ for (const auto & changefeedDesc : desc.GetChangefeedDescriptions ()) {
513+ TFsPath changefeedDirPath = CreateDirectory (folderPath, changefeedDesc.GetName ());
514+
515+ auto protoChangeFeedDesc = ProtoFromChangefeedDesc (changefeedDesc);
516+ const auto descTopicResult = GetTopicDescription (driver, JoinDatabasePath (dirPath, changefeedDesc.GetName ()));
517+ NConsoleClient::ThrowOnError (descTopicResult);
518+ const auto & topicDescription = descTopicResult.GetTopicDescription ();
519+ const auto protoTopicDescription = NYdb::TProtoAccessor::GetProto (topicDescription);
520+
521+ WriteProtoToFile (protoChangeFeedDesc, changefeedDirPath, CHANGEFEED_DESCRIPTION_FILE_NAME);
522+ WriteProtoToFile (protoTopicDescription, changefeedDirPath, TOPIC_DESCRIPTION_FILE_NAME);
523+ }
524+ }
525+
474526void BackupTable (TDriver driver, const TString& dbPrefix, const TString& backupPrefix, const TString& path,
475527 const TFsPath& folderPath, bool schemaOnly, bool preservePoolKinds, bool ordered) {
476528 Y_ENSURE (!path.empty ());
@@ -489,6 +541,7 @@ void BackupTable(TDriver driver, const TString& dbPrefix, const TString& backupP
489541 TFile outFile (folderPath.Child (SCHEME_FILE_NAME), CreateAlways | WrOnly);
490542 outFile.Write (schemaStr.data (), schemaStr.size ());
491543
544+ BackupChangefeeds (driver, dbPrefix, path, folderPath);
492545 BackupPermissions (driver, dbPrefix, path, folderPath);
493546
494547 if (!schemaOnly) {
0 commit comments