Jackie-Jiang commented on code in PR #19838:
URL: https://github.com/apache/pinot/pull/19838#discussion_r4364754125


##########
pinot-broker/src/main/java/org/apache/pinot/broker/queryquota/HelixExternalViewBasedQueryQuotaManager.java:
##########
@@ -91,6 +93,7 @@ public class HelixExternalViewBasedQueryQuotaManager 
implements ClusterChangeHan
   private final String _instanceId;
   private final AtomicInteger _lastKnownBrokerResourceVersion = new 
AtomicInteger(-1);
   private final Map<String, QueryQuotaEntity> _rateLimiterMap = new 
ConcurrentHashMap<>();
+  private final Map<String, QuotaEnforcementMode> _enforcementModeOverrideMap 
= new ConcurrentHashMap<>();

Review Comment:
   Optional simplification: consider storing the effective enforcement mode on 
`QueryQuotaEntity`, defaulting to `ENFORCED` and using a `volatile` field for 
visibility to concurrent readers. This would remove the parallel 
`_enforcementModeOverrideMap`, its update helper and test-only size accessor, 
and duplicated cleanup at each table removal/reset path. The limiter and its 
enforcement policy would then share one lifecycle.



##########
pinot-broker/src/main/java/org/apache/pinot/broker/requesthandler/BaseBrokerRequestHandler.java:
##########
@@ -311,17 +313,44 @@ protected boolean hasExceededQPSQuota(@Nullable String 
database, Set<String> tab
       return true;
     }
     for (String tableName : tableNames) {
-      if (!_queryQuotaManager.acquire(tableName)) {
+      if (isTableQpsQuotaBreachEnforced(tableName)) {
         LOGGER.warn("Request {}: query exceeds quota for table: {}", 
requestContext.getRequestId(), tableName);
         requestContext.setErrorCode(QueryErrorCode.TOO_MANY_REQUESTS);
-        String rawTableName = TableNameBuilder.extractRawTableName(tableName);
-        _brokerMetrics.addMeteredTableValue(rawTableName, 
BrokerMeter.QUERY_QUOTA_EXCEEDED, 1);
         return true;
       }
     }
     return false;
   }
 
+  ///  Acquires the QPS quota of the given table (name with or without type 
suffix) and returns true only if the quota
+  ///  is breached and the table's enforcement mode requires rejecting the 
query.
+  protected boolean isTableQpsQuotaBreachEnforced(String tableName) {
+    return isQpsQuotaBreachEnforced(tableName, _queryQuotaManager::acquire);
+  }
+
+  ///  Same as [#isTableQpsQuotaBreachEnforced(String)] for a logical table.
+  protected boolean isLogicalTableQpsQuotaBreachEnforced(String 
logicalTableName) {
+    return isQpsQuotaBreachEnforced(logicalTableName, 
_queryQuotaManager::acquireLogicalTable);
+  }
+
+  private boolean isQpsQuotaBreachEnforced(String tableName, Predicate<String> 
acquire) {

Review Comment:
   Optional simplification: the two wrappers could call `acquire()` / 
`acquireLogicalTable()` directly and share only the breach handling, removing 
the `Predicate<String>` parameter and method-reference indirection. For example:
   
   ```java
   return !_queryQuotaManager.acquire(tableName) && 
shouldEnforceQuotaBreach(tableName);
   ```
   
   The shared helper would start with mode resolution. Short-circuiting 
preserves the current behavior of looking up the mode only after acquisition 
fails.



##########
pinot-controller/src/main/java/org/apache/pinot/controller/validation/RealtimeSegmentValidationManager.java:
##########
@@ -196,6 +197,16 @@ boolean shouldEnsureConsuming(String tableNameWithType) {
     // Perform storage quota checks.
     TableConfig tableConfig = 
_pinotHelixResourceManager.getTableConfig(tableNameWithType);
     boolean isQuotaExceeded = 
_storageQuotaChecker.isTableStorageQuotaExceeded(tableConfig);
+    QuotaEnforcementMode enforcementMode = 
_storageQuotaChecker.getEnforcementMode(tableConfig);
+    if (isQuotaExceeded && enforcementMode != QuotaEnforcementMode.ENFORCED) {
+      if (enforcementMode == QuotaEnforcementMode.SHADOW) {
+        // The breach meter is already emitted by StorageQuotaChecker
+        LOGGER.warn("Storage quota exceeded for table: {}, but enforcement 
mode is SHADOW, not pausing consumption",
+            tableNameWithType);
+      }
+      // DISABLED or SHADOW: don't treat the breach as exceeded for 
pause/resume purposes
+      isQuotaExceeded = false;

Review Comment:
   Optional simplification: keep `isQuotaExceeded` as the raw breach result and 
derive the enforcement decision separately:
   
   ```java
   boolean shouldPauseForQuota = isQuotaExceeded && enforcementMode == 
QuotaEnforcementMode.ENFORCED;
   ```
   
   Use `shouldPauseForQuota` for the pause-state comparison, transition and 
return, while retaining the SHADOW log. This avoids changing the meaning of 
`isQuotaExceeded` midway through the method and preserves breach metering in 
the checker.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to