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

yiguolei pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-4.1 by this push:
     new 56ca08ec03d branch-4.1: [feature](workload) Support remote scan bytes 
breaker in workload policy #64649 (#65064)
56ca08ec03d is described below

commit 56ca08ec03d34845232cd77beecfbd9c3ccbb5b9
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Thu Jul 2 08:24:29 2026 +0800

    branch-4.1: [feature](workload) Support remote scan bytes breaker in 
workload policy #64649 (#65064)
    
    Cherry-picked from #64649
    
    Co-authored-by: Wen Zhenghu <[email protected]>
---
 .../workload_management/workload_condition.cpp     |  15 ++-
 .../workload_management/workload_condition.h       |  33 ++++-
 .../workload_management/workload_sched_policy.cpp  |   6 +
 be/test/runtime/workload_sched_policy_test.cpp     |  34 ++++-
 .../workloadschedpolicy/WorkloadCondition.java     |   3 +
 ...kloadConditionBeScanBytesFromRemoteStorage.java |  60 +++++++++
 .../workloadschedpolicy/WorkloadMetricType.java    |   3 +-
 .../WorkloadSchedPolicyMgr.java                    |   7 +-
 .../WorkloadSchedPolicyMgrTest.java                |  46 +++++++
 gensrc/thrift/BackendService.thrift                |   4 +-
 .../test_workload_policy_remote_scan_bytes.groovy  | 143 +++++++++++++++++++++
 11 files changed, 347 insertions(+), 7 deletions(-)

diff --git a/be/src/runtime/workload_management/workload_condition.cpp 
b/be/src/runtime/workload_management/workload_condition.cpp
index 4c85a95ad1f..618168df690 100644
--- a/be/src/runtime/workload_management/workload_condition.cpp
+++ b/be/src/runtime/workload_management/workload_condition.cpp
@@ -56,6 +56,19 @@ bool WorkloadConditionScanBytes::eval(std::string str_val) {
     return WorkloadCompareUtils::compare_signed_integer(_op, scan_bytes_args, 
_scan_bytes);
 }
 
+// remote scan bytes
+WorkloadConditionScanBytesFromRemoteStorage::WorkloadConditionScanBytesFromRemoteStorage(
+        WorkloadCompareOperator op, std::string str_val) {
+    _op = op;
+    _scan_bytes_from_remote_storage = std::stol(str_val);
+}
+
+bool WorkloadConditionScanBytesFromRemoteStorage::eval(std::string str_val) {
+    int64_t scan_bytes_from_remote_storage_args = std::stol(str_val);
+    return WorkloadCompareUtils::compare_signed_integer(_op, 
scan_bytes_from_remote_storage_args,
+                                                        
_scan_bytes_from_remote_storage);
+}
+
 // query memory
 
WorkloadConditionQueryMemory::WorkloadConditionQueryMemory(WorkloadCompareOperator
 op,
                                                            std::string 
str_val) {
@@ -80,4 +93,4 @@ bool WorkloadConditionUsername::eval(std::string str_val) {
     return WorkloadCompareUtils::compare_string(_op, str_val, _username);
 }
 
-} // namespace doris
\ No newline at end of file
+} // namespace doris
diff --git a/be/src/runtime/workload_management/workload_condition.h 
b/be/src/runtime/workload_management/workload_condition.h
index 1a8c9e8dc8b..15ecc8d4b25 100644
--- a/be/src/runtime/workload_management/workload_condition.h
+++ b/be/src/runtime/workload_management/workload_condition.h
@@ -23,7 +23,15 @@
 
 namespace doris {
 
-enum WorkloadMetricType { QUERY_TIME, SCAN_ROWS, SCAN_BYTES, 
QUERY_MEMORY_BYTES, USERNAME };
+enum WorkloadMetricType {
+    QUERY_TIME,
+    SCAN_ROWS,
+    SCAN_BYTES,
+    // Extend the BE workload metric enum with remote scan bytes support.
+    SCAN_BYTES_FROM_REMOTE_STORAGE,
+    QUERY_MEMORY_BYTES,
+    USERNAME
+};
 
 class WorkloadCondition {
 public:
@@ -90,6 +98,25 @@ private:
     WorkloadCompareOperator _op;
 };
 
+class WorkloadConditionScanBytesFromRemoteStorage : public WorkloadCondition {
+public:
+    WorkloadConditionScanBytesFromRemoteStorage(WorkloadCompareOperator op, 
std::string str_val);
+    bool eval(std::string str_val) override;
+    WorkloadMetricType get_workload_metric_type() override {
+        return WorkloadMetricType::SCAN_BYTES_FROM_REMOTE_STORAGE;
+    }
+
+    std::string get_metric_string() override { return 
"scan_bytes_from_remote_storage"; }
+
+    std::string get_metric_value_string() override {
+        return std::to_string(_scan_bytes_from_remote_storage);
+    }
+
+private:
+    int64_t _scan_bytes_from_remote_storage;
+    WorkloadCompareOperator _op;
+};
+
 class WorkloadConditionQueryMemory : public WorkloadCondition {
 public:
     WorkloadConditionQueryMemory(WorkloadCompareOperator op, std::string 
str_val);
@@ -136,6 +163,8 @@ public:
             return std::make_unique<WorkloadConditionScanRows>(op, str_val);
         } else if (TWorkloadMetricType::type::BE_SCAN_BYTES == metric_name) {
             return std::make_unique<WorkloadConditionScanBytes>(op, str_val);
+        } else if 
(TWorkloadMetricType::type::BE_SCAN_BYTES_FROM_REMOTE_STORAGE == metric_name) {
+            return 
std::make_unique<WorkloadConditionScanBytesFromRemoteStorage>(op, str_val);
         } else if (TWorkloadMetricType::type::QUERY_BE_MEMORY_BYTES == 
metric_name) {
             return std::make_unique<WorkloadConditionQueryMemory>(op, str_val);
         } else if (TWorkloadMetricType::type::USERNAME == metric_name) {
@@ -146,4 +175,4 @@ public:
     }
 };
 
-} // namespace doris
\ No newline at end of file
+} // namespace doris
diff --git a/be/src/runtime/workload_management/workload_sched_policy.cpp 
b/be/src/runtime/workload_management/workload_sched_policy.cpp
index e439c873ad2..a3cbc003ac0 100644
--- a/be/src/runtime/workload_management/workload_sched_policy.cpp
+++ b/be/src/runtime/workload_management/workload_sched_policy.cpp
@@ -80,6 +80,12 @@ bool 
WorkloadSchedPolicy::is_match(WorkloadAction::RuntimeContext* action_runtim
             val = 
std::to_string(action_runtime_ctx->resource_ctx->io_context()->scan_bytes());
             break;
         }
+        // Evaluate the remote read breaker against the existing IO context 
remote scan counter.
+        case WorkloadMetricType::SCAN_BYTES_FROM_REMOTE_STORAGE: {
+            val = std::to_string(action_runtime_ctx->resource_ctx->io_context()
+                                         ->scan_bytes_from_remote_storage());
+            break;
+        }
         case WorkloadMetricType::SCAN_ROWS: {
             val = 
std::to_string(action_runtime_ctx->resource_ctx->io_context()->scan_rows());
             break;
diff --git a/be/test/runtime/workload_sched_policy_test.cpp 
b/be/test/runtime/workload_sched_policy_test.cpp
index 719ce0f04ad..311bf982685 100644
--- a/be/test/runtime/workload_sched_policy_test.cpp
+++ b/be/test/runtime/workload_sched_policy_test.cpp
@@ -198,7 +198,39 @@ TEST_F(WorkloadSchedPolicyTest, one_policy_one_condition) {
                 << ": " << 
action_runtime_ctx.resource_ctx->io_context()->scan_bytes();
     }
 
-    // 5 check query be memory bytes
+    // 5 check remote scan bytes
+    {
+        std::shared_ptr<WorkloadSchedPolicy> policy = 
std::make_shared<WorkloadSchedPolicy>();
+        std::vector<std::unique_ptr<WorkloadCondition>> cond_ptr_list;
+        cond_ptr_list.push_back(create_workload_condition(
+                TWorkloadMetricType::type::BE_SCAN_BYTES_FROM_REMOTE_STORAGE,
+                TCompareOperator::type::GREATER, "1000"));
+        std::vector<std::unique_ptr<WorkloadAction>> action_ptr_list;
+        
action_ptr_list.push_back(create_workload_action(TWorkloadActionType::type::CANCEL_QUERY));
+        std::set<int64_t> wg_id_set;
+        policy->init(0, "p1", 0, true, 0, wg_id_set, std::move(cond_ptr_list),
+                     std::move(action_ptr_list));
+
+        // Updating total scan bytes alone must not satisfy the remote read 
condition.
+        WorkloadAction::RuntimeContext action_runtime_ctx = 
create_runtime_context();
+        action_runtime_ctx.resource_ctx->io_context()->update_scan_bytes(1001);
+        EXPECT_FALSE(policy->is_match(&action_runtime_ctx))
+                << ": " << 
action_runtime_ctx.resource_ctx->io_context()->scan_bytes();
+
+        // Updating remote scan bytes below the threshold must still miss.
+        
action_runtime_ctx.resource_ctx->io_context()->update_scan_bytes_from_remote_storage(999);
+        EXPECT_FALSE(policy->is_match(&action_runtime_ctx))
+                << ": "
+                << 
action_runtime_ctx.resource_ctx->io_context()->scan_bytes_from_remote_storage();
+
+        // Only the remote scan bytes counter should drive this metric to a 
match.
+        
action_runtime_ctx.resource_ctx->io_context()->update_scan_bytes_from_remote_storage(2);
+        EXPECT_TRUE(policy->is_match(&action_runtime_ctx))
+                << ": "
+                << 
action_runtime_ctx.resource_ctx->io_context()->scan_bytes_from_remote_storage();
+    }
+
+    // 6 check query be memory bytes
     {
         std::shared_ptr<WorkloadSchedPolicy> policy = 
std::make_shared<WorkloadSchedPolicy>();
         std::vector<std::unique_ptr<WorkloadCondition>> cond_ptr_list;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/resource/workloadschedpolicy/WorkloadCondition.java
 
b/fe/fe-core/src/main/java/org/apache/doris/resource/workloadschedpolicy/WorkloadCondition.java
index c790a401308..01dfae955dc 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/resource/workloadschedpolicy/WorkloadCondition.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/resource/workloadschedpolicy/WorkloadCondition.java
@@ -37,6 +37,9 @@ public interface WorkloadCondition {
             return WorkloadConditionBeScanRows.createWorkloadCondition(cm.op, 
cm.value);
         } else if (WorkloadMetricType.BE_SCAN_BYTES.equals(cm.metricName)) {
             return WorkloadConditionBeScanBytes.createWorkloadCondition(cm.op, 
cm.value);
+        // Register the remote scan bytes condition so FE can parse and 
persist the new metric.
+        } else if 
(WorkloadMetricType.BE_SCAN_BYTES_FROM_REMOTE_STORAGE.equals(cm.metricName)) {
+            return 
WorkloadConditionBeScanBytesFromRemoteStorage.createWorkloadCondition(cm.op, 
cm.value);
         } else if 
(WorkloadMetricType.QUERY_BE_MEMORY_BYTES.equals(cm.metricName)) {
             return 
WorkloadConditionQueryBeMemory.createWorkloadCondition(cm.op, cm.value);
         }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/resource/workloadschedpolicy/WorkloadConditionBeScanBytesFromRemoteStorage.java
 
b/fe/fe-core/src/main/java/org/apache/doris/resource/workloadschedpolicy/WorkloadConditionBeScanBytesFromRemoteStorage.java
new file mode 100644
index 00000000000..3b4e004971e
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/resource/workloadschedpolicy/WorkloadConditionBeScanBytesFromRemoteStorage.java
@@ -0,0 +1,60 @@
+// 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.doris.resource.workloadschedpolicy;
+
+import org.apache.doris.common.UserException;
+
+/**
+ * Workload condition for matching query remote scan bytes collected on BE.
+ */
+public class WorkloadConditionBeScanBytesFromRemoteStorage implements 
WorkloadCondition {
+
+    private long value;
+
+    private WorkloadConditionOperator op;
+
+    public 
WorkloadConditionBeScanBytesFromRemoteStorage(WorkloadConditionOperator op, 
long value) {
+        this.op = op;
+        this.value = value;
+    }
+
+    @Override
+    public boolean eval(String strValue) {
+        // Currently this metric is evaluated only on BE, so FE-side matching 
always returns false.
+        return false;
+    }
+
+    public static WorkloadConditionBeScanBytesFromRemoteStorage 
createWorkloadCondition(
+            WorkloadConditionOperator op, String value) throws UserException {
+        long longValue = -1;
+        try {
+            longValue = Long.parseLong(value);
+            if (longValue < 0) {
+                throw new NumberFormatException();
+            }
+        } catch (NumberFormatException e) {
+            throw new UserException("invalid remote scan bytes value: " + 
value + ", it requires >= 0");
+        }
+        return new WorkloadConditionBeScanBytesFromRemoteStorage(op, 
longValue);
+    }
+
+    @Override
+    public WorkloadMetricType getMetricType() {
+        return WorkloadMetricType.BE_SCAN_BYTES_FROM_REMOTE_STORAGE;
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/resource/workloadschedpolicy/WorkloadMetricType.java
 
b/fe/fe-core/src/main/java/org/apache/doris/resource/workloadschedpolicy/WorkloadMetricType.java
index 93e612a85c2..5d83cb845f9 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/resource/workloadschedpolicy/WorkloadMetricType.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/resource/workloadschedpolicy/WorkloadMetricType.java
@@ -18,5 +18,6 @@
 package org.apache.doris.resource.workloadschedpolicy;
 
 public enum WorkloadMetricType {
-    USERNAME, QUERY_TIME, BE_SCAN_ROWS, BE_SCAN_BYTES, QUERY_BE_MEMORY_BYTES
+    // Keep the metric enum aligned with the workload policy metrics published 
to BE.
+    USERNAME, QUERY_TIME, BE_SCAN_ROWS, BE_SCAN_BYTES, 
BE_SCAN_BYTES_FROM_REMOTE_STORAGE, QUERY_BE_MEMORY_BYTES
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/resource/workloadschedpolicy/WorkloadSchedPolicyMgr.java
 
b/fe/fe-core/src/main/java/org/apache/doris/resource/workloadschedpolicy/WorkloadSchedPolicyMgr.java
index 3442c8a7789..07d4288b643 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/resource/workloadschedpolicy/WorkloadSchedPolicyMgr.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/resource/workloadschedpolicy/WorkloadSchedPolicyMgr.java
@@ -105,7 +105,9 @@ public class WorkloadSchedPolicyMgr extends MasterDaemon 
implements Writable, Gs
 
     public static final ImmutableSet<WorkloadMetricType> BE_METRIC_SET
             = new 
ImmutableSet.Builder<WorkloadMetricType>().add(WorkloadMetricType.BE_SCAN_ROWS)
-            
.add(WorkloadMetricType.BE_SCAN_BYTES).add(WorkloadMetricType.QUERY_TIME)
+            .add(WorkloadMetricType.BE_SCAN_BYTES)
+            // Treat remote scan bytes as a BE-only runtime metric.
+            
.add(WorkloadMetricType.BE_SCAN_BYTES_FROM_REMOTE_STORAGE).add(WorkloadMetricType.QUERY_TIME)
             
.add(WorkloadMetricType.QUERY_BE_MEMORY_BYTES).add(WorkloadMetricType.USERNAME).build();
 
     // used for convert fe type to thrift type
@@ -114,6 +116,9 @@ public class WorkloadSchedPolicyMgr extends MasterDaemon 
implements Writable, Gs
             .put(WorkloadMetricType.QUERY_TIME, TWorkloadMetricType.QUERY_TIME)
             .put(WorkloadMetricType.BE_SCAN_ROWS, 
TWorkloadMetricType.BE_SCAN_ROWS)
             .put(WorkloadMetricType.BE_SCAN_BYTES, 
TWorkloadMetricType.BE_SCAN_BYTES)
+            // Map the new FE metric enum to the appended thrift metric enum.
+            .put(WorkloadMetricType.BE_SCAN_BYTES_FROM_REMOTE_STORAGE,
+                    TWorkloadMetricType.BE_SCAN_BYTES_FROM_REMOTE_STORAGE)
             .put(WorkloadMetricType.QUERY_BE_MEMORY_BYTES, 
TWorkloadMetricType.QUERY_BE_MEMORY_BYTES)
             .put(WorkloadMetricType.USERNAME, 
TWorkloadMetricType.USERNAME).build();
     public static final ImmutableMap<WorkloadActionType, TWorkloadActionType> 
ACTION_MAP
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/resource/workloadschedpolicy/WorkloadSchedPolicyMgrTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/resource/workloadschedpolicy/WorkloadSchedPolicyMgrTest.java
index 7461cba03d5..6d4b6e2e6c3 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/resource/workloadschedpolicy/WorkloadSchedPolicyMgrTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/resource/workloadschedpolicy/WorkloadSchedPolicyMgrTest.java
@@ -21,6 +21,7 @@ import org.apache.doris.catalog.Env;
 import org.apache.doris.common.Config;
 import org.apache.doris.common.UserException;
 import org.apache.doris.persist.EditLog;
+import org.apache.doris.thrift.TWorkloadMetricType;
 
 import org.junit.After;
 import org.junit.Assert;
@@ -343,4 +344,49 @@ public class WorkloadSchedPolicyMgrTest {
                     e.getMessage().contains("non-cloud mode"));
         }
     }
+
+    @Test
+    public void testRemoteScanBytesMetricCanCreateBePolicy() throws 
UserException {
+        List<WorkloadConditionMeta> conditionMetas = new ArrayList<>();
+        // Verify the new metric string can be parsed into a BE-side workload 
condition.
+        conditionMetas.add(new 
WorkloadConditionMeta("be_scan_bytes_from_remote_storage", ">", "100"));
+        List<WorkloadActionMeta> actionMetas = new ArrayList<>();
+        actionMetas.add(new WorkloadActionMeta("cancel_query", ""));
+
+        mgr.createWorkloadSchedPolicy("policy_remote_scan_bytes", false, 
conditionMetas, actionMetas, null);
+
+        Assert.assertTrue(WorkloadSchedPolicyMgr.BE_METRIC_SET.contains(
+                WorkloadMetricType.BE_SCAN_BYTES_FROM_REMOTE_STORAGE));
+        
Assert.assertEquals(TWorkloadMetricType.BE_SCAN_BYTES_FROM_REMOTE_STORAGE,
+                
WorkloadSchedPolicyMgr.METRIC_MAP.get(WorkloadMetricType.BE_SCAN_BYTES_FROM_REMOTE_STORAGE));
+    }
+
+    @Test
+    public void testRemoteScanBytesMetricRejectsNegativeValue() throws 
UserException {
+        try {
+            // Reject negative thresholds for the remote scan bytes breaker.
+            WorkloadCondition.createWorkloadCondition(
+                    new 
WorkloadConditionMeta("be_scan_bytes_from_remote_storage", ">", "-1"));
+            Assert.fail("Should throw exception for negative remote scan bytes 
value");
+        } catch (UserException e) {
+            Assert.assertTrue(e.getMessage().contains("remote scan bytes"));
+        }
+    }
+
+    @Test
+    public void testRemoteScanBytesMetricCanNotMixWithFeAction() throws 
UserException {
+        try {
+            List<WorkloadConditionMeta> conditionMetas = new ArrayList<>();
+            // Validate the new metric follows the existing BE-only action 
compatibility rules.
+            conditionMetas.add(new 
WorkloadConditionMeta("be_scan_bytes_from_remote_storage", ">", "100"));
+            List<WorkloadActionMeta> actionMetas = new ArrayList<>();
+            actionMetas.add(new WorkloadActionMeta("set_session_variable", 
"workload_group=normal"));
+
+            
mgr.createWorkloadSchedPolicy("policy_remote_scan_bytes_with_fe_action", false, 
conditionMetas,
+                    actionMetas, null);
+            Assert.fail("Should throw exception for remote scan bytes metric 
with FE action");
+        } catch (UserException e) {
+            Assert.assertTrue(e.getMessage().contains("action and metric must 
run in FE together or run in BE together"));
+        }
+    }
 }
diff --git a/gensrc/thrift/BackendService.thrift 
b/gensrc/thrift/BackendService.thrift
index 676f116f003..faea4c46cea 100644
--- a/gensrc/thrift/BackendService.thrift
+++ b/gensrc/thrift/BackendService.thrift
@@ -297,7 +297,9 @@ enum TWorkloadMetricType {
     BE_SCAN_ROWS = 1,
     BE_SCAN_BYTES = 2,
     QUERY_BE_MEMORY_BYTES = 3,
-    USERNAME = 4
+    USERNAME = 4,
+    // Append the new enum value to keep existing metric ids stable across 
versions.
+    BE_SCAN_BYTES_FROM_REMOTE_STORAGE = 5
 }
 
 enum TCompareOperator {
diff --git 
a/regression-test/suites/external_table_p0/hive/test_workload_policy_remote_scan_bytes.groovy
 
b/regression-test/suites/external_table_p0/hive/test_workload_policy_remote_scan_bytes.groovy
new file mode 100644
index 00000000000..3b6cb46f1b3
--- /dev/null
+++ 
b/regression-test/suites/external_table_p0/hive/test_workload_policy_remote_scan_bytes.groovy
@@ -0,0 +1,143 @@
+// 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.
+
+suite("test_workload_policy_remote_scan_bytes", "p0,external") {
+    String enabled = context.config.otherConfigs.get("enableHiveTest")
+    if (enabled == null || !enabled.equalsIgnoreCase("true")) {
+        logger.info("disable Hive test.")
+        return
+    }
+
+    String hivePrefix = "hive2"
+    setHivePrefix(hivePrefix)
+
+    String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
+    String hmsPort = context.config.otherConfigs.get(hivePrefix + "HmsPort")
+    String catalogName = "test_workload_policy_remote_scan_bytes"
+    String workloadGroupName = "test_remote_scan_bytes_wg"
+    String policyName = "test_remote_scan_bytes_policy"
+    String invalidPolicyName = "test_remote_scan_bytes_invalid"
+
+    String forComputeGroupStr = ""
+    String currentCgName = ""
+    if (isCloudMode()) {
+        def clusters = sql "SHOW CLUSTERS"
+        assertTrue(!clusters.isEmpty())
+        String validCluster = clusters[0][0]
+        currentCgName = "${validCluster}."
+        forComputeGroupStr = " for ${validCluster} "
+    }
+
+    try {
+        sql """DROP WORKLOAD POLICY IF EXISTS ${policyName}"""
+        sql """DROP WORKLOAD POLICY IF EXISTS ${invalidPolicyName}"""
+        sql """DROP WORKLOAD GROUP IF EXISTS ${workloadGroupName} 
${forComputeGroupStr}"""
+        sql """DROP CATALOG IF EXISTS ${catalogName}"""
+
+        sql """
+            CREATE CATALOG ${catalogName} PROPERTIES (
+                'type' = 'hms',
+                'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hmsPort}',
+                'hadoop.username' = 'hive',
+                'ipc.client.fallback-to-simple-auth-allowed' = 'true'
+            )
+        """
+
+        String lineitemDb = "tpch1_parquet"
+        try {
+            def tables = sql """SHOW TABLES FROM ${catalogName}.${lineitemDb} 
LIKE 'lineitem'"""
+            if (tables.isEmpty()) {
+                throw new IllegalStateException("${lineitemDb}.lineitem does 
not exist")
+            }
+        } catch (Throwable ignored) {
+            lineitemDb = "tpch1"
+            def tables = sql """SHOW TABLES FROM ${catalogName}.${lineitemDb} 
LIKE 'lineitem'"""
+            assertFalse(tables.isEmpty(), "${catalogName} does not contain 
tpch1_parquet.lineitem or tpch1.lineitem")
+        }
+
+        sql """
+            CREATE WORKLOAD GROUP ${workloadGroupName} ${forComputeGroupStr}
+            PROPERTIES ('max_cpu_percent' = '100')
+        """
+
+        test {
+            sql """
+                CREATE WORKLOAD POLICY ${invalidPolicyName}
+                CONDITIONS(be_scan_bytes_from_remote_storage > -1)
+                ACTIONS(cancel_query)
+                PROPERTIES('enabled' = 'false')
+            """
+            exception "invalid remote scan bytes value"
+        }
+
+        sql """
+            CREATE WORKLOAD POLICY ${policyName}
+            CONDITIONS(be_scan_bytes_from_remote_storage > 1)
+            ACTIONS(cancel_query)
+            PROPERTIES(
+                'priority' = '100',
+                'workload_group' = '${currentCgName}${workloadGroupName}'
+            )
+        """
+
+        def policy = sql """
+            SELECT name, condition, action, priority, enabled, workload_group
+            FROM information_schema.workload_policy
+            WHERE name = '${policyName}'
+        """
+        assertEquals(1, policy.size())
+        assertEquals(policyName, policy[0][0])
+        
assertTrue(policy[0][1].toString().contains("be_scan_bytes_from_remote_storage 
> 1"))
+
+        // Wait for FE to publish the new BE-side policy before issuing the 
query.
+        Thread.sleep(15000)
+
+        Throwable queryException = null
+        sql """SET workload_group = '${workloadGroupName}'"""
+        sql """SET enable_file_cache = false"""
+        sql """SET enable_sql_cache = false"""
+        try {
+            sql """
+                SELECT SUM(SLEEP(1) + l_quantity)
+                FROM (
+                    SELECT l_quantity
+                    FROM ${catalogName}.${lineitemDb}.lineitem
+                    LIMIT 10
+                ) s
+            """
+        } catch (Throwable t) {
+            queryException = t
+        }
+        assertTrue(queryException != null, "query should be cancelled by 
remote scan bytes workload policy")
+        String msg = queryException.getMessage()
+        logger.info("Remote scan bytes workload policy cancel message: " + msg)
+        assertTrue(msg != null && msg.contains("cancelled by workload policy: 
${policyName}"),
+                "unexpected cancel policy: " + msg)
+        assertTrue(msg.contains("scan_bytes_from_remote_storage"),
+                "remote scan bytes counter is missing from cancel message: " + 
msg)
+    } finally {
+        try {
+            sql """SET workload_group = ''"""
+        } catch (Throwable t) {
+            logger.info("ignore reset workload_group failure: " + 
t.getMessage())
+        }
+        sql """DROP WORKLOAD POLICY IF EXISTS ${policyName}"""
+        sql """DROP WORKLOAD POLICY IF EXISTS ${invalidPolicyName}"""
+        sql """DROP WORKLOAD GROUP IF EXISTS ${workloadGroupName} 
${forComputeGroupStr}"""
+        sql """DROP CATALOG IF EXISTS ${catalogName}"""
+    }
+}


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

Reply via email to