Skip to content

Commit 55fdbd1

Browse files
committed
YQ-3756 Shared reading: check buffer size in read_actor (ydb-platform#10418)
1 parent 398dbfd commit 55fdbd1

File tree

4 files changed

+79
-22
lines changed

4 files changed

+79
-22
lines changed

ydb/library/yql/providers/pq/async_io/dq_pq_rd_read_actor.cpp

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,10 @@ class TDqPqRdReadActor : public NActors::TActor<TDqPqRdReadActor>, public NYql::
150150
const TTxId& txId,
151151
const NActors::TActorId selfId,
152152
TActorId rowDispatcherActorId,
153+
ui64 partitionId,
153154
ui64 eventQueueId)
154-
: RowDispatcherActorId(rowDispatcherActorId) {
155+
: RowDispatcherActorId(rowDispatcherActorId)
156+
, PartitionId(partitionId) {
155157
EventsQueue.Init(txId, selfId, selfId, eventQueueId, /* KeepAlive */ true);
156158
EventsQueue.OnNewRecipientId(rowDispatcherActorId);
157159
}
@@ -160,12 +162,15 @@ class TDqPqRdReadActor : public NActors::TActor<TDqPqRdReadActor>, public NYql::
160162
ui64 NextOffset = 0;
161163
bool IsWaitingRowDispatcherResponse = false;
162164
NYql::NDq::TRetryEventsQueue EventsQueue;
163-
bool NewDataArrived = false;
165+
bool HasPendingData = false;
164166
TActorId RowDispatcherActorId;
167+
ui64 PartitionId;
165168
};
166169

167170
TMap<ui64, SessionInfo> Sessions;
168171
const THolderFactory& HolderFactory;
172+
const i64 MaxBufferSize;
173+
i64 ReadyBufferSizeBytes = 0;
169174

170175
public:
171176
TDqPqRdReadActor(
@@ -179,7 +184,8 @@ class TDqPqRdReadActor : public NActors::TActor<TDqPqRdReadActor>, public NYql::
179184
const NActors::TActorId& computeActorId,
180185
const NActors::TActorId& localRowDispatcherActorId,
181186
const TString& token,
182-
const ::NMonitoring::TDynamicCounterPtr& counters);
187+
const ::NMonitoring::TDynamicCounterPtr& counters,
188+
i64 bufferSize);
183189

184190
void Handle(NFq::TEvRowDispatcher::TEvCoordinatorChanged::TPtr& ev);
185191
void Handle(NFq::TEvRowDispatcher::TEvCoordinatorResult::TPtr& ev);
@@ -233,6 +239,7 @@ class TDqPqRdReadActor : public NActors::TActor<TDqPqRdReadActor>, public NYql::
233239
void StopSessions();
234240
void ReInit(const TString& reason);
235241
void PrintInternalState();
242+
void TrySendGetNextBatch(SessionInfo& sessionInfo);
236243
};
237244

238245
TDqPqRdReadActor::TDqPqRdReadActor(
@@ -246,13 +253,15 @@ TDqPqRdReadActor::TDqPqRdReadActor(
246253
const NActors::TActorId& computeActorId,
247254
const NActors::TActorId& localRowDispatcherActorId,
248255
const TString& token,
249-
const ::NMonitoring::TDynamicCounterPtr& counters)
256+
const ::NMonitoring::TDynamicCounterPtr& counters,
257+
i64 bufferSize)
250258
: TActor<TDqPqRdReadActor>(&TDqPqRdReadActor::StateFunc)
251259
, TDqPqReadActorBase(inputIndex, taskId, this->SelfId(), txId, std::move(sourceParams), std::move(readParams), computeActorId)
252260
, Token(token)
253261
, LocalRowDispatcherActorId(localRowDispatcherActorId)
254262
, Metrics(txId, taskId, counters)
255263
, HolderFactory(holderFactory)
264+
, MaxBufferSize(bufferSize)
256265
{
257266
MetadataFields.reserve(SourceParams.MetadataFieldsSize());
258267
TPqMetaExtractor fieldsExtractor;
@@ -375,23 +384,28 @@ i64 TDqPqRdReadActor::GetAsyncInputData(NKikimr::NMiniKQL::TUnboxedValueBatch& b
375384
buffer.clear();
376385
do {
377386
auto& readyBatch = ReadyBuffer.front();
378-
SRC_LOG_T("Return " << readyBatch.Data.size() << " items");
379387

380388
for (const auto& message : readyBatch.Data) {
381389
auto [item, size] = CreateItem(message);
382390
buffer.push_back(std::move(item));
383391
}
384392
usedSpace += readyBatch.UsedSpace;
385393
freeSpace -= readyBatch.UsedSpace;
386-
SRC_LOG_T("usedSpace " << usedSpace);
387-
SRC_LOG_T("freeSpace " << freeSpace);
388-
389394
TPartitionKey partitionKey{TString{}, readyBatch.PartitionId};
390395
PartitionToOffset[partitionKey] = readyBatch.NextOffset;
391396
SRC_LOG_T("NextOffset " << readyBatch.NextOffset);
392397
ReadyBuffer.pop();
393398
} while (freeSpace > 0 && !ReadyBuffer.empty());
394399

400+
ReadyBufferSizeBytes -= usedSpace;
401+
SRC_LOG_T("Return " << buffer.RowCount() << " rows, buffer size " << ReadyBufferSizeBytes << ", free space " << freeSpace << ", result size " << usedSpace);
402+
403+
if (!ReadyBuffer.empty()) {
404+
Send(ComputeActorId, new TEvNewAsyncInputDataArrived(InputIndex));
405+
}
406+
for (auto& [partitionId, sessionInfo] : Sessions) {
407+
TrySendGetNextBatch(sessionInfo);
408+
}
395409
ProcessState();
396410
return usedSpace;
397411
}
@@ -490,11 +504,8 @@ void TDqPqRdReadActor::Handle(NFq::TEvRowDispatcher::TEvNewDataArrived::TPtr& ev
490504
SRC_LOG_W("Wrong seq num ignore message, seqNo " << meta.GetSeqNo());
491505
return;
492506
}
493-
sessionInfo.NewDataArrived = true;
494-
Metrics.InFlyGetNextBatch->Inc();
495-
auto event = std::make_unique<NFq::TEvRowDispatcher::TEvGetNextBatch>();
496-
event->Record.SetPartitionId(partitionId);
497-
sessionInfo.EventsQueue.Send(event.release());
507+
sessionInfo.HasPendingData = true;
508+
TrySendGetNextBatch(sessionInfo);
498509
}
499510

500511
void TDqPqRdReadActor::Handle(const NYql::NDq::TEvRetryQueuePrivate::TEvRetry::TPtr& ev) {
@@ -578,7 +589,7 @@ void TDqPqRdReadActor::Handle(NFq::TEvRowDispatcher::TEvCoordinatorResult::TPtr&
578589
Sessions.emplace(
579590
std::piecewise_construct,
580591
std::forward_as_tuple(partitionId),
581-
std::forward_as_tuple(TxId, SelfId(), rowDispatcherActorId, partitionId));
592+
std::forward_as_tuple(TxId, SelfId(), rowDispatcherActorId, partitionId, partitionId));
582593
}
583594
}
584595
}
@@ -637,11 +648,12 @@ void TDqPqRdReadActor::Handle(NFq::TEvRowDispatcher::TEvMessageBatch::TPtr& ev)
637648
for (const auto& message : ev->Get()->Record.GetMessages()) {
638649
SRC_LOG_T("Json: " << message.GetJson());
639650
activeBatch.Data.emplace_back(message.GetJson());
640-
activeBatch.UsedSpace += message.GetJson().size();
641651
sessionInfo.NextOffset = message.GetOffset() + 1;
642652
bytes += message.GetJson().size();
643653
SRC_LOG_T("TEvMessageBatch NextOffset " << sessionInfo.NextOffset);
644654
}
655+
activeBatch.UsedSpace = bytes;
656+
ReadyBufferSizeBytes += bytes;
645657
IngressStats.Bytes += bytes;
646658
IngressStats.Chunks++;
647659
activeBatch.NextOffset = ev->Get()->Record.GetNextMessageOffset();
@@ -697,6 +709,20 @@ void TDqPqRdReadActor::Handle(TEvPrivate::TEvProcessState::TPtr&) {
697709
ProcessState();
698710
}
699711

712+
void TDqPqRdReadActor::TrySendGetNextBatch(SessionInfo& sessionInfo) {
713+
if (!sessionInfo.HasPendingData) {
714+
return;
715+
}
716+
if (ReadyBufferSizeBytes > MaxBufferSize) {
717+
return;
718+
}
719+
Metrics.InFlyGetNextBatch->Inc();
720+
auto event = std::make_unique<NFq::TEvRowDispatcher::TEvGetNextBatch>();
721+
sessionInfo.HasPendingData = false;
722+
event->Record.SetPartitionId(sessionInfo.PartitionId);
723+
sessionInfo.EventsQueue.Send(event.release());
724+
}
725+
700726
std::pair<IDqComputeActorAsyncInput*, NActors::IActor*> CreateDqPqRdReadActor(
701727
NPq::NProto::TDqPqTopicSource&& settings,
702728
ui64 inputIndex,
@@ -709,7 +735,7 @@ std::pair<IDqComputeActorAsyncInput*, NActors::IActor*> CreateDqPqRdReadActor(
709735
const NActors::TActorId& localRowDispatcherActorId,
710736
const NKikimr::NMiniKQL::THolderFactory& holderFactory,
711737
const ::NMonitoring::TDynamicCounterPtr& counters,
712-
i64 /*bufferSize*/) // TODO
738+
i64 bufferSize)
713739
{
714740
auto taskParamsIt = taskParams.find("pq");
715741
YQL_ENSURE(taskParamsIt != taskParams.end(), "Failed to get pq task params");
@@ -731,7 +757,8 @@ std::pair<IDqComputeActorAsyncInput*, NActors::IActor*> CreateDqPqRdReadActor(
731757
computeActorId,
732758
localRowDispatcherActorId,
733759
token,
734-
counters
760+
counters,
761+
bufferSize
735762
);
736763

737764
return {actor, actor};

ydb/library/yql/providers/pq/async_io/dq_pq_rd_read_actor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
namespace NYql::NDq {
2121
class TDqAsyncIoFactory;
2222

23-
const i64 PQRdReadDefaultFreeSpace = 16_MB;
23+
const i64 PQRdReadDefaultFreeSpace = 256_MB;
2424

2525
std::pair<IDqComputeActorAsyncInput*, NActors::IActor*> CreateDqPqRdReadActor(
2626
NPq::NProto::TDqPqTopicSource&& settings,

ydb/tests/fq/pq_async_io/ut/dq_pq_rd_read_actor_ut.cpp

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
#include <library/cpp/testing/unittest/registar.h>
66
#include <ydb/core/fq/libs/row_dispatcher/events/data_plane.h>
7+
#include <ydb/library/actors/testlib/test_runtime.h>
8+
#include <library/cpp/testing/unittest/gtest.h>
79

810
#include <thread>
911

@@ -51,7 +53,8 @@ struct TFixture : public TPqIoTestFixture {
5153
LocalRowDispatcherId,
5254
actor.GetHolderFactory(),
5355
MakeIntrusive<NMonitoring::TDynamicCounters>(),
54-
freeSpace);
56+
freeSpace
57+
);
5558

5659
actor.InitAsyncInput(dqSource, dqSourceAsActor);
5760
});
@@ -191,9 +194,8 @@ struct TFixture : public TPqIoTestFixture {
191194
});
192195
}
193196

194-
195-
void StartSession(NYql::NPq::NProto::TDqPqTopicSource& settings) {
196-
InitRdSource(settings);
197+
void StartSession(NYql::NPq::NProto::TDqPqTopicSource& settings, i64 freeSpace = 1_MB) {
198+
InitRdSource(settings, freeSpace);
197199
SourceRead<TString>(UVParser);
198200
ExpectCoordinatorChangesSubscribe();
199201

@@ -345,6 +347,30 @@ Y_UNIT_TEST_SUITE(TDqPqRdReadActorTests) {
345347
ProcessSomeJsons(3, {Json4}, RowDispatcher2);
346348
}
347349

350+
Y_UNIT_TEST_F(Backpressure, TFixture) {
351+
StartSession(Source1, 2_KB);
352+
353+
TString json(900, 'c');
354+
ProcessSomeJsons(0, {json}, RowDispatcher1);
355+
356+
MockNewDataArrived(RowDispatcher1);
357+
ExpectGetNextBatch(RowDispatcher1);
358+
MockMessageBatch(0, {json, json, json}, RowDispatcher1);
359+
360+
MockNewDataArrived(RowDispatcher1);
361+
ASSERT_THROW(
362+
CaSetup->Runtime->GrabEdgeEvent<NFq::TEvRowDispatcher::TEvGetNextBatch>(RowDispatcher1, TDuration::Seconds(0)),
363+
NActors::TEmptyEventQueueException);
364+
365+
auto result = SourceReadDataUntil<TString>(UVParser, 3);
366+
AssertDataWithWatermarks(result, {json, json, json}, {});
367+
ExpectGetNextBatch(RowDispatcher1);
368+
369+
MockMessageBatch(3, {Json1}, RowDispatcher1);
370+
result = SourceReadDataUntil<TString>(UVParser, 1);
371+
AssertDataWithWatermarks(result, {Json1}, {});
372+
}
373+
348374
Y_UNIT_TEST_F(RowDispatcherIsRestarted, TFixture) {
349375
StartSession(Source1);
350376
ProcessSomeJsons(0, {Json1, Json2}, RowDispatcher1);

ydb/tests/fq/pq_async_io/ya.make

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,7 @@ PEERDIR(
1414
YQL_LAST_ABI_VERSION()
1515

1616
END()
17+
18+
RECURSE_FOR_TESTS(
19+
ut
20+
)

0 commit comments

Comments
 (0)