This is an automated email from the ASF dual-hosted git repository.

yashmayya pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new 1f6b882841 Add withTableProperties to Get Tenant Table API (#16202)
1f6b882841 is described below

commit 1f6b8828411297c818cf0ba72dfa98c05a894b2d
Author: Jhow <[email protected]>
AuthorDate: Thu Jul 10 20:17:22 2025 -0700

    Add withTableProperties to Get Tenant Table API (#16202)
---
 .../api/resources/PinotTenantRestletResource.java  |  38 ++++++--
 .../tenant/TenantTableWithProperties.java          | 103 +++++++++++++++++++++
 2 files changed, 134 insertions(+), 7 deletions(-)

diff --git 
a/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotTenantRestletResource.java
 
b/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotTenantRestletResource.java
index 19b9de65fc..94a1b125c1 100644
--- 
a/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotTenantRestletResource.java
+++ 
b/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotTenantRestletResource.java
@@ -53,6 +53,7 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
+import org.apache.helix.model.IdealState;
 import org.apache.helix.model.InstanceConfig;
 import org.apache.pinot.common.assignment.InstancePartitions;
 import org.apache.pinot.common.assignment.InstancePartitionsUtils;
@@ -70,6 +71,8 @@ import 
org.apache.pinot.controller.helix.core.rebalance.tenant.TenantRebalanceCo
 import 
org.apache.pinot.controller.helix.core.rebalance.tenant.TenantRebalanceProgressStats;
 import 
org.apache.pinot.controller.helix.core.rebalance.tenant.TenantRebalanceResult;
 import 
org.apache.pinot.controller.helix.core.rebalance.tenant.TenantRebalancer;
+import 
org.apache.pinot.controller.helix.core.rebalance.tenant.TenantTableWithProperties;
+import org.apache.pinot.controller.util.TableSizeReader;
 import org.apache.pinot.core.auth.Actions;
 import org.apache.pinot.core.auth.Authorize;
 import org.apache.pinot.core.auth.TargetType;
@@ -126,6 +129,7 @@ public class PinotTenantRestletResource {
   private static final Logger LOGGER = 
LoggerFactory.getLogger(PinotTenantRestletResource.class);
   private static final String TENANT_NAME = "tenantName";
   private static final String TABLES = "tables";
+  public static final String TABLES_WITH_PROPERTIES = "tablesWithProperties";
 
   @Inject
   PinotHelixResourceManager _pinotHelixResourceManager;
@@ -136,6 +140,9 @@ public class PinotTenantRestletResource {
   @Inject
   TenantRebalancer _tenantRebalancer;
 
+  @Inject
+  TableSizeReader _tableSizeReader;
+
   @POST
   @Path("/tenants")
   @Authorize(targetType = TargetType.CLUSTER, action = 
Actions.Cluster.CREATE_TENANT)
@@ -295,9 +302,11 @@ public class PinotTenantRestletResource {
       @ApiParam(value = "Tenant name", required = true) 
@PathParam("tenantName") String tenantName,
       @ApiParam(value = "Tenant type (server|broker)",
           required = false, allowableValues = "BROKER, SERVER", defaultValue = 
"SERVER")
-      @QueryParam("type") String tenantType, @Context HttpHeaders headers) {
+      @QueryParam("type") String tenantType,
+      @QueryParam("withTableProperties") @DefaultValue("false") boolean 
withTableProperties,
+      @Context HttpHeaders headers) {
     if (tenantType == null || tenantType.isEmpty() || 
tenantType.equalsIgnoreCase("server")) {
-      return getTablesServedFromServerTenant(tenantName, 
headers.getHeaderString(DATABASE));
+      return getTablesServedFromServerTenant(tenantName, 
headers.getHeaderString(DATABASE), withTableProperties);
     } else if (tenantType.equalsIgnoreCase("broker")) {
       return getTablesServedFromBrokerTenant(tenantName, 
headers.getHeaderString(DATABASE));
     } else {
@@ -386,23 +395,38 @@ public class PinotTenantRestletResource {
     }
   }
 
-  private String getTablesServedFromServerTenant(String tenantName, @Nullable 
String database) {
+  private String getTablesServedFromServerTenant(String tenantName, @Nullable 
String database,
+      boolean withTableProperties) {
     Set<String> tables = new HashSet<>();
+    Set<TenantTableWithProperties> tablePropertiesSet = withTableProperties ? 
new HashSet<>() : null;
     ObjectNode resourceGetRet = JsonUtils.newObjectNode();
 
-    for (String table : _pinotHelixResourceManager.getAllTables(database)) {
-      TableConfig tableConfig = 
_pinotHelixResourceManager.getTableConfig(table);
+    for (String tableNameWithType : 
_pinotHelixResourceManager.getAllTables(database)) {
+      TableConfig tableConfig = 
_pinotHelixResourceManager.getTableConfig(tableNameWithType);
       if (tableConfig == null) {
-        LOGGER.error("Unable to retrieve table config for table: {}", table);
+        LOGGER.error("Unable to retrieve table config for table: {}", 
tableNameWithType);
         continue;
       }
       Set<String> relevantTags = TableConfigUtils.getRelevantTags(tableConfig);
       if (relevantTags.contains(TagNameUtils.getServerTagForTenant(tenantName, 
tableConfig.getTableType()))) {
-        tables.add(table);
+        tables.add(tableNameWithType);
+        if (withTableProperties) {
+          IdealState idealState = 
_pinotHelixResourceManager.getTableIdealState(tableNameWithType);
+          if (idealState == null) {
+            LOGGER.error("Unable to retrieve ideal state for table: {}", 
tableNameWithType);
+            continue;
+          }
+          TenantTableWithProperties tableWithProperties = new 
TenantTableWithProperties(tableConfig,
+              idealState.getRecord().getMapFields(), _tableSizeReader);
+          tablePropertiesSet.add(tableWithProperties);
+        }
       }
     }
 
     resourceGetRet.set(TABLES, JsonUtils.objectToJsonNode(tables));
+    if (withTableProperties) {
+      resourceGetRet.set(TABLES_WITH_PROPERTIES, 
JsonUtils.objectToJsonNode(tablePropertiesSet));
+    }
     return resourceGetRet.toString();
   }
 
diff --git 
a/pinot-controller/src/main/java/org/apache/pinot/controller/helix/core/rebalance/tenant/TenantTableWithProperties.java
 
b/pinot-controller/src/main/java/org/apache/pinot/controller/helix/core/rebalance/tenant/TenantTableWithProperties.java
new file mode 100644
index 0000000000..fd670d76a5
--- /dev/null
+++ 
b/pinot-controller/src/main/java/org/apache/pinot/controller/helix/core/rebalance/tenant/TenantTableWithProperties.java
@@ -0,0 +1,103 @@
+/**
+ * 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.pinot.controller.helix.core.rebalance.tenant;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Map;
+import org.apache.pinot.common.exception.InvalidConfigException;
+import org.apache.pinot.controller.util.TableSizeReader;
+import org.apache.pinot.spi.config.table.TableConfig;
+import org.apache.pinot.spi.config.table.TableType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Class to hold table properties when listing tables for a tenant during 
rebalancing.
+ * This class contains pre-defined properties of a table that are relevant
+ * for making include/exclude decisions during tenant rebalance operations.
+ * The properties focus on factors that could impact rebalance performance and 
stability.
+ */
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class TenantTableWithProperties {
+  // Basic table identification
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(TenantTableWithProperties.class);
+
+  @JsonProperty("tableNameWithType")
+  private final String _tableNameWithType;
+  @JsonProperty("tableType")
+  private final TableType _tableType;
+  @JsonProperty("isDimTable")
+  private final boolean _isDimTable;
+  @JsonProperty("replication")
+  private final int _replication;
+  @JsonProperty("totalSegments")
+  private final int _totalSegments;
+  @JsonProperty("estimatedTableSizeInBytes")
+  private final long _estimatedTableSizeInBytes;
+  @JsonProperty("isUpsertEnabled")
+  private final boolean _isUpsertEnabled;
+  @JsonProperty("isDedupEnabled")
+  private final boolean _isDedupEnabled;
+
+  private static final int TABLE_SIZE_READER_TIMEOUT_MS = 10000; // 10 seconds
+
+  @JsonCreator
+  public TenantTableWithProperties(
+      @JsonProperty("tableNameWithType") String tableNameWithType,
+      @JsonProperty("tableType") TableType tableType,
+      @JsonProperty("isDimTable") boolean isDimTable,
+      @JsonProperty("replication") int replication,
+      @JsonProperty("totalSegments") int totalSegments,
+      @JsonProperty("estimatedTableSizeInBytes") long 
estimatedTableSizeInBytes,
+      @JsonProperty("isUpsertEnabled") boolean isUpsertEnabled,
+      @JsonProperty("isDedupEnabled") boolean isDedupEnabled) {
+    _tableNameWithType = tableNameWithType;
+    _tableType = tableType;
+    _isDimTable = isDimTable;
+    _replication = replication;
+    _totalSegments = totalSegments;
+    _estimatedTableSizeInBytes = estimatedTableSizeInBytes;
+    _isUpsertEnabled = isUpsertEnabled;
+    _isDedupEnabled = isDedupEnabled;
+  }
+
+  public TenantTableWithProperties(TableConfig tableConfig, Map<String, 
Map<String, String>> idealStateInstanceStateMap,
+      TableSizeReader tableSizeReader) {
+    long estimatedTableSizeInBytes;
+    _tableNameWithType = tableConfig.getTableName();
+    _tableType = tableConfig.getTableType();
+    _isDimTable = tableConfig.isDimTable();
+    _replication = tableConfig.getReplication();
+    _totalSegments = idealStateInstanceStateMap.size();
+    try {
+      TableSizeReader.TableSubTypeSizeDetails sizeDetails =
+          tableSizeReader.getTableSubtypeSize(_tableNameWithType, 
TABLE_SIZE_READER_TIMEOUT_MS, false);
+      estimatedTableSizeInBytes = sizeDetails._estimatedSizeInBytes;
+    } catch (InvalidConfigException e) {
+      LOGGER.warn("Failed to read table size for table: {}", 
_tableNameWithType, e);
+      estimatedTableSizeInBytes = -1; // Indicate failure to read size
+    }
+    _estimatedTableSizeInBytes = estimatedTableSizeInBytes;
+    _isUpsertEnabled = tableConfig.isUpsertEnabled();
+    _isDedupEnabled = tableConfig.isDedupEnabled();
+  }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to