Skip to content

Commit ac2e53a

Browse files
code EES_WRITTEN_IN_TX (#7766)
1 parent 49fe58f commit ac2e53a

File tree

7 files changed

+84
-49
lines changed

7 files changed

+84
-49
lines changed

ydb/core/persqueue/partition_write.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ void TPartition::ReplyWrite(
7878
write->SetTotalTimeInPartitionQueueMs(queueTime.MilliSeconds());
7979
write->SetWriteTimeMs(writeTime.MilliSeconds());
8080

81+
write->SetWrittenInTx(IsSupportive());
82+
8183
ctx.Send(Tablet, response.Release());
8284
}
8385

ydb/core/protos/msgbus_pq.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,8 @@ message TPersQueuePartitionResponse {
446446
optional uint32 TopicQuotedTimeMs = 11;
447447
optional uint32 TotalTimeInPartitionQueueMs = 9;
448448
optional uint32 WriteTimeMs = 10;
449+
450+
optional bool WrittenInTx = 12;
449451
}
450452

451453
message TCmdGetMaxSeqNoResult {

ydb/public/api/protos/ydb_topic.proto

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ message StreamWriteMessage {
198198
oneof message_write_status {
199199
Written written = 2;
200200
Skipped skipped = 3;
201+
WrittenInTx written_in_tx = 4;
201202
}
202203

203204
message Written {
@@ -213,6 +214,9 @@ message StreamWriteMessage {
213214
REASON_ALREADY_WRITTEN = 1;
214215
}
215216
}
217+
218+
message WrittenInTx {
219+
}
216220
}
217221

218222
// Message with write statistics.

ydb/public/sdk/cpp/client/ydb_topic/impl/write_session_impl.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -982,17 +982,23 @@ TWriteSessionImpl::TProcessSrvMessageResult TWriteSessionImpl::ProcessServerMess
982982
writeStat->PartitionQuotedTime = durationConv(stat.partition_quota_wait_time());
983983
writeStat->TopicQuotedTime = durationConv(stat.topic_quota_wait_time());
984984

985-
for (size_t messageIndex = 0, endIndex = batchWriteResponse.acks_size(); messageIndex != endIndex; ++messageIndex) {
985+
for (const auto& ack : batchWriteResponse.acks()) {
986986
// TODO: Fill writer statistics
987-
auto ack = batchWriteResponse.acks(messageIndex);
988987
ui64 sequenceNumber = ack.seq_no();
989988

990-
Y_ABORT_UNLESS(ack.has_written() || ack.has_skipped());
991-
auto msgWriteStatus = ack.has_written()
992-
? TWriteSessionEvent::TWriteAck::EES_WRITTEN
993-
: (ack.skipped().reason() == Ydb::Topic::StreamWriteMessage_WriteResponse_WriteAck_Skipped_Reason::StreamWriteMessage_WriteResponse_WriteAck_Skipped_Reason_REASON_ALREADY_WRITTEN
994-
? TWriteSessionEvent::TWriteAck::EES_ALREADY_WRITTEN
995-
: TWriteSessionEvent::TWriteAck::EES_DISCARDED);
989+
Y_ABORT_UNLESS(ack.has_written() || ack.has_skipped() || ack.has_written_in_tx());
990+
991+
TWriteSessionEvent::TWriteAck::EEventState msgWriteStatus;
992+
if (ack.has_written_in_tx()) {
993+
msgWriteStatus = TWriteSessionEvent::TWriteAck::EES_WRITTEN_IN_TX;
994+
} else if (ack.has_written()) {
995+
msgWriteStatus = TWriteSessionEvent::TWriteAck::EES_WRITTEN;
996+
} else {
997+
msgWriteStatus =
998+
(ack.skipped().reason() == Ydb::Topic::StreamWriteMessage_WriteResponse_WriteAck_Skipped_Reason::StreamWriteMessage_WriteResponse_WriteAck_Skipped_Reason_REASON_ALREADY_WRITTEN)
999+
? TWriteSessionEvent::TWriteAck::EES_ALREADY_WRITTEN
1000+
: TWriteSessionEvent::TWriteAck::EES_DISCARDED;
1001+
}
9961002

9971003
ui64 offset = ack.has_written() ? ack.written().offset() : 0;
9981004

ydb/public/sdk/cpp/client/ydb_topic/include/write_events.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ struct TWriteSessionEvent {
5555
enum EEventState {
5656
EES_WRITTEN, //! Successfully written.
5757
EES_ALREADY_WRITTEN, //! Skipped on SeqNo deduplication.
58-
EES_DISCARDED //! In case of destruction of writer or retry policy discarded future retries in this writer.
58+
EES_DISCARDED, //! In case of destruction of writer or retry policy discarded future retries in this writer.
59+
EES_WRITTEN_IN_TX, //! Successfully written in tx.
5960
};
6061
//! Details of successfully written message.
6162
struct TWrittenMessageDetails {

ydb/public/sdk/cpp/client/ydb_topic/ut/topic_to_table_ut.cpp

Lines changed: 56 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,15 @@ class TFixture : public NUnitTest::TBaseFixture {
3131
TTopicWriteSessionPtr Session;
3232
TMaybe<NTopic::TContinuationToken> ContinuationToken;
3333
size_t WriteCount = 0;
34-
size_t AckCount = 0;
34+
size_t WrittenAckCount = 0;
35+
size_t WrittenInTxAckCount = 0;
3536

3637
void WaitForContinuationToken();
3738
void Write(const TString& message, NTable::TTransaction* tx = nullptr);
39+
40+
size_t AckCount() const { return WrittenAckCount + WrittenInTxAckCount; }
41+
42+
void WaitForEvent();
3843
};
3944

4045
void SetUp(NUnitTest::TTestContext&) override;
@@ -88,7 +93,8 @@ class TFixture : public NUnitTest::TBaseFixture {
8893
NTable::TTransaction* tx = nullptr,
8994
TMaybe<ui32> partitionId = Nothing());
9095
void WaitForAcks(const TString& topicPath,
91-
const TString& messageGroupId);
96+
const TString& messageGroupId,
97+
size_t writtenInTxCount = Max<size_t>());
9298
void WaitForSessionClose(const TString& topicPath,
9399
const TString& messageGroupId,
94100
NYdb::EStatus status);
@@ -591,19 +597,31 @@ auto TFixture::GetTopicReadSession(const TString& topicPath,
591597
void TFixture::TTopicWriteSessionContext::WaitForContinuationToken()
592598
{
593599
while (!ContinuationToken.Defined()) {
594-
Session->WaitEvent().Wait();
595-
for (auto& event : Session->GetEvents()) {
596-
if (auto* e = std::get_if<NTopic::TWriteSessionEvent::TReadyToAcceptEvent>(&event)) {
597-
ContinuationToken = std::move(e->ContinuationToken);
598-
} else if (auto* e = std::get_if<NTopic::TWriteSessionEvent::TAcksEvent>(&event)) {
599-
for (auto& ack : e->Acks) {
600-
if (ack.State == NTopic::TWriteSessionEvent::TWriteAck::EES_WRITTEN) {
601-
++AckCount;
602-
}
600+
WaitForEvent();
601+
}
602+
}
603+
604+
void TFixture::TTopicWriteSessionContext::WaitForEvent()
605+
{
606+
Session->WaitEvent().Wait();
607+
for (auto& event : Session->GetEvents()) {
608+
if (auto* e = std::get_if<NTopic::TWriteSessionEvent::TReadyToAcceptEvent>(&event)) {
609+
ContinuationToken = std::move(e->ContinuationToken);
610+
} else if (auto* e = std::get_if<NTopic::TWriteSessionEvent::TAcksEvent>(&event)) {
611+
for (auto& ack : e->Acks) {
612+
switch (ack.State) {
613+
case NTopic::TWriteSessionEvent::TWriteAck::EES_WRITTEN:
614+
++WrittenAckCount;
615+
break;
616+
case NTopic::TWriteSessionEvent::TWriteAck::EES_WRITTEN_IN_TX:
617+
++WrittenInTxAckCount;
618+
break;
619+
default:
620+
break;
603621
}
604-
} else if (auto* e = std::get_if<NTopic::TSessionClosedEvent>(&event)) {
605-
UNIT_FAIL("");
606622
}
623+
} else if (auto* e = std::get_if<NTopic::TSessionClosedEvent>(&event)) {
624+
UNIT_FAIL("");
607625
}
608626
}
609627
}
@@ -691,34 +709,25 @@ TVector<TString> TFixture::ReadFromTopic(const TString& topicPath,
691709
return messages;
692710
}
693711

694-
void TFixture::WaitForAcks(const TString& topicPath, const TString& messageGroupId)
712+
void TFixture::WaitForAcks(const TString& topicPath, const TString& messageGroupId, size_t writtenInTxCount)
695713
{
696714
std::pair<TString, TString> key(topicPath, messageGroupId);
697715
auto i = TopicWriteSessions.find(key);
698716
UNIT_ASSERT(i != TopicWriteSessions.end());
699717

700718
auto& context = i->second;
701719

702-
UNIT_ASSERT(context.AckCount <= context.WriteCount);
720+
UNIT_ASSERT(context.AckCount() <= context.WriteCount);
703721

704-
while (context.AckCount < context.WriteCount) {
705-
context.Session->WaitEvent().Wait();
706-
for (auto& event : context.Session->GetEvents()) {
707-
if (auto* e = std::get_if<NTopic::TWriteSessionEvent::TReadyToAcceptEvent>(&event)) {
708-
context.ContinuationToken = std::move(e->ContinuationToken);
709-
} else if (auto* e = std::get_if<NTopic::TWriteSessionEvent::TAcksEvent>(&event)) {
710-
for (auto& ack : e->Acks) {
711-
if (ack.State == NTopic::TWriteSessionEvent::TWriteAck::EES_WRITTEN) {
712-
++context.AckCount;
713-
}
714-
}
715-
} else if (auto* e = std::get_if<NTopic::TSessionClosedEvent>(&event)) {
716-
UNIT_FAIL("");
717-
}
718-
}
722+
while (context.AckCount() < context.WriteCount) {
723+
context.WaitForEvent();
719724
}
720725

721-
UNIT_ASSERT(context.AckCount == context.WriteCount);
726+
UNIT_ASSERT((context.WrittenAckCount + context.WrittenInTxAckCount) == context.WriteCount);
727+
728+
if (writtenInTxCount != Max<size_t>()) {
729+
UNIT_ASSERT_VALUES_EQUAL(context.WrittenInTxAckCount, writtenInTxCount);
730+
}
722731
}
723732

724733
void TFixture::WaitForSessionClose(const TString& topicPath,
@@ -731,7 +740,7 @@ void TFixture::WaitForSessionClose(const TString& topicPath,
731740

732741
auto& context = i->second;
733742

734-
UNIT_ASSERT(context.AckCount <= context.WriteCount);
743+
UNIT_ASSERT(context.AckCount() <= context.WriteCount);
735744

736745
for(bool stop = false; !stop; ) {
737746
context.Session->WaitEvent().Wait();
@@ -740,8 +749,15 @@ void TFixture::WaitForSessionClose(const TString& topicPath,
740749
context.ContinuationToken = std::move(e->ContinuationToken);
741750
} else if (auto* e = std::get_if<NTopic::TWriteSessionEvent::TAcksEvent>(&event)) {
742751
for (auto& ack : e->Acks) {
743-
if (ack.State == NTopic::TWriteSessionEvent::TWriteAck::EES_WRITTEN) {
744-
++context.AckCount;
752+
switch (ack.State) {
753+
case NTopic::TWriteSessionEvent::TWriteAck::EES_WRITTEN:
754+
++context.WrittenAckCount;
755+
break;
756+
case NTopic::TWriteSessionEvent::TWriteAck::EES_WRITTEN_IN_TX:
757+
++context.WrittenInTxAckCount;
758+
break;
759+
default:
760+
break;
745761
}
746762
}
747763
} else if (auto* e = std::get_if<NTopic::TSessionClosedEvent>(&event)) {
@@ -752,7 +768,7 @@ void TFixture::WaitForSessionClose(const TString& topicPath,
752768
}
753769
}
754770

755-
UNIT_ASSERT(context.AckCount <= context.WriteCount);
771+
UNIT_ASSERT(context.AckCount() <= context.WriteCount);
756772
}
757773

758774
ui64 TFixture::GetTopicTabletId(const TActorId& actorId, const TString& topicPath, ui32 partition)
@@ -1852,7 +1868,7 @@ Y_UNIT_TEST_F(WriteToTopic_Demo_27, TFixture)
18521868
CreateTopic("topic_B", TEST_CONSUMER);
18531869
CreateTopic("topic_C", TEST_CONSUMER);
18541870

1855-
for (size_t i = 0; i < 2; ++i) {
1871+
for (size_t i = 0, writtenInTx = 0; i < 2; ++i) {
18561872
WriteToTopic("topic_A", TEST_MESSAGE_GROUP_ID, "message #1", nullptr, 0);
18571873
WriteToTopic("topic_B", TEST_MESSAGE_GROUP_ID, "message #2", nullptr, 0);
18581874

@@ -1862,12 +1878,14 @@ Y_UNIT_TEST_F(WriteToTopic_Demo_27, TFixture)
18621878
auto messages = ReadFromTopic("topic_A", TEST_CONSUMER, TDuration::Seconds(2), &tx, 0);
18631879
UNIT_ASSERT_VALUES_EQUAL(messages.size(), 1);
18641880
WriteToTopic("topic_C", TEST_MESSAGE_GROUP_ID, messages[0], &tx, 0);
1865-
WaitForAcks("topic_C", TEST_MESSAGE_GROUP_ID);
1881+
++writtenInTx;
1882+
WaitForAcks("topic_C", TEST_MESSAGE_GROUP_ID, writtenInTx);
18661883

18671884
messages = ReadFromTopic("topic_B", TEST_CONSUMER, TDuration::Seconds(2), &tx, 0);
18681885
UNIT_ASSERT_VALUES_EQUAL(messages.size(), 1);
18691886
WriteToTopic("topic_C", TEST_MESSAGE_GROUP_ID, messages[0], &tx, 0);
1870-
WaitForAcks("topic_C", TEST_MESSAGE_GROUP_ID);
1887+
++writtenInTx;
1888+
WaitForAcks("topic_C", TEST_MESSAGE_GROUP_ID, writtenInTx);
18711889

18721890
CommitTx(tx, EStatus::SUCCESS);
18731891

ydb/services/persqueue_v1/actors/write_session_actor.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -928,14 +928,16 @@ void TWriteSessionActor<UseMigrationProtocol>::ProcessWriteResponse(
928928
};
929929

930930
auto addAck = [this](const TPersQueuePartitionResponse::TCmdWriteResult& res,
931-
Topic::StreamWriteMessage::WriteResponse* writeResponse,
932-
Topic::StreamWriteMessage::WriteResponse::WriteStatistics* stat) {
931+
Topic::StreamWriteMessage::WriteResponse* writeResponse,
932+
Topic::StreamWriteMessage::WriteResponse::WriteStatistics* stat) {
933933
auto ack = writeResponse->add_acks();
934934
// TODO (ildar-khisam@): validate res before filling ack fields
935935
ack->set_seq_no(res.GetSeqNo());
936936
if (res.GetAlreadyWritten()) {
937937
Y_ABORT_UNLESS(UseDeduplication);
938938
ack->mutable_skipped()->set_reason(Topic::StreamWriteMessage::WriteResponse::WriteAck::Skipped::REASON_ALREADY_WRITTEN);
939+
} else if (res.HasWrittenInTx() && res.GetWrittenInTx()) {
940+
ack->mutable_written_in_tx();
939941
} else {
940942
ack->mutable_written()->set_offset(res.GetOffset());
941943
}

0 commit comments

Comments
 (0)