This is an automated email from the ASF dual-hosted git repository. czy006 pushed a commit to branch 0.9.x in repository https://gitbox.apache.org/repos/asf/amoro.git
commit 43a6c799b21dba54f91e56b39c86442812e0551f Author: hutiefang76 <[email protected]> AuthorDate: Sat Oct 3 06:34:54 2026 +0800 [AMORO-4400][AMS]Keep dashboard optimizing quota positive (#4403) [AMS] Keep dashboard optimizing quota positive (cherry picked from commit 488b2e34c48d0160af4638478958406d29416870) --- .../server/dashboard/utils/OptimizingUtil.java | 6 +- .../dashboard/utils/TestTableOptimizingInfo.java | 104 +++++++++++++++++++++ 2 files changed, 109 insertions(+), 1 deletion(-) diff --git a/amoro-ams/src/main/java/org/apache/amoro/server/dashboard/utils/OptimizingUtil.java b/amoro-ams/src/main/java/org/apache/amoro/server/dashboard/utils/OptimizingUtil.java index 17e91f4c8..b597f74bd 100644 --- a/amoro-ams/src/main/java/org/apache/amoro/server/dashboard/utils/OptimizingUtil.java +++ b/amoro-ams/src/main/java/org/apache/amoro/server/dashboard/utils/OptimizingUtil.java @@ -62,8 +62,12 @@ public class OptimizingUtil { TableConfigurations.parseTableConfig(tableRuntimeMeta.getTableConfig()); OptimizingConfig optimizingConfig = tableConfig.getOptimizingConfig(); double targetQuota = optimizingConfig.getTargetQuota(); + // A non-positive target quota must not make the occupation ratio NaN; clamp to 1 like + // DefaultTableRuntime.calculateQuotaOccupy does. tableOptimizeInfo.setQuota( - targetQuota > 1 ? (int) targetQuota : (int) Math.ceil(targetQuota * threadCount)); + targetQuota > 1 + ? (int) targetQuota + : (int) Math.max(1, Math.ceil(targetQuota * threadCount))); long endTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis() - AmoroServiceConstants.QUOTA_LOOK_BACK_TIME; diff --git a/amoro-ams/src/test/java/org/apache/amoro/server/dashboard/utils/TestTableOptimizingInfo.java b/amoro-ams/src/test/java/org/apache/amoro/server/dashboard/utils/TestTableOptimizingInfo.java new file mode 100644 index 000000000..94bb18b1a --- /dev/null +++ b/amoro-ams/src/test/java/org/apache/amoro/server/dashboard/utils/TestTableOptimizingInfo.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.amoro.server.dashboard.utils; + +import org.apache.amoro.ServerTableIdentifier; +import org.apache.amoro.TableFormat; +import org.apache.amoro.server.AmoroServiceConstants; +import org.apache.amoro.server.dashboard.model.TableOptimizingInfo; +import org.apache.amoro.server.optimizing.OptimizingStatus; +import org.apache.amoro.server.optimizing.OptimizingTaskMeta; +import org.apache.amoro.server.optimizing.TaskRuntime; +import org.apache.amoro.server.persistence.TableRuntimeMeta; +import org.apache.amoro.table.TableProperties; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** Tests for {@link OptimizingUtil#buildTableOptimizeInfo}. */ +public class TestTableOptimizingInfo { + + private static final int THREAD_COUNT = 4; + + @Test + public void testZeroQuota() { + TableOptimizingInfo tableOptimizingInfo = + buildOptimizingInfo("0", OptimizingStatus.PENDING, null); + Assertions.assertEquals(1.0, tableOptimizingInfo.getQuota()); + Assertions.assertEquals(0.0, tableOptimizingInfo.getQuotaOccupation()); + } + + @Test + public void testNegativeQuota() { + TableOptimizingInfo tableOptimizingInfo = + buildOptimizingInfo("-0.5", OptimizingStatus.IDLE, null); + Assertions.assertEquals(1.0, tableOptimizingInfo.getQuota()); + Assertions.assertTrue(Double.isFinite(tableOptimizingInfo.getQuotaOccupation())); + } + + @Test + public void testFractionalQuota() { + TableOptimizingInfo tableOptimizingInfo = + buildOptimizingInfo("0.5", OptimizingStatus.PENDING, null); + Assertions.assertEquals(2.0, tableOptimizingInfo.getQuota()); + } + + @Test + public void testQuotaGreaterThanOne() { + TableOptimizingInfo tableOptimizingInfo = + buildOptimizingInfo("3", OptimizingStatus.PENDING, null); + Assertions.assertEquals(3.0, tableOptimizingInfo.getQuota()); + } + + @Test + public void testQuotaOccupationWithRunningTask() { + long taskStartTime = + System.currentTimeMillis() - AmoroServiceConstants.QUOTA_LOOK_BACK_TIME / 2; + OptimizingTaskMeta taskMeta = new OptimizingTaskMeta(); + taskMeta.setStatus(TaskRuntime.Status.ACKED); + taskMeta.setStartTime(taskStartTime); + taskMeta.setCostTime(AmoroServiceConstants.QUOTA_LOOK_BACK_TIME / 2); + + TableOptimizingInfo tableOptimizingInfo = + buildOptimizingInfo("0.25", OptimizingStatus.PENDING, Collections.singletonList(taskMeta)); + Assertions.assertEquals(1.0, tableOptimizingInfo.getQuota()); + Assertions.assertEquals(0.5, tableOptimizingInfo.getQuotaOccupation()); + } + + private TableOptimizingInfo buildOptimizingInfo( + String quota, OptimizingStatus status, List<OptimizingTaskMeta> processTasks) { + Map<String, String> tableConfig = new HashMap<>(); + tableConfig.put(TableProperties.SELF_OPTIMIZING_QUOTA, quota); + TableRuntimeMeta tableRuntimeMeta = new TableRuntimeMeta(); + tableRuntimeMeta.setTableId(1L); + tableRuntimeMeta.setGroupName("test"); + tableRuntimeMeta.setStatusCode(status.getCode()); + tableRuntimeMeta.setTableConfig(tableConfig); + return OptimizingUtil.buildTableOptimizeInfo( + ServerTableIdentifier.of(1L, "catalog", "database", "table", TableFormat.ICEBERG), + tableRuntimeMeta, + processTasks, + null, + THREAD_COUNT); + } +}
