@@ -197,6 +197,7 @@ class TPQTabletFixture : public NUnitTest::TBaseFixture {
197
197
198
198
void WaitReadSetAck (NHelpers::TPQTabletMock& tablet, const TReadSetAckMatcher& matcher);
199
199
void SendReadSetAck (NHelpers::TPQTabletMock& tablet);
200
+ void WaitForNoReadSetAck (NHelpers::TPQTabletMock& tablet);
200
201
201
202
void SendDropTablet (const TDropTabletParams& params);
202
203
void WaitDropTabletReply (const TDropTabletReplyMatcher& matcher);
@@ -206,7 +207,7 @@ class TPQTabletFixture : public NUnitTest::TBaseFixture {
206
207
207
208
void SendCancelTransactionProposal (const TCancelTransactionProposalParams& params);
208
209
209
- void StartPQWriteTxsObserver ();
210
+ void StartPQWriteTxsObserver (TAutoPtr<IEventHandle>* ev = nullptr );
210
211
void WaitForPQWriteTxs ();
211
212
212
213
template <class T > void WaitForEvent (size_t count);
@@ -215,7 +216,7 @@ class TPQTabletFixture : public NUnitTest::TBaseFixture {
215
216
216
217
void TestWaitingForTEvReadSet (size_t senders, size_t receivers);
217
218
218
- void StartPQWriteObserver (bool & flag, unsigned cookie);
219
+ void StartPQWriteObserver (bool & flag, unsigned cookie, TAutoPtr<IEventHandle>* ev = nullptr );
219
220
void WaitForPQWriteComplete (bool & flag);
220
221
221
222
bool FoundPQWriteState = false ;
@@ -241,6 +242,9 @@ class TPQTabletFixture : public NUnitTest::TBaseFixture {
241
242
void WaitForTxState (ui64 txId, NKikimrPQ::TTransaction::EState state);
242
243
void WaitForExecStep (ui64 step);
243
244
245
+ void InterceptSaveTxState (TAutoPtr<IEventHandle>& event);
246
+ void SendSaveTxState (TAutoPtr<IEventHandle>& event);
247
+
244
248
//
245
249
// TODO(abcdef): для тестирования повторных вызовов нужны примитивы Send+Wait
246
250
//
@@ -522,6 +526,17 @@ void TPQTabletFixture::WaitReadSetAck(NHelpers::TPQTabletMock& tablet, const TRe
522
526
}
523
527
}
524
528
529
+ void TPQTabletFixture::WaitForNoReadSetAck (NHelpers::TPQTabletMock& tablet)
530
+ {
531
+ TDispatchOptions options;
532
+ options.CustomFinalCondition = [&]() {
533
+ return tablet.ReadSetAck .Defined ();
534
+ };
535
+ Ctx->Runtime ->DispatchEvents (options, TDuration::Seconds (2 ));
536
+
537
+ UNIT_ASSERT (!tablet.ReadSetAck .Defined ());
538
+ }
539
+
525
540
void TPQTabletFixture::SendDropTablet (const TDropTabletParams& params)
526
541
{
527
542
auto event = MakeHolder<TEvPersQueue::TEvDropTablet>();
@@ -745,18 +760,21 @@ void TPQTabletFixture::WaitWriteResponse(const TWriteResponseMatcher& matcher)
745
760
Ctx->Runtime ->SetObserverFunc (prev);
746
761
}
747
762
748
- void TPQTabletFixture::StartPQWriteObserver (bool & flag, unsigned cookie)
763
+ void TPQTabletFixture::StartPQWriteObserver (bool & flag, unsigned cookie, TAutoPtr<IEventHandle>* ev )
749
764
{
750
765
flag = false ;
751
766
752
- auto observer = [&flag, cookie](TAutoPtr<IEventHandle>& event) {
767
+ auto observer = [&flag, cookie, ev ](TAutoPtr<IEventHandle>& event) {
753
768
if (auto * kvResponse = event->CastAsLocal <TEvKeyValue::TEvResponse>()) {
754
- if (kvResponse->Record .HasCookie ()) {
755
- }
756
769
if ((event->Sender == event->Recipient ) &&
757
770
kvResponse->Record .HasCookie () &&
758
771
(kvResponse->Record .GetCookie () == cookie)) {
759
772
flag = true ;
773
+
774
+ if (ev) {
775
+ *ev = event;
776
+ return TTestActorRuntimeBase::EEventAction::DROP;
777
+ }
760
778
}
761
779
}
762
780
@@ -793,9 +811,9 @@ void TPQTabletFixture::SendCancelTransactionProposal(const TCancelTransactionPro
793
811
event.Release ());
794
812
}
795
813
796
- void TPQTabletFixture::StartPQWriteTxsObserver ()
814
+ void TPQTabletFixture::StartPQWriteTxsObserver (TAutoPtr<IEventHandle>* event )
797
815
{
798
- StartPQWriteObserver (FoundPQWriteTxs, 5 ); // TPersQueue::WRITE_TX_COOKIE
816
+ StartPQWriteObserver (FoundPQWriteTxs, 5 , event ); // TPersQueue::WRITE_TX_COOKIE
799
817
}
800
818
801
819
void TPQTabletFixture::WaitForPQWriteTxs ()
@@ -1030,6 +1048,40 @@ void TPQTabletFixture::WaitForExecStep(ui64 step)
1030
1048
UNIT_FAIL (" expected execution step " << step);
1031
1049
}
1032
1050
1051
+ void TPQTabletFixture::InterceptSaveTxState (TAutoPtr<IEventHandle>& ev)
1052
+ {
1053
+ bool found = false ;
1054
+
1055
+ TTestActorRuntimeBase::TEventFilter prev;
1056
+ auto filter = [&](TTestActorRuntimeBase&, TAutoPtr<IEventHandle>& event) -> bool {
1057
+ if (auto * msg = event->CastAsLocal <TEvKeyValue::TEvRequest>()) {
1058
+ if (msg->Record .HasCookie () && (msg->Record .GetCookie () == 5 )) { // WRITE_TX_COOKIE
1059
+ ev = event;
1060
+ found = true ;
1061
+ return true ;
1062
+ }
1063
+ }
1064
+
1065
+ return false ;
1066
+ };
1067
+ prev = Ctx->Runtime ->SetEventFilter (filter);
1068
+
1069
+ TDispatchOptions options;
1070
+ options.CustomFinalCondition = [&found]() {
1071
+ return found;
1072
+ };
1073
+
1074
+ UNIT_ASSERT (Ctx->Runtime ->DispatchEvents (options));
1075
+ UNIT_ASSERT (found);
1076
+
1077
+ Ctx->Runtime ->SetEventFilter (prev);
1078
+ }
1079
+
1080
+ void TPQTabletFixture::SendSaveTxState (TAutoPtr<IEventHandle>& event)
1081
+ {
1082
+ Ctx->Runtime ->Send (event);
1083
+ }
1084
+
1033
1085
Y_UNIT_TEST_F (Parallel_Transactions_1, TPQTabletFixture)
1034
1086
{
1035
1087
TestParallelTransactions (" consumer" , " consumer" );
@@ -1926,6 +1978,45 @@ Y_UNIT_TEST_F(After_Restarting_The_Tablet_Sends_A_TEvReadSet_For_Transactions_In
1926
1978
WaitReadSetEx (*tablet, {.Step =100 , .TxId =txId_1, .Decision =NKikimrTx::TReadSetData::DECISION_COMMIT, .Count =2 });
1927
1979
}
1928
1980
1981
+ Y_UNIT_TEST_F (TEvReadSet_Is_Not_Sent_Ahead_Of_Time, TPQTabletFixture)
1982
+ {
1983
+ const ui64 txId = 67890 ;
1984
+ const ui64 mockTabletId = 22222 ;
1985
+
1986
+ NHelpers::TPQTabletMock* tablet = CreatePQTabletMock (mockTabletId);
1987
+ PQTabletPrepare ({.partitions =1 }, {}, *Ctx);
1988
+
1989
+ SendProposeTransactionRequest ({.TxId =txId,
1990
+ .Senders ={mockTabletId}, .Receivers ={mockTabletId},
1991
+ .TxOps ={
1992
+ {.Partition =0 , .Consumer =" user" , .Begin =0 , .End =0 , .Path =" /topic" },
1993
+ }});
1994
+ WaitProposeTransactionResponse ({.TxId =txId,
1995
+ .Status =NKikimrPQ::TEvProposeTransactionResult::PREPARED});
1996
+
1997
+ SendPlanStep ({.Step =100 , .TxIds ={txId}});
1998
+
1999
+ WaitForCalcPredicateResult ();
2000
+
2001
+ tablet->SendReadSet (*Ctx->Runtime , {.Step =100 , .TxId =txId, .Target =Ctx->TabletId , .Decision =NKikimrTx::TReadSetData::DECISION_COMMIT});
2002
+
2003
+ // WaitProposeTransactionResponse({.TxId=txId,
2004
+ // .Status=NKikimrPQ::TEvProposeTransactionResult::COMPLETE});
2005
+
2006
+ TAutoPtr<IEventHandle> kvRequest;
2007
+ InterceptSaveTxState (kvRequest);
2008
+
2009
+ tablet->SendReadSet (*Ctx->Runtime , {.Step =100 , .TxId =txId, .Target =Ctx->TabletId , .Decision =NKikimrTx::TReadSetData::DECISION_COMMIT});
2010
+
2011
+ WaitForNoReadSetAck (*tablet);
2012
+
2013
+ SendSaveTxState (kvRequest);
2014
+
2015
+ WaitForTxState (txId, NKikimrPQ::TTransaction::EXECUTED);
2016
+
2017
+ WaitReadSetAck (*tablet, {.Step =100 , .TxId =txId, .Source =22222 , .Target =Ctx->TabletId , .Consumer =Ctx->TabletId });
2018
+ }
2019
+
1929
2020
}
1930
2021
1931
2022
}
0 commit comments