This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 4d99c7e4d32 [feature](workload) Support remote scan bytes breaker in
workload policy (#64649)
4d99c7e4d32 is described below
commit 4d99c7e4d32a431c17b0e4a43553adf71103c0d9
Author: Wen Zhenghu <[email protected]>
AuthorDate: Wed Jul 1 11:32:54 2026 +0800
[feature](workload) Support remote scan bytes breaker in workload policy
(#64649)
### What problem does this PR solve?
Issue Number: None
Related PR: None
Problem Summary:
This PR adds a new workload policy condition
`be_scan_bytes_from_remote_storage`, which allows Doris to cancel
queries according to the amount of data read from remote storage by BE
scan tasks. This is useful for limiting external table queries that read
too much remote HDFS or object storage data.
Implementation summary:
- Add a new BE-side workload metric type in thrift for remote storage
scan bytes.
- Add FE workload policy parsing, validation, metadata mapping, and
replay support for `be_scan_bytes_from_remote_storage`.
- Add BE workload condition evaluation based on
`io_context()->scan_bytes_from_remote_storage()`.
- Add regression coverage using an existing Hive external `lineitem`
table.
### Release note
Support workload policy cancellation by BE remote storage scan bytes.
### Check List (For Author)
- Test:
- FE UT: passed
- BE UT: passed
- Regression test: passed, `test_workload_policy_remote_scan_bytes`
- Manual test: verified existing workload policy behavior and new remote
scan bytes cancellation on a deployed Doris instance
- Behavior changed: Yes. Add a new workload policy condition
`be_scan_bytes_from_remote_storage`.
- Does this need documentation: Yes. The workload policy condition list
should be updated.
---
.../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 d6cd95083c9..3867cec245f 100644
--- a/gensrc/thrift/BackendService.thrift
+++ b/gensrc/thrift/BackendService.thrift
@@ -312,7 +312,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]