Skip to content

Commit 87a072e

Browse files
authored
Restore async replication (#14465)
1 parent ddc16f2 commit 87a072e

File tree

8 files changed

+99
-20
lines changed

8 files changed

+99
-20
lines changed

ydb/core/tx/schemeshard/schemeshard_import__create.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,8 @@ struct TSchemeShard::TImport::TTxProgress: public TSchemeShard::TXxport::TTxBase
848848
<< importInfo->Settings.items(msg.ItemIdx).source_prefix() << NYdb::NDump::NFiles::CreateView().FileName;
849849

850850
NYql::TIssues issues;
851-
if (!NYdb::NDump::RewriteCreateViewQuery(item.CreationQuery, database, true, item.DstPathName, source, issues)) {
851+
if (!NYdb::NDump::RewriteCreateViewQuery(item.CreationQuery, database, true, item.DstPathName, issues)) {
852+
issues.AddIssue(TStringBuilder() << "path: " << source);
852853
return CancelAndPersist(db, importInfo, msg.ItemIdx, issues.ToString(), "invalid view creation query");
853854
}
854855
item.SchemeQueryExecutor = ctx.Register(CreateSchemeQueryExecutor(

ydb/public/lib/ydb_cli/dump/restore_impl.cpp

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <ydb/public/lib/ydb_cli/common/retry_func.h>
1010
#include <ydb/public/lib/ydb_cli/dump/files/files.h>
1111
#include <ydb/public/lib/ydb_cli/dump/util/log.h>
12+
#include <ydb/public/lib/ydb_cli/dump/util/rewrite_query.h>
1213
#include <ydb/public/lib/ydb_cli/dump/util/util.h>
1314
#include <ydb/public/lib/ydb_cli/dump/util/view_utils.h>
1415
#include <ydb-cpp-sdk/client/proto/accessor.h>
@@ -48,12 +49,24 @@ bool IsFileExists(const TFsPath& path) {
4849
return path.Exists() && path.IsFile();
4950
}
5051

51-
template <typename TProtoType>
52-
TProtoType ReadProtoFromFile(const TFsPath& fsDirPath, const TLog* log, const NFiles::TFileInfo& fileInfo) {
52+
TString ReadFromFile(const TFsPath& fsDirPath, const TLog* log, const NFiles::TFileInfo& fileInfo) {
5353
const auto fsPath = fsDirPath.Child(fileInfo.FileName);
5454
LOG_IMPL(log, ELogPriority::TLOG_DEBUG, "Read " << fileInfo.LogObjectType << " from " << fsPath.GetPath().Quote());
55+
return TFileInput(fsPath).ReadAll();
56+
}
57+
58+
TString ReadViewQuery(const TFsPath& fsDirPath, const TLog* log) {
59+
return ReadFromFile(fsDirPath, log, NFiles::CreateView());
60+
}
61+
62+
TString ReadAsyncReplicationQuery(const TFsPath& fsDirPath, const TLog* log) {
63+
return ReadFromFile(fsDirPath, log, NFiles::CreateAsyncReplication());
64+
}
65+
66+
template <typename TProtoType>
67+
TProtoType ReadProtoFromFile(const TFsPath& fsDirPath, const TLog* log, const NFiles::TFileInfo& fileInfo) {
5568
TProtoType proto;
56-
Y_ENSURE(google::protobuf::TextFormat::ParseFromString(TFileInput(fsPath).ReadAll(), &proto));
69+
Y_ENSURE(google::protobuf::TextFormat::ParseFromString(ReadFromFile(fsDirPath, log, fileInfo), &proto));
5770
return proto;
5871
}
5972

@@ -465,6 +478,10 @@ TRestoreResult TRestoreClient::RestoreFolder(
465478
return RestoreCoordinationNode(fsPath, objectDbPath, settings, oldEntries.contains(objectDbPath));
466479
}
467480

481+
if (IsFileExists(fsPath.Child(NFiles::CreateAsyncReplication().FileName))) {
482+
return RestoreReplication(fsPath, objectDbPath, settings, oldEntries.contains(objectDbPath));
483+
}
484+
468485
if (IsFileExists(fsPath.Child(NFiles::Empty().FileName))) {
469486
return RestoreEmptyDir(fsPath, objectDbPath, settings, oldEntries.contains(objectDbPath));
470487
}
@@ -486,6 +503,8 @@ TRestoreResult TRestoreClient::RestoreFolder(
486503
result = RestoreTopic(child, childDbPath, settings, oldEntries.contains(childDbPath));
487504
} else if (IsFileExists(child.Child(NFiles::CreateCoordinationNode().FileName))) {
488505
result = RestoreCoordinationNode(child, childDbPath, settings, oldEntries.contains(childDbPath));
506+
} else if (IsFileExists(child.Child(NFiles::CreateAsyncReplication().FileName))) {
507+
result = RestoreReplication(child, childDbPath, settings, oldEntries.contains(childDbPath));
489508
} else if (child.IsDirectory()) {
490509
result = RestoreFolder(child, dbRestoreRoot, Join('/', dbPathRelativeToRestoreRoot, child.GetName()), settings, oldEntries);
491510
}
@@ -520,13 +539,12 @@ TRestoreResult TRestoreClient::RestoreView(
520539
const TString dbPath = dbRestoreRoot + dbPathRelativeToRestoreRoot;
521540
LOG_I("Restore view " << fsPath.GetPath().Quote() << " to " << dbPath.Quote());
522541

523-
const auto createViewFile = fsPath.Child(NFiles::CreateView().FileName);
524-
TString query = TFileInput(createViewFile).ReadAll();
542+
TString query = ReadViewQuery(fsPath, Log.get());
525543

526544
NYql::TIssues issues;
527545
const bool isDb = IsDatabase(SchemeClient, dbRestoreRoot);
528-
if (!RewriteCreateViewQuery(query, dbRestoreRoot, isDb, dbPath, createViewFile.GetPath().Quote(), issues)) {
529-
return Result<TRestoreResult>(dbPath, EStatus::BAD_REQUEST, issues.ToString());
546+
if (!RewriteCreateViewQuery(query, dbRestoreRoot, isDb, dbPath, issues)) {
547+
return Result<TRestoreResult>(fsPath.GetPath(), EStatus::BAD_REQUEST, issues.ToString());
530548
}
531549

532550
if (settings.DryRun_) {
@@ -584,6 +602,44 @@ TRestoreResult TRestoreClient::RestoreTopic(
584602
return Result<TRestoreResult>(dbPath, std::move(result));
585603
}
586604

605+
TRestoreResult TRestoreClient::RestoreReplication(
606+
const TFsPath& fsPath,
607+
const TString& dbPath,
608+
const TRestoreSettings& settings,
609+
bool isAlreadyExisting)
610+
{
611+
LOG_D("Process " << fsPath.GetPath().Quote());
612+
613+
if (auto error = ErrorOnIncomplete(fsPath)) {
614+
return *error;
615+
}
616+
617+
LOG_I("Restore async replication " << fsPath.GetPath().Quote() << " to " << dbPath.Quote());
618+
619+
if (settings.DryRun_) {
620+
return CheckExistenceAndType(SchemeClient, dbPath, ESchemeEntryType::Replication);
621+
}
622+
623+
auto query = ReadAsyncReplicationQuery(fsPath, Log.get());
624+
625+
NYql::TIssues issues;
626+
if (!RewriteCreateQuery(query, "CREATE ASYNC REPLICATION `{}`", dbPath, issues)) {
627+
return Result<TRestoreResult>(fsPath.GetPath(), EStatus::BAD_REQUEST, issues.ToString());
628+
}
629+
630+
auto result = QueryClient.RetryQuerySync([&](NQuery::TSession session) {
631+
return session.ExecuteQuery(query, NQuery::TTxControl::NoTx()).ExtractValueSync();
632+
});
633+
634+
if (result.IsSuccess()) {
635+
LOG_D("Created " << dbPath.Quote());
636+
return RestorePermissions(fsPath, dbPath, settings, isAlreadyExisting);
637+
}
638+
639+
LOG_E("Failed to create " << dbPath.Quote());
640+
return Result<TRestoreResult>(dbPath, std::move(result));
641+
}
642+
587643
TRestoreResult TRestoreClient::RestoreRateLimiter(
588644
const TFsPath& fsPath,
589645
const TString& coordinationNodePath,

ydb/public/lib/ydb_cli/dump/restore_impl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ class TRestoreClient {
131131
TRestoreResult RestoreTable(const TFsPath& fsPath, const TString& dbPath, const TRestoreSettings& settings, bool isAlreadyExisting);
132132
TRestoreResult RestoreView(const TFsPath& fsPath, const TString& dbRestoreRoot, const TString& dbPathRelativeToRestoreRoot, const TRestoreSettings& settings, bool isAlreadyExisting);
133133
TRestoreResult RestoreTopic(const TFsPath& fsPath, const TString& dbPath, const TRestoreSettings& settings, bool isAlreadyExisting);
134+
TRestoreResult RestoreReplication(const TFsPath& fsPath, const TString& dbPath, const TRestoreSettings& settings, bool isAlreadyExisting);
134135
TRestoreResult RestoreCoordinationNode(const TFsPath& fsPath, const TString& dbPath, const TRestoreSettings& settings, bool isAlreadyExisting);
135136
TRestoreResult RestoreDependentResources(const TFsPath& fsPath, const TString& dbPath);
136137
TRestoreResult RestoreRateLimiter(const TFsPath& fsPath, const TString& coordinationNodePath, const TString& resourcePath);
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include "rewrite_query.h"
2+
3+
#include <util/string/builder.h>
4+
5+
#include <re2/re2.h>
6+
7+
#include <format>
8+
9+
namespace NYdb::NDump {
10+
11+
bool RewriteCreateQuery(TString& query, std::string_view pattern, const std::string& dbPath, NYql::TIssues& issues) {
12+
const auto searchPattern = std::vformat(pattern, std::make_format_args("\\S+"));
13+
if (re2::RE2::Replace(&query, searchPattern, std::vformat(pattern, std::make_format_args(dbPath)))) {
14+
return true;
15+
}
16+
17+
issues.AddIssue(TStringBuilder() << "Pattern: \"" << pattern << "\" was not found: " << query.Quote());
18+
return false;
19+
}
20+
21+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include <yql/essentials/public/issue/yql_issue.h>
2+
3+
namespace NYdb::NDump {
4+
5+
bool RewriteCreateQuery(TString& query, std::string_view pattern, const std::string& dbPath, NYql::TIssues& issues);
6+
7+
}

ydb/public/lib/ydb_cli/dump/util/view_utils.cpp

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include "rewrite_query.h"
12
#include "view_utils.h"
23

34
#include <yql/essentials/parser/proto_ast/gen/v1/SQLv1Lexer.h>
@@ -361,7 +362,7 @@ TString BuildCreateViewQuery(
361362
}
362363

363364
bool RewriteCreateViewQuery(TString& query, const TString& restoreRoot, bool restoreRootIsDatabase,
364-
const TString& dbPath, const TString& source, NYql::TIssues& issues
365+
const TString& dbPath, NYql::TIssues& issues
365366
) {
366367
const auto backupRoot = GetBackupRoot(query);
367368

@@ -373,16 +374,7 @@ bool RewriteCreateViewQuery(TString& query, const TString& restoreRoot, bool res
373374
return false;
374375
}
375376

376-
constexpr TStringBuf pattern = R"(CREATE VIEW IF NOT EXISTS `\S+` )";
377-
if (!re2::RE2::Replace(&query, pattern, std::format(R"(CREATE VIEW IF NOT EXISTS `{}` )", dbPath.c_str()))) {
378-
issues.AddIssue(TStringBuilder()
379-
<< "Cannot restore a view from the source: " << source
380-
<< ". Pattern: \"" << pattern << "\", was not found in the create view statement: " << query.Quote()
381-
);
382-
return false;
383-
}
384-
385-
return true;
377+
return RewriteCreateQuery(query, "CREATE VIEW IF NOT EXISTS `{}`", dbPath, issues);
386378
}
387379

388380
}

ydb/public/lib/ydb_cli/dump/util/view_utils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ TString BuildCreateViewQuery(
88
);
99

1010
bool RewriteCreateViewQuery(TString& query, const TString& restoreRoot, bool restoreRootIsDatabase,
11-
const TString& dbPath, const TString& source, NYql::TIssues& issues
11+
const TString& dbPath, NYql::TIssues& issues
1212
);
1313

1414
}

ydb/public/lib/ydb_cli/dump/util/ya.make

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
LIBRARY()
22

33
SRCS(
4+
rewrite_query.cpp
45
util.cpp
56
view_utils.cpp
67
)

0 commit comments

Comments
 (0)