33#include < ydb/public/sdk/cpp/client/ydb_topic/topic.h>
44#include < ydb/public/sdk/cpp/client/ydb_table/table.h>
55#include < ydb/public/sdk/cpp/client/ydb_persqueue_public/ut/ut_utils/ut_utils.h>
6+ #include < ydb/core/cms/console/console.h>
67#include < ydb/core/keyvalue/keyvalue_events.h>
78#include < ydb/core/persqueue/key.h>
89#include < ydb/core/persqueue/blob.h>
@@ -37,8 +38,14 @@ class TFixture : public NUnitTest::TBaseFixture {
3738 void Write (const TString& message, NTable::TTransaction* tx = nullptr );
3839 };
3940
41+ struct TFeatureFlags {
42+ bool EnablePQConfigTransactionsAtSchemeShard = true ;
43+ };
44+
4045 void SetUp (NUnitTest::TTestContext&) override ;
4146
47+ void NotifySchemeShard (const TFeatureFlags& flags);
48+
4249 NTable::TSession CreateTableSession ();
4350 NTable::TTransaction BeginTx (NTable::TSession& session);
4451 void CommitTx (NTable::TTransaction& tx, EStatus status = EStatus::SUCCESS);
@@ -62,6 +69,8 @@ class TFixture : public NUnitTest::TBaseFixture {
6269 std::optional<size_t > maxPartitionCount = std::nullopt );
6370 void DescribeTopic (const TString& path);
6471
72+ void AddConsumer (const TString& topic, const TVector<TString>& consumers);
73+
6574 void WriteToTopicWithInvalidTxId (bool invalidTxId);
6675
6776 TTopicWriteSessionPtr CreateTopicWriteSession (const TString& topicPath,
@@ -95,6 +104,8 @@ class TFixture : public NUnitTest::TBaseFixture {
95104 NYdb::EStatus status);
96105 void CloseTopicWriteSession (const TString& topicPath,
97106 const TString& messageGroupId);
107+ void CloseTopicReadSession (const TString& topicPath,
108+ const TString& consumerName);
98109
99110 enum EEndOfTransaction {
100111 Commit,
@@ -173,6 +184,8 @@ class TFixture : public NUnitTest::TBaseFixture {
173184 ui64 tabletId,
174185 const NPQ::TWriteId& writeId);
175186
187+ ui64 GetSchemeShardTabletId (const TActorId& actorId);
188+
176189 std::unique_ptr<TTopicSdkTestSetup> Setup;
177190 std::unique_ptr<TDriver> Driver;
178191
@@ -190,11 +203,27 @@ void TFixture::SetUp(NUnitTest::TTestContext&)
190203{
191204 NKikimr::Tests::TServerSettings settings = TTopicSdkTestSetup::MakeServerSettings ();
192205 settings.SetEnableTopicServiceTx (true );
206+
193207 Setup = std::make_unique<TTopicSdkTestSetup>(TEST_CASE_NAME, settings);
194208
195209 Driver = std::make_unique<TDriver>(Setup->MakeDriver ());
196210}
197211
212+ void TFixture::NotifySchemeShard (const TFeatureFlags& flags)
213+ {
214+ auto request = std::make_unique<NConsole::TEvConsole::TEvConfigNotificationRequest>();
215+ *request->Record .MutableConfig () = *Setup->GetServer ().ServerSettings .AppConfig ;
216+ request->Record .MutableConfig ()->MutableFeatureFlags ()->SetEnablePQConfigTransactionsAtSchemeShard (flags.EnablePQConfigTransactionsAtSchemeShard );
217+
218+ auto & runtime = Setup->GetRuntime ();
219+ auto actorId = runtime.AllocateEdgeActor ();
220+
221+ ui64 ssId = GetSchemeShardTabletId (actorId);
222+
223+ runtime.SendToPipe (ssId, actorId, request.release ());
224+ runtime.GrabEdgeEvent <NConsole::TEvConsole::TEvConfigNotificationResponse>();
225+ }
226+
198227NTable::TSession TFixture::CreateTableSession ()
199228{
200229 NTable::TTableClient client (GetDriver ());
@@ -321,6 +350,20 @@ void TFixture::CreateTopic(const TString& path,
321350 Setup->CreateTopic (path, consumer, partitionCount, maxPartitionCount);
322351}
323352
353+ void TFixture::AddConsumer (const TString& path,
354+ const TVector<TString>& consumers)
355+ {
356+ NTopic::TTopicClient client (GetDriver ());
357+ NTopic::TAlterTopicSettings settings;
358+
359+ for (const auto & consumer : consumers) {
360+ settings.BeginAddConsumer (consumer);
361+ }
362+
363+ auto result = client.AlterTopic (path, settings).GetValueSync ();
364+ UNIT_ASSERT_C (result.IsSuccess (), result.GetIssues ().ToString ());
365+ }
366+
324367void TFixture::DescribeTopic (const TString& path)
325368{
326369 Setup->DescribeTopic (path);
@@ -643,6 +686,13 @@ void TFixture::CloseTopicWriteSession(const TString& topicPath,
643686 TopicWriteSessions.erase (key);
644687}
645688
689+ void TFixture::CloseTopicReadSession (const TString& topicPath,
690+ const TString& consumerName)
691+ {
692+ Y_UNUSED (consumerName);
693+ TopicReadSessions.erase (topicPath);
694+ }
695+
646696void TFixture::WriteToTopic (const TString& topicPath,
647697 const TString& messageGroupId,
648698 const TString& message,
@@ -761,6 +811,37 @@ void TFixture::WaitForSessionClose(const TString& topicPath,
761811 UNIT_ASSERT (context.AckCount <= context.WriteCount );
762812}
763813
814+ ui64 TFixture::GetSchemeShardTabletId (const TActorId& actorId)
815+ {
816+ auto navigate = std::make_unique<NSchemeCache::TSchemeCacheNavigate>();
817+ navigate->DatabaseName = " /Root" ;
818+
819+ NSchemeCache::TSchemeCacheNavigate::TEntry entry;
820+ entry.Path = SplitPath (" /Root" );
821+ entry.SyncVersion = true ;
822+ entry.ShowPrivatePath = true ;
823+ entry.Operation = NSchemeCache::TSchemeCacheNavigate::OpList;
824+
825+ navigate->ResultSet .push_back (std::move (entry));
826+ // navigate->UserToken = "root@builtin";
827+ navigate->Cookie = 12345 ;
828+
829+ auto & runtime = Setup->GetRuntime ();
830+
831+ runtime.Send (MakeSchemeCacheID (), actorId,
832+ new TEvTxProxySchemeCache::TEvNavigateKeySet (navigate.release ()),
833+ 0 ,
834+ true );
835+ auto response = runtime.GrabEdgeEvent <TEvTxProxySchemeCache::TEvNavigateKeySetResult>();
836+
837+ UNIT_ASSERT_VALUES_EQUAL (response->Request ->Cookie , 12345 );
838+ UNIT_ASSERT_VALUES_EQUAL (response->Request ->ErrorCount , 0 );
839+
840+ auto & front = response->Request ->ResultSet .front ();
841+
842+ return front.Self ->Info .GetSchemeshardId ();
843+ }
844+
764845ui64 TFixture::GetTopicTabletId (const TActorId& actorId, const TString& topicPath, ui32 partition)
765846{
766847 auto navigate = std::make_unique<NSchemeCache::TSchemeCacheNavigate>();
@@ -1914,3 +1995,100 @@ Y_UNIT_TEST_F(WriteToTopic_Demo_28, TFixture)
19141995}
19151996
19161997}
1998+
1999+ Y_UNIT_TEST_F (WriteToTopic_Demo_30, TFixture)
2000+ {
2001+ WriteMessagesInTx (1 , 0 );
2002+ WriteMessagesInTx (0 , 1 );
2003+ }
2004+
2005+ Y_UNIT_TEST_F (WriteToTopic_Demo_31, TFixture)
2006+ {
2007+ WriteMessagesInTx (1 , 0 );
2008+ WriteMessagesInTx (1 , 1 );
2009+ }
2010+
2011+ Y_UNIT_TEST_F (WriteToTopic_Demo_32, TFixture)
2012+ {
2013+ WriteMessagesInTx (0 , 1 );
2014+ WriteMessagesInTx (1 , 0 );
2015+ }
2016+
2017+ Y_UNIT_TEST_F (WriteToTopic_Demo_33, TFixture)
2018+ {
2019+ WriteMessagesInTx (0 , 1 );
2020+ WriteMessagesInTx (0 , 1 );
2021+ }
2022+
2023+ Y_UNIT_TEST_F (WriteToTopic_Demo_34, TFixture)
2024+ {
2025+ WriteMessagesInTx (0 , 1 );
2026+ WriteMessagesInTx (1 , 1 );
2027+ }
2028+
2029+ Y_UNIT_TEST_F (WriteToTopic_Demo_35, TFixture)
2030+ {
2031+ WriteMessagesInTx (1 , 1 );
2032+ WriteMessagesInTx (1 , 0 );
2033+ }
2034+
2035+ Y_UNIT_TEST_F (WriteToTopic_Demo_36, TFixture)
2036+ {
2037+ WriteMessagesInTx (1 , 1 );
2038+ WriteMessagesInTx (0 , 1 );
2039+ }
2040+
2041+ Y_UNIT_TEST_F (WriteToTopic_Demo_37, TFixture)
2042+ {
2043+ WriteMessagesInTx (1 , 1 );
2044+ WriteMessagesInTx (1 , 1 );
2045+ }
2046+
2047+
2048+ Y_UNIT_TEST_F (WriteToTopic_Demo_38, TFixture)
2049+ {
2050+ WriteMessagesInTx (2 , 202 );
2051+ WriteMessagesInTx (2 , 200 );
2052+ WriteMessagesInTx (0 , 1 );
2053+ WriteMessagesInTx (4 , 0 );
2054+ WriteMessagesInTx (0 , 1 );
2055+ }
2056+
2057+ Y_UNIT_TEST_F (ReadRuleGeneration, TFixture)
2058+ {
2059+ // There was a server
2060+ NotifySchemeShard ({.EnablePQConfigTransactionsAtSchemeShard = false });
2061+
2062+ // Users have created their own topic on it
2063+ CreateTopic (TEST_TOPIC);
2064+
2065+ // And they wrote their messages into it
2066+ WriteToTopic (TEST_TOPIC, TEST_MESSAGE_GROUP_ID, " message-1" );
2067+ WriteToTopic (TEST_TOPIC, TEST_MESSAGE_GROUP_ID, " message-2" );
2068+ WriteToTopic (TEST_TOPIC, TEST_MESSAGE_GROUP_ID, " message-3" );
2069+
2070+ // And he had a consumer
2071+ AddConsumer (TEST_TOPIC, {" consumer-1" });
2072+
2073+ // We read messages from the topic and committed offsets
2074+ auto messages = ReadFromTopic (TEST_TOPIC, " consumer-1" , TDuration::Seconds (2 ));
2075+ UNIT_ASSERT_VALUES_EQUAL (messages.size (), 3 );
2076+ CloseTopicReadSession (TEST_TOPIC, " consumer-1" );
2077+
2078+ // And then the Logbroker team turned on the feature flag
2079+ NotifySchemeShard ({.EnablePQConfigTransactionsAtSchemeShard = true });
2080+
2081+ // Users continued to write to the topic
2082+ WriteToTopic (TEST_TOPIC, TEST_MESSAGE_GROUP_ID, " message-4" );
2083+
2084+ // Users have added new consumers
2085+ AddConsumer (TEST_TOPIC, {" consumer-2" });
2086+
2087+ // And they wanted to continue reading their messages
2088+ messages = ReadFromTopic (TEST_TOPIC, " consumer-1" , TDuration::Seconds (2 ));
2089+ UNIT_ASSERT_VALUES_EQUAL (messages.size (), 1 );
2090+ }
2091+
2092+ }
2093+
2094+ }
0 commit comments