Skip to content

Commit bdc944f

Browse files
authored
Merge f02876b into 0c2f282
2 parents 0c2f282 + f02876b commit bdc944f

File tree

4 files changed

+127
-12
lines changed

4 files changed

+127
-12
lines changed

ydb/core/tx/schemeshard/schemeshard_export__create.cpp

+13-6
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,19 @@ struct TSchemeShard::TExport::TTxCreate: public TSchemeShard::TXxport::TTxBase {
5151
}
5252

5353
const TString& uid = GetUid(request.GetRequest().GetOperationParams().labels());
54-
if (uid && Self->ExportsByUid.contains(uid)) {
55-
return Reply(
56-
std::move(response),
57-
Ydb::StatusIds::ALREADY_EXISTS,
58-
TStringBuilder() << "Export with uid '" << uid << "' already exists"
59-
);
54+
if (uid) {
55+
if (auto it = Self->ExportsByUid.find(uid); it != Self->ExportsByUid.end()) {
56+
if (IsSameDomain(it->second, request.GetDatabaseName())) {
57+
Self->FromXxportInfo(*response->Record.MutableResponse()->MutableEntry(), it->second);
58+
return Reply(std::move(response));
59+
} else {
60+
return Reply(
61+
std::move(response),
62+
Ydb::StatusIds::ALREADY_EXISTS,
63+
TStringBuilder() << "Export with uid '" << uid << "' already exists"
64+
);
65+
}
66+
}
6067
}
6168

6269
const TPath domainPath = TPath::Resolve(request.GetDatabaseName(), Self);

ydb/core/tx/schemeshard/schemeshard_import__create.cpp

+13-6
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,19 @@ struct TSchemeShard::TImport::TTxCreate: public TSchemeShard::TXxport::TTxBase {
5353
}
5454

5555
const TString& uid = GetUid(request.GetRequest().GetOperationParams().labels());
56-
if (uid && Self->ImportsByUid.contains(uid)) {
57-
return Reply(
58-
std::move(response),
59-
Ydb::StatusIds::ALREADY_EXISTS,
60-
TStringBuilder() << "Import with uid '" << uid << "' already exists"
61-
);
56+
if (uid) {
57+
if (auto it = Self->ImportsByUid.find(uid); it != Self->ImportsByUid.end()) {
58+
if (IsSameDomain(it->second, request.GetDatabaseName())) {
59+
Self->FromXxportInfo(*response->Record.MutableResponse()->MutableEntry(), it->second);
60+
return Reply(std::move(response));
61+
} else {
62+
return Reply(
63+
std::move(response),
64+
Ydb::StatusIds::ALREADY_EXISTS,
65+
TStringBuilder() << "Import with uid '" << uid << "' already exists"
66+
);
67+
}
68+
}
6269
}
6370

6471
const TPath domainPath = TPath::Resolve(request.GetDatabaseName(), Self);

ydb/core/tx/schemeshard/ut_export/ut_export.cpp

+48
Original file line numberDiff line numberDiff line change
@@ -1394,4 +1394,52 @@ partitioning_settings {
13941394

13951395
TestGetExport(runtime, txId, "/MyRoot", Ydb::StatusIds::CANCELLED);
13961396
}
1397+
1398+
Y_UNIT_TEST(UidAsIdempotencyKey) {
1399+
TTestBasicRuntime runtime;
1400+
TTestEnv env(runtime);
1401+
ui64 txId = 100;
1402+
1403+
TestCreateTable(runtime, ++txId, "/MyRoot", R"(
1404+
Name: "Table"
1405+
Columns { Name: "key" Type: "Utf8" }
1406+
Columns { Name: "value" Type: "Utf8" }
1407+
KeyColumnNames: ["key"]
1408+
)");
1409+
env.TestWaitNotification(runtime, txId);
1410+
1411+
TPortManager portManager;
1412+
const ui16 port = portManager.GetPort();
1413+
1414+
TS3Mock s3Mock({}, TS3Mock::TSettings(port));
1415+
UNIT_ASSERT(s3Mock.Start());
1416+
1417+
const auto request = Sprintf(R"(
1418+
OperationParams {
1419+
labels {
1420+
key: "uid"
1421+
value: "foo"
1422+
}
1423+
}
1424+
ExportToS3Settings {
1425+
endpoint: "localhost:%d"
1426+
scheme: HTTP
1427+
items {
1428+
source_path: "/MyRoot/Table"
1429+
destination_prefix: ""
1430+
}
1431+
}
1432+
)", port);
1433+
1434+
// create operation
1435+
TestExport(runtime, ++txId, "/MyRoot", request);
1436+
const ui64 exportId = txId;
1437+
// create operation again with same uid
1438+
TestExport(runtime, ++txId, "/MyRoot", request);
1439+
// new operation was not created
1440+
TestGetExport(runtime, txId, "/MyRoot", Ydb::StatusIds::NOT_FOUND);
1441+
// check previous operation
1442+
TestGetExport(runtime, exportId, "/MyRoot");
1443+
env.TestWaitNotification(runtime, exportId);
1444+
}
13971445
}

ydb/core/tx/schemeshard/ut_restore/ut_restore.cpp

+53
Original file line numberDiff line numberDiff line change
@@ -2451,6 +2451,59 @@ Y_UNIT_TEST_SUITE(TImportTests) {
24512451
Run(runtime, env, ConvertTestData(data), request, Ydb::StatusIds::PRECONDITION_FAILED);
24522452
Run(runtime, env, ConvertTestData(data), request, Ydb::StatusIds::SUCCESS, "/MyRoot", false, userSID);
24532453
}
2454+
2455+
Y_UNIT_TEST(UidAsIdempotencyKey) {
2456+
TTestBasicRuntime runtime;
2457+
TTestEnv env(runtime, TTestEnvOptions());
2458+
ui64 txId = 100;
2459+
2460+
const auto data = GenerateTestData(R"(
2461+
columns {
2462+
name: "key"
2463+
type { optional_type { item { type_id: UTF8 } } }
2464+
}
2465+
columns {
2466+
name: "value"
2467+
type { optional_type { item { type_id: UTF8 } } }
2468+
}
2469+
primary_key: "key"
2470+
)", {{"a", 1}});
2471+
2472+
TPortManager portManager;
2473+
const ui16 port = portManager.GetPort();
2474+
2475+
TS3Mock s3Mock(ConvertTestData(data), TS3Mock::TSettings(port));
2476+
UNIT_ASSERT(s3Mock.Start());
2477+
2478+
const auto request = Sprintf(R"(
2479+
OperationParams {
2480+
labels {
2481+
key: "uid"
2482+
value: "foo"
2483+
}
2484+
}
2485+
ImportFromS3Settings {
2486+
endpoint: "localhost:%d"
2487+
scheme: HTTP
2488+
items {
2489+
source_prefix: ""
2490+
destination_path: "/MyRoot/Table"
2491+
}
2492+
}
2493+
)", port);
2494+
2495+
// create operation
2496+
TestImport(runtime, ++txId, "/MyRoot", request);
2497+
const ui64 importId = txId;
2498+
// create operation again with same uid
2499+
TestImport(runtime, ++txId, "/MyRoot", request);
2500+
// new operation was not created
2501+
TestGetImport(runtime, txId, "/MyRoot", Ydb::StatusIds::NOT_FOUND);
2502+
// check previous operation
2503+
TestGetImport(runtime, importId, "/MyRoot");
2504+
env.TestWaitNotification(runtime, importId);
2505+
}
2506+
24542507
}
24552508

24562509
Y_UNIT_TEST_SUITE(TImportWithRebootsTests) {

0 commit comments

Comments
 (0)