@@ -2001,7 +2001,8 @@ void TPersQueue::HandleWriteRequest(const ui64 responseCookie, const TActorId& p
20012001 " Tablet " << TabletID () <<
20022002 " Write in transaction." <<
20032003 " Partition: " << req.GetPartition () <<
2004- " , WriteId: " << req.GetWriteId ());
2004+ " , WriteId: " << req.GetWriteId () <<
2005+ " , FirstWrite: " << req.GetFirstWrite ());
20052006 }
20062007
20072008 for (ui32 i = 0 ; i < req.CmdWriteSize (); ++i) {
@@ -2198,7 +2199,8 @@ void TPersQueue::HandleReserveBytesRequest(const ui64 responseCookie, const TAct
21982199 " Tablet " << TabletID () <<
21992200 " Reserve bytes in transaction." <<
22002201 " Partition: " << req.GetPartition () <<
2201- " , WriteId: " << req.GetWriteId ());
2202+ " , WriteId: " << req.GetWriteId () <<
2203+ " , FirstWrite: " << req.GetFirstWrite ());
22022204 }
22032205
22042206 InitResponseBuilder (responseCookie, 1 , COUNTER_LATENCY_PQ_RESERVE_BYTES);
@@ -2574,6 +2576,8 @@ void TPersQueue::HandleWriteRequestForSupportivePartition(const ui64 responseCoo
25742576 const NKikimrClient::TPersQueuePartitionRequest& req,
25752577 const TActorContext& ctx)
25762578{
2579+ Y_ABORT_UNLESS (req.HasWriteId ());
2580+
25772581 const TPartitionInfo& partition = GetPartitionInfo (req);
25782582 const TActorId& actorId = partition.Actor ;
25792583
@@ -2618,6 +2622,7 @@ void TPersQueue::HandleEventForSupportivePartition(const ui64 responseCookie,
26182622
26192623 ui64 writeId = req.GetWriteId ();
26202624 ui32 originalPartitionId = req.GetPartition ();
2625+ bool firstWrite = req.GetFirstWrite ();
26212626
26222627 if (TxWrites.contains (writeId) && TxWrites.at (writeId).Partitions .contains (originalPartitionId)) {
26232628 //
@@ -2648,6 +2653,14 @@ void TPersQueue::HandleEventForSupportivePartition(const ui64 responseCookie,
26482653 sender);
26492654 }
26502655 } else {
2656+ if (!firstWrite) {
2657+ ReplyError (ctx,
2658+ responseCookie,
2659+ NPersQueue::NErrorCode::BAD_REQUEST,
2660+ " lost messages" );
2661+ return ;
2662+ }
2663+
26512664 //
26522665 // этап 1:
26532666 // - создать запись в TxWrites
@@ -2665,6 +2678,7 @@ void TPersQueue::HandleEventForSupportivePartition(const ui64 responseCookie,
26652678 TPartitionId partitionId (originalPartitionId, writeId, NextSupportivePartitionId++);
26662679
26672680 writeInfo.Partitions .emplace (originalPartitionId, partitionId);
2681+ TxWritesChanged = true ;
26682682 AddSupportivePartition (partitionId);
26692683
26702684 Y_ABORT_UNLESS (Partitions.contains (partitionId));
@@ -3115,6 +3129,38 @@ void TPersQueue::Handle(TEvPersQueue::TEvProposeTransaction::TPtr& ev, const TAc
31153129
31163130}
31173131
3132+ bool TPersQueue::CheckTxWriteOperation (const NKikimrPQ::TPartitionOperation& operation,
3133+ ui64 writeId) const
3134+ {
3135+ TPartitionId partitionId (operation.GetPartitionId (),
3136+ writeId,
3137+ operation.GetSupportivePartition ());
3138+ return Partitions.contains (partitionId);
3139+ }
3140+
3141+ bool TPersQueue::CheckTxWriteOperations (const NKikimrPQ::TDataTransaction& txBody) const
3142+ {
3143+ if (!txBody.HasWriteId ()) {
3144+ return true ;
3145+ }
3146+
3147+ ui64 writeId = txBody.GetWriteId ();
3148+
3149+ for (auto & operation : txBody.GetOperations ()) {
3150+ auto isWrite = [](const NKikimrPQ::TPartitionOperation& o) {
3151+ return !o.HasBegin ();
3152+ };
3153+
3154+ if (isWrite (operation)) {
3155+ if (!CheckTxWriteOperation (operation, writeId)) {
3156+ return false ;
3157+ }
3158+ }
3159+ }
3160+
3161+ return true ;
3162+ }
3163+
31183164void TPersQueue::HandleDataTransaction (TAutoPtr<TEvPersQueue::TEvProposeTransaction> ev,
31193165 const TActorContext& ctx)
31203166{
@@ -3123,23 +3169,6 @@ void TPersQueue::HandleDataTransaction(TAutoPtr<TEvPersQueue::TEvProposeTransact
31233169 Y_ABORT_UNLESS (event.HasData ());
31243170 const NKikimrPQ::TDataTransaction& txBody = event.GetData ();
31253171
3126- for (auto & operation : txBody.GetOperations ()) {
3127- Y_ABORT_UNLESS (!operation.HasPath () || (operation.GetPath () == TopicPath));
3128-
3129- bool isWriteOperation = !operation.HasBegin ();
3130-
3131- LOG_DEBUG_S (ctx, NKikimrServices::PERSQUEUE,
3132- " Tablet " << TabletID () <<
3133- " tx=" << event.GetTxId () <<
3134- " , write_id=" << txBody.GetWriteId () <<
3135- " , path=" << operation.GetPath () <<
3136- " , partition=" << operation.GetPartitionId () <<
3137- " , consumer=" << operation.GetConsumer () <<
3138- " , begin=" << operation.GetBegin () <<
3139- " , end=" << operation.GetEnd () <<
3140- " , is_write=" << isWriteOperation);
3141- }
3142-
31433172 if (TabletState != NKikimrPQ::ENormal) {
31443173 SendProposeTransactionAbort (ActorIdFromProto (event.GetSourceActor ()),
31453174 event.GetTxId (),
@@ -3158,6 +3187,13 @@ void TPersQueue::HandleDataTransaction(TAutoPtr<TEvPersQueue::TEvProposeTransact
31583187 return ;
31593188 }
31603189
3190+ if (!CheckTxWriteOperations (txBody)) {
3191+ SendProposeTransactionAbort (ActorIdFromProto (event.GetSourceActor ()),
3192+ event.GetTxId (),
3193+ ctx);
3194+ return ;
3195+ }
3196+
31613197 TMaybe<TPartitionId> partitionId = FindPartitionId (txBody);
31623198 if (!partitionId.Defined ()) {
31633199 SendProposeTransactionAbort (ActorIdFromProto (event.GetSourceActor ()),
@@ -3392,7 +3428,8 @@ void TPersQueue::BeginWriteTxs(const TActorContext& ctx)
33923428 CanProcessPlanStepQueue () ||
33933429 CanProcessWriteTxs () ||
33943430 CanProcessDeleteTxs () ||
3395- CanProcessTxWrites ()
3431+ CanProcessTxWrites () ||
3432+ TxWritesChanged
33963433 ;
33973434 if (!canProcess) {
33983435 return ;
@@ -3441,6 +3478,8 @@ void TPersQueue::EndWriteTxs(const NKikimrClient::TResponse& resp,
34413478 return ;
34423479 }
34433480
3481+ TxWritesChanged = false ;
3482+
34443483 SendReplies (ctx);
34453484 CheckChangedTxStates (ctx);
34463485 CreateSupportivePartitionActors (ctx);
@@ -4411,7 +4450,7 @@ void TPersQueue::ProcessCheckPartitionStatusRequests(const TPartitionId& partiti
44114450 }
44124451}
44134452
4414- void TPersQueue::Handle (NLongTxService::TEvLongTxService::TEvLockStatus::TPtr& ev, const TActorContext&)
4453+ void TPersQueue::Handle (NLongTxService::TEvLongTxService::TEvLockStatus::TPtr& ev, const TActorContext& ctx )
44154454{
44164455 auto & record = ev->Get ()->Record ;
44174456 ui64 writeId = record.GetLockId ();
@@ -4473,6 +4512,7 @@ void TPersQueue::Handle(TEvPQ::TEvDeletePartitionDone::TPtr& ev, const TActorCon
44734512 }
44744513 TxWrites.erase (writeId);
44754514 }
4515+ TxWritesChanged = true ;
44764516
44774517 TryWriteTxs (ctx);
44784518}
0 commit comments