Skip to content

Commit d6d5488

Browse files
authored
Reply error on database size exceeded (#12110)
1 parent 10fc4f2 commit d6d5488

File tree

2 files changed

+69
-57
lines changed

2 files changed

+69
-57
lines changed

ydb/core/persqueue/partition_write.cpp

+10-4
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ namespace NKikimr::NPQ {
2727

2828
static const ui32 BATCH_UNPACK_SIZE_BORDER = 500_KB;
2929
static const ui32 MAX_INLINE_SIZE = 1000;
30+
static const TDuration SubDomainQuotaWaitDurationMs = TDuration::Seconds(60);
3031

3132
static constexpr NPersQueue::NErrorCode::EErrorCode InactivePartitionErrorCode = NPersQueue::NErrorCode::WRITE_ERROR_PARTITION_INACTIVE;
3233

@@ -1483,8 +1484,12 @@ void TPartition::AddNewWriteBlob(std::pair<TKey, ui32>& res, TEvKeyValue::TEvReq
14831484

14841485
void TPartition::SetDeadlinesForWrites(const TActorContext& ctx) {
14851486
PQ_LOG_T("TPartition::SetDeadlinesForWrites.");
1486-
if (AppData(ctx)->PQConfig.GetQuotingConfig().GetQuotaWaitDurationMs() > 0 && QuotaDeadline == TInstant::Zero()) {
1487-
QuotaDeadline = ctx.Now() + TDuration::MilliSeconds(AppData(ctx)->PQConfig.GetQuotingConfig().GetQuotaWaitDurationMs());
1487+
auto quotaWaitDurationMs = TDuration::MilliSeconds(AppData(ctx)->PQConfig.GetQuotingConfig().GetQuotaWaitDurationMs());
1488+
if (SubDomainOutOfSpace) {
1489+
quotaWaitDurationMs = quotaWaitDurationMs ? std::min(quotaWaitDurationMs, SubDomainQuotaWaitDurationMs) : SubDomainQuotaWaitDurationMs;
1490+
}
1491+
if (quotaWaitDurationMs > TDuration::Zero() && QuotaDeadline == TInstant::Zero()) {
1492+
QuotaDeadline = ctx.Now() + quotaWaitDurationMs;
14881493

14891494
ctx.Schedule(QuotaDeadline, new TEvPQ::TEvQuotaDeadlineCheck());
14901495
}
@@ -1513,7 +1518,7 @@ void TPartition::FilterDeadlinedWrites(const TActorContext& ctx, TMessageQueue&
15131518
{
15141519
TMessageQueue newRequests;
15151520
for (auto& w : requests) {
1516-
if (!w.IsWrite() || w.GetWrite().Msg.IgnoreQuotaDeadline) {
1521+
if (!w.IsWrite() || (w.GetWrite().Msg.IgnoreQuotaDeadline && !SubDomainOutOfSpace)) {
15171522
newRequests.emplace_back(std::move(w));
15181523
continue;
15191524
}
@@ -1529,7 +1534,8 @@ void TPartition::FilterDeadlinedWrites(const TActorContext& ctx, TMessageQueue&
15291534
WriteInflightSize -= msg.Data.size();
15301535
}
15311536

1532-
ReplyError(ctx, w.GetCookie(), NPersQueue::NErrorCode::OVERLOAD, "quota exceeded");
1537+
TString errorMsg = SubDomainOutOfSpace ? "database size exceeded" : "quota exceeded";
1538+
ReplyError(ctx, w.GetCookie(), NPersQueue::NErrorCode::OVERLOAD, errorMsg);
15331539
}
15341540
requests = std::move(newRequests);
15351541
}

ydb/core/persqueue/ut/partition_ut.cpp

+59-53
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ class TPartitionFixture : public NUnitTest::TBaseFixture {
287287
void ShadowPartitionCountersTest(bool isFirstClass);
288288

289289
void TestWriteSubDomainOutOfSpace(TDuration quotaWaitDuration, bool ignoreQuotaDeadline);
290+
void TestWriteSubDomainOutOfSpace_DeadlineWork(bool ignoreQuotaDeadline);
290291
void WaitKeyValueRequest(TMaybe<ui64>& cookie);
291292

292293
void CmdChangeOwner(ui64 cookie, const TString& sourceId, TDuration duration, TString& ownerCookie);
@@ -1206,6 +1207,62 @@ void TPartitionFixture::EmulateKVTablet()
12061207
Cerr << "Send disk status response with cookie: " << cookie.GetOrElse(0) << Endl;
12071208
}
12081209

1210+
void TPartitionFixture::TestWriteSubDomainOutOfSpace_DeadlineWork(bool ignoreQuotaDeadline)
1211+
{
1212+
Ctx->Runtime->GetAppData().FeatureFlags.SetEnableTopicDiskSubDomainQuota(true);
1213+
Ctx->Runtime->GetAppData().PQConfig.MutableQuotingConfig()->SetQuotaWaitDurationMs(300);
1214+
CreatePartition({
1215+
.Partition=TPartitionId{1},
1216+
.Begin=0, .End=0,
1217+
//
1218+
// partition configuration
1219+
//
1220+
.Config={.Version=1, .Consumers={{.Consumer="client-1", .Offset=3}}}
1221+
},
1222+
//
1223+
// tablet configuration
1224+
//
1225+
{.Version=2, .Consumers={{.Consumer="client-1"}}});
1226+
TMaybe<ui64> kvCookie;
1227+
1228+
SendSubDomainStatus(true);
1229+
1230+
ui64 cookie = 1;
1231+
ui64 messageNo = 0;
1232+
TString ownerCookie;
1233+
1234+
CmdChangeOwner(cookie, "owner1", TDuration::Seconds(1), ownerCookie);
1235+
1236+
TAutoPtr<IEventHandle> handle;
1237+
std::function<bool(const TEvPQ::TEvError&)> truth = [&](const TEvPQ::TEvError& e) {
1238+
return cookie == e.Cookie;
1239+
};
1240+
1241+
TString data = "data for write";
1242+
1243+
// First message will be processed because used storage 0 and limit 0. That is, the limit is not exceeded.
1244+
SendWrite(++cookie, messageNo, ownerCookie, (messageNo + 1) * 100, data, ignoreQuotaDeadline);
1245+
messageNo++;
1246+
1247+
WaitKeyValueRequest(kvCookie); // the partition saves the TEvPQ::TEvWrite event
1248+
SendDiskStatusResponse(&kvCookie);
1249+
1250+
{
1251+
auto event = Ctx->Runtime->GrabEdgeEvent<TEvPQ::TEvProxyResponse>(TDuration::Seconds(1));
1252+
UNIT_ASSERT(event != nullptr);
1253+
}
1254+
1255+
// Second message will not be processed because the limit is exceeded.
1256+
SendWrite(++cookie, messageNo, ownerCookie, (messageNo + 1) * 100, data, ignoreQuotaDeadline);
1257+
messageNo++;
1258+
1259+
{
1260+
auto event = Ctx->Runtime->GrabEdgeEventIf<TEvPQ::TEvError>(handle, truth, TDuration::Seconds(1));
1261+
UNIT_ASSERT(event != nullptr);
1262+
UNIT_ASSERT_EQUAL(NPersQueue::NErrorCode::OVERLOAD, event->ErrorCode);
1263+
}
1264+
}
1265+
12091266
void TPartitionFixture::TestWriteSubDomainOutOfSpace(TDuration quotaWaitDuration, bool ignoreQuotaDeadline)
12101267
{
12111268
Ctx->Runtime->GetAppData().FeatureFlags.SetEnableTopicDiskSubDomainQuota(true);
@@ -2323,58 +2380,7 @@ Y_UNIT_TEST_F(ReserveSubDomainOutOfSpace, TPartitionFixture)
23232380

23242381
Y_UNIT_TEST_F(WriteSubDomainOutOfSpace, TPartitionFixture)
23252382
{
2326-
Ctx->Runtime->GetAppData().FeatureFlags.SetEnableTopicDiskSubDomainQuota(true);
2327-
Ctx->Runtime->GetAppData().PQConfig.MutableQuotingConfig()->SetQuotaWaitDurationMs(300);
2328-
CreatePartition({
2329-
.Partition=TPartitionId{1},
2330-
.Begin=0, .End=0,
2331-
//
2332-
// partition configuration
2333-
//
2334-
.Config={.Version=1, .Consumers={{.Consumer="client-1", .Offset=3}}}
2335-
},
2336-
//
2337-
// tablet configuration
2338-
//
2339-
{.Version=2, .Consumers={{.Consumer="client-1"}}});
2340-
TMaybe<ui64> kvCookie;
2341-
2342-
SendSubDomainStatus(true);
2343-
2344-
ui64 cookie = 1;
2345-
ui64 messageNo = 0;
2346-
TString ownerCookie;
2347-
2348-
CmdChangeOwner(cookie, "owner1", TDuration::Seconds(1), ownerCookie);
2349-
2350-
TAutoPtr<IEventHandle> handle;
2351-
std::function<bool(const TEvPQ::TEvError&)> truth = [&](const TEvPQ::TEvError& e) {
2352-
return cookie == e.Cookie;
2353-
};
2354-
2355-
TString data = "data for write";
2356-
2357-
// First message will be processed because used storage 0 and limit 0. That is, the limit is not exceeded.
2358-
SendWrite(++cookie, messageNo, ownerCookie, (messageNo + 1) * 100, data);
2359-
messageNo++;
2360-
2361-
WaitKeyValueRequest(kvCookie); // the partition saves the TEvPQ::TEvWrite event
2362-
SendDiskStatusResponse(&kvCookie);
2363-
2364-
{
2365-
auto event = Ctx->Runtime->GrabEdgeEvent<TEvPQ::TEvProxyResponse>(TDuration::Seconds(1));
2366-
UNIT_ASSERT(event != nullptr);
2367-
}
2368-
2369-
// Second message will not be processed because the limit is exceeded.
2370-
SendWrite(++cookie, messageNo, ownerCookie, (messageNo + 1) * 100, data);
2371-
messageNo++;
2372-
2373-
{
2374-
auto event = Ctx->Runtime->GrabEdgeEventIf<TEvPQ::TEvError>(handle, truth, TDuration::Seconds(1));
2375-
UNIT_ASSERT(event != nullptr);
2376-
UNIT_ASSERT_EQUAL(NPersQueue::NErrorCode::OVERLOAD, event->ErrorCode);
2377-
}
2383+
TestWriteSubDomainOutOfSpace_DeadlineWork(false);
23782384
}
23792385

23802386
Y_UNIT_TEST_F(WriteSubDomainOutOfSpace_DisableExpiration, TPartitionFixture)
@@ -2384,7 +2390,7 @@ Y_UNIT_TEST_F(WriteSubDomainOutOfSpace_DisableExpiration, TPartitionFixture)
23842390

23852391
Y_UNIT_TEST_F(WriteSubDomainOutOfSpace_IgnoreQuotaDeadline, TPartitionFixture)
23862392
{
2387-
TestWriteSubDomainOutOfSpace(TDuration::MilliSeconds(300), true);
2393+
TestWriteSubDomainOutOfSpace_DeadlineWork(true);
23882394
}
23892395

23902396
Y_UNIT_TEST_F(GetPartitionWriteInfoSuccess, TPartitionFixture) {

0 commit comments

Comments
 (0)