Skip to content

Fix usage of storage until alter the topic #21515

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -792,11 +792,13 @@ class TAlterPQ: public TSubOperation {
return result;
}

const auto& stats = topic->Stats;
const PQGroupReserve reserve(newTabletConfig, alterData->ActivePartitionCount);
const PQGroupReserve reserveForCheckLimit(newTabletConfig, alterData->ActivePartitionCount + involvedPartitions.size());
const PQGroupReserve oldReserve(tabletConfig, topic->ActivePartitionCount);
const PQGroupReserve oldReserveForCheckLimit(tabletConfig, topic->ActivePartitionCount, stats.DataSize);

const ui64 storageToReserve = reserveForCheckLimit.Storage > oldReserve.Storage ? reserveForCheckLimit.Storage - oldReserve.Storage : 0;
const ui64 storageToReserve = reserveForCheckLimit.Storage > oldReserveForCheckLimit.Storage ? reserveForCheckLimit.Storage - oldReserveForCheckLimit.Storage : 0;

{
TPath::TChecker checks = path.Check();
Expand Down
5 changes: 3 additions & 2 deletions ydb/core/tx/schemeshard/schemeshard_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
namespace NKikimr {
namespace NSchemeShard {

PQGroupReserve::PQGroupReserve(const ::NKikimrPQ::TPQTabletConfig& tabletConfig, ui64 partitions) {
Storage = partitions * NPQ::TopicPartitionReserveSize(tabletConfig);
PQGroupReserve::PQGroupReserve(const ::NKikimrPQ::TPQTabletConfig& tabletConfig, ui64 partitions, ui64 currentStorageUsage) {
Storage = NKikimrPQ::TPQTabletConfig::METERING_MODE_REQUEST_UNITS == tabletConfig.GetMeteringMode()
? currentStorageUsage : partitions * NPQ::TopicPartitionReserveSize(tabletConfig);
Throughput = partitions * NPQ::TopicPartitionReserveThroughput(tabletConfig);
}

Expand Down
2 changes: 1 addition & 1 deletion ydb/core/tx/schemeshard/schemeshard_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ inline NKikimrSchemeOp::TModifyScheme TransactionTemplate(const TString& working

class PQGroupReserve {
public:
PQGroupReserve(const ::NKikimrPQ::TPQTabletConfig& tabletConfig, ui64 partitions);
PQGroupReserve(const ::NKikimrPQ::TPQTabletConfig& tabletConfig, ui64 partitions, ui64 currentStorageUsage = 0);

ui64 Storage;
ui64 Throughput;
Expand Down
82 changes: 82 additions & 0 deletions ydb/core/tx/schemeshard/ut_base/ut_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11595,6 +11595,88 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) {
env.TestWaitNotification(runtime, txId);
}

Y_UNIT_TEST(AlterTopicOverDiskSpaceQuotas) {
TTestBasicRuntime runtime;

TTestEnvOptions opts;
opts.DisableStatsBatching(true);
opts.EnablePersistentPartitionStats(true);
opts.EnableTopicDiskSubDomainQuota(true);

TTestEnv env(runtime, opts);

ui64 txId = 100;

// Subdomain with a 1-byte data size quota
TestCreateSubDomain(runtime, ++txId, "/MyRoot", R"(
Name: "USER_1"
PlanResolution: 50
Coordinators: 1
Mediators: 1
TimeCastBucketsPerMediator: 2
StoragePools {
Name: "name_USER_0_kind_hdd-1"
Kind: "hdd-1"
}
StoragePools {
Name: "name_USER_0_kind_hdd-2"
Kind: "hdd-2"
}
DatabaseQuotas {
data_size_hard_quota: 100
}
)");
env.TestWaitNotification(runtime, txId);

TestCreatePQGroup(runtime, ++txId, "/MyRoot/USER_1", R"(
Name: "Topic1"
TotalGroupCount: 1
PartitionPerTablet: 1
PQTabletConfig {
PartitionConfig {
LifetimeSeconds: 1
WriteSpeedInBytesPerSecond : 100
}
MeteringMode: METERING_MODE_REQUEST_UNITS
}
)");
env.TestWaitNotification(runtime, txId);

ui64 topicId = DescribePath(runtime, "/MyRoot/USER_1/Topic1").GetPathDescription().GetSelf().GetPathId();

ui64 generation = 1;
ui64 round = 1;

// Now topic use 50 bytes of the storage
SendTEvPeriodicTopicStats(runtime, topicId, generation, ++round, 50, 0);

// Now we reserve 150 bytes but limit 100 bytes
TestAlterPQGroup(runtime, ++txId, "/MyRoot/USER_1", R"(
Name: "Topic1"
PQTabletConfig {
PartitionConfig {
LifetimeSeconds: 1
WriteSpeedInBytesPerSecond : 150
}
MeteringMode: METERING_MODE_RESERVED_CAPACITY
}
)", {{TEvSchemeShard::EStatus::StatusResourceExhausted, "database size limit exceeded"}});
env.TestWaitNotification(runtime, txId);

// Now we reserve 100 bytes and limit 100 bytes
TestAlterPQGroup(runtime, ++txId, "/MyRoot/USER_1", R"(
Name: "Topic1"
PQTabletConfig {
PartitionConfig {
LifetimeSeconds: 1
WriteSpeedInBytesPerSecond : 100
}
MeteringMode: METERING_MODE_RESERVED_CAPACITY
}
)");
env.TestWaitNotification(runtime, txId);
}

Y_UNIT_TEST(CreateSystemColumn) {
TTestBasicRuntime runtime;
TTestEnv env(runtime);
Expand Down
Loading