|
1 | 1 | #include <ydb/core/metering/metering.h>
|
| 2 | +#include <ydb/core/testlib/actors/block_events.h> |
2 | 3 | #include <ydb/core/tx/schemeshard/ut_helpers/helpers.h>
|
3 | 4 | #include <ydb/core/tx/schemeshard/schemeshard_billing_helpers.h>
|
4 | 5 | #include <ydb/core/tx/schemeshard/schemeshard_impl.h>
|
| 6 | +#include <ydb/core/tx/schemeshard/schemeshard_private.h> |
5 | 7 |
|
6 | 8 | #include <library/cpp/json/json_reader.h>
|
7 | 9 | #include <library/cpp/json/json_writer.h>
|
@@ -1754,6 +1756,80 @@ Y_UNIT_TEST_SUITE(TCdcStreamWithInitialScanTests) {
|
1754 | 1756 | env.TestWaitNotification(runtime, txId);
|
1755 | 1757 | }
|
1756 | 1758 |
|
| 1759 | + Y_UNIT_TEST(RacyAlterStreamAndRestart) { |
| 1760 | + TTestBasicRuntime runtime; |
| 1761 | + TTestEnv env(runtime, TTestEnvOptions() |
| 1762 | + .EnableChangefeedInitialScan(true)); |
| 1763 | + ui64 txId = 100; |
| 1764 | + |
| 1765 | + TActorId schemeShardActorId; |
| 1766 | + auto findActorId = runtime.AddObserver<TEvSchemeShard::TEvModifySchemeTransactionResult>([&](auto& ev) { |
| 1767 | + if (!schemeShardActorId) { |
| 1768 | + schemeShardActorId = ev->Sender; |
| 1769 | + } |
| 1770 | + }); |
| 1771 | + |
| 1772 | + TestCreateTable(runtime, ++txId, "/MyRoot", R"( |
| 1773 | + Name: "Table" |
| 1774 | + Columns { Name: "key" Type: "Uint64" } |
| 1775 | + Columns { Name: "value" Type: "Uint64" } |
| 1776 | + KeyColumnNames: ["key"] |
| 1777 | + )"); |
| 1778 | + env.TestWaitNotification(runtime, txId); |
| 1779 | + |
| 1780 | + TBlockEvents<TEvSchemeShard::TEvModifySchemeTransaction> blockedAlterStream(runtime, [&](auto& ev) { |
| 1781 | + const auto& record = ev->Get()->Record; |
| 1782 | + if (record.GetTransaction(0).GetOperationType() == NKikimrSchemeOp::ESchemeOpAlterCdcStream) { |
| 1783 | + txId = record.GetTxId(); |
| 1784 | + return true; |
| 1785 | + } |
| 1786 | + return false; |
| 1787 | + }); |
| 1788 | + |
| 1789 | + TestCreateCdcStream(runtime, ++txId, "/MyRoot", R"( |
| 1790 | + TableName: "Table" |
| 1791 | + StreamDescription { |
| 1792 | + Name: "Stream" |
| 1793 | + Mode: ECdcStreamModeKeysOnly |
| 1794 | + Format: ECdcStreamFormatProto |
| 1795 | + State: ECdcStreamStateScan |
| 1796 | + } |
| 1797 | + )"); |
| 1798 | + env.TestWaitNotification(runtime, txId); |
| 1799 | + |
| 1800 | + runtime.WaitFor("AlterCdcStream", [&]{ return blockedAlterStream.size(); }); |
| 1801 | + blockedAlterStream.Stop(); |
| 1802 | + |
| 1803 | + UNIT_ASSERT(schemeShardActorId); |
| 1804 | + |
| 1805 | + TBlockEvents<TEvPrivate::TEvProgressOperation> blockedProgress(runtime, [&](auto& ev) { |
| 1806 | + return schemeShardActorId == ev->Sender; |
| 1807 | + }); |
| 1808 | + |
| 1809 | + blockedAlterStream.Unblock(); |
| 1810 | + runtime.WaitFor("Progress", [&]{ return blockedProgress.size(); }); |
| 1811 | + blockedProgress.Stop(); |
| 1812 | + |
| 1813 | + RebootTablet(runtime, TTestTxConfig::SchemeShard, runtime.AllocateEdgeActor()); |
| 1814 | + env.TestWaitNotification(runtime, txId); |
| 1815 | + |
| 1816 | + TestDescribeResult(DescribePrivatePath(runtime, "/MyRoot/Table/Stream"), { |
| 1817 | + NLs::PathExist, |
| 1818 | + NLs::StreamState(NKikimrSchemeOp::ECdcStreamStateReady), |
| 1819 | + }); |
| 1820 | + |
| 1821 | + TestDropCdcStream(runtime, ++txId, "/MyRoot", R"( |
| 1822 | + TableName: "Table" |
| 1823 | + StreamName: "Stream" |
| 1824 | + )"); |
| 1825 | + env.TestWaitNotification(runtime, txId); |
| 1826 | + |
| 1827 | + RebootTablet(runtime, TTestTxConfig::SchemeShard, runtime.AllocateEdgeActor()); |
| 1828 | + TestDescribeResult(DescribePrivatePath(runtime, "/MyRoot/Table/Stream"), { |
| 1829 | + NLs::PathNotExist, |
| 1830 | + }); |
| 1831 | + } |
| 1832 | + |
1757 | 1833 | void Metering(bool serverless) {
|
1758 | 1834 | TTestBasicRuntime runtime;
|
1759 | 1835 | TTestEnv env(runtime, TTestEnvOptions()
|
|
0 commit comments