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

morrySnow 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 7a8224fdfbe [feature](query) Support session level 
force_forward_all_queries (#66691)
7a8224fdfbe is described below

commit 7a8224fdfbe12f0595b35c5183be1a93003d82fd
Author: yujun <[email protected]>
AuthorDate: Fri Aug 14 14:19:34 2026 +0800

    [feature](query) Support session level force_forward_all_queries (#66691)
    
    ### What problem does this PR solve?
    
    Problem Summary:
    
    Some users query a freshness/health-check on a follower FE before every
    business request. When the follower is replaying a large journal, the
    freshness query result can lag and trigger business degradation.
    `Config.force_forward_all_queries = true` forces all queries to the
    master, but it is cluster-wide and too coarse when clients connect
    through a load balancer. The existing session variable
    `forward_to_master` does not participate in the ordinary SELECT
    forwarding decision.
    
    This PR adds a session-level variable `force_forward_all_queries`. A
    query is forwarded to the master when either
    `Config.force_forward_all_queries` or the session variable is enabled,
    so only the freshness queries need to opt in.
    
    ### Release note
    
    Added a session variable `force_forward_all_queries` to force queries of
    the session to be forwarded to the master FE.
---
 .../java/org/apache/doris/qe/SessionVariable.java  |  9 +++
 .../java/org/apache/doris/qe/StmtExecutor.java     |  3 +-
 .../doris/qe/ForceForwardAllQueriesTest.java       | 77 ++++++++++++++++++++++
 3 files changed, 88 insertions(+), 1 deletion(-)

diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
index 52ac4da4ff8..a1592de2947 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
@@ -214,6 +214,8 @@ public class SessionVariable implements Serializable, 
Writable {
 
     // if set to true, some of stmt will be forwarded to master FE to get 
result
     public static final String FORWARD_TO_MASTER = "forward_to_master";
+    // if set to true, all queries of this session will be forwarded to master 
FE
+    public static final String FORCE_FORWARD_ALL_QUERIES = 
"force_forward_all_queries";
     // user can set instance num after exchange, no need to be equal to nums 
of before exchange
     public static final String PARALLEL_EXCHANGE_INSTANCE_NUM = 
"parallel_exchange_instance_num";
     public static final String SHOW_HIDDEN_COLUMNS = "show_hidden_columns";
@@ -1568,6 +1570,9 @@ public class SessionVariable implements Serializable, 
Writable {
     @VarAttrDef.VarAttr(name = FORWARD_TO_MASTER)
     public boolean forwardToMaster = true;
 
+    @VarAttrDef.VarAttr(name = FORCE_FORWARD_ALL_QUERIES)
+    public boolean forceForwardAllQueries = false;
+
     // compatible with some mysql client connect, say DataGrip of JetBrains
     @VarAttrDef.VarAttr(name = EVENT_SCHEDULER)
     public String eventScheduler = "OFF";
@@ -4464,6 +4469,10 @@ public class SessionVariable implements Serializable, 
Writable {
         return forwardToMaster;
     }
 
+    public boolean isForceForwardAllQueries() {
+        return forceForwardAllQueries;
+    }
+
     // for unit test
 
     public String getEventScheduler() {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
index 17235a7bf15..902bbfb4646 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
@@ -463,7 +463,8 @@ public class StmtExecutor {
 
         // this is a query stmt, but this non-master FE can not read, forward 
it to master
         if (isQuery() && !Env.getCurrentEnv().isMaster()
-                && (!Env.getCurrentEnv().canRead() || debugForwardAllQueries() 
|| Config.force_forward_all_queries)) {
+                && (!Env.getCurrentEnv().canRead() || debugForwardAllQueries() 
|| Config.force_forward_all_queries
+                        || 
context.getSessionVariable().isForceForwardAllQueries())) {
             return true;
         }
 
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/qe/ForceForwardAllQueriesTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/qe/ForceForwardAllQueriesTest.java
new file mode 100644
index 00000000000..d0ca148e69d
--- /dev/null
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/qe/ForceForwardAllQueriesTest.java
@@ -0,0 +1,77 @@
+// 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.qe;
+
+import org.apache.doris.analysis.StatementBase;
+import org.apache.doris.catalog.Env;
+import org.apache.doris.common.Config;
+import org.apache.doris.common.jmockit.Deencapsulation;
+import org.apache.doris.ha.FrontendNodeType;
+import org.apache.doris.utframe.TestWithFeService;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class ForceForwardAllQueriesTest extends TestWithFeService {
+
+    @Test
+    public void testSessionForceForwardAllQueries() throws Exception {
+        Config.force_forward_all_queries = false;
+        Config.enable_bdbje_debug_mode = false;
+
+        Env env = Env.getCurrentEnv();
+        FrontendNodeType originalFeType = env.getFeType();
+        AtomicBoolean canRead = Deencapsulation.getField(env, "canRead");
+        Deencapsulation.setField(env, "feType", FrontendNodeType.FOLLOWER);
+        canRead.set(true);
+        try {
+            ConnectContext ctx = createDefaultCtx();
+            ctx.setThreadLocalInfo();
+            StatementBase parsedStmt = analyzeAndGetStmtByNereids("select 1", 
ctx);
+            StmtExecutor executor = new StmtExecutor(ctx, parsedStmt);
+
+            // neither session variable nor config enabled -> not forwarded
+            ctx.getSessionVariable().forceForwardAllQueries = false;
+            Config.force_forward_all_queries = false;
+            boolean forward = Deencapsulation.invoke(executor, 
"shouldForwardToMaster");
+            Assert.assertFalse(forward);
+
+            // session variable enabled -> forwarded
+            ctx.getSessionVariable().forceForwardAllQueries = true;
+            forward = Deencapsulation.invoke(executor, 
"shouldForwardToMaster");
+            Assert.assertTrue(forward);
+
+            // session variable disabled but config enabled -> forwarded
+            ctx.getSessionVariable().forceForwardAllQueries = false;
+            Config.force_forward_all_queries = true;
+            forward = Deencapsulation.invoke(executor, 
"shouldForwardToMaster");
+            Assert.assertTrue(forward);
+
+            // both disabled -> not forwarded
+            Config.force_forward_all_queries = false;
+            forward = Deencapsulation.invoke(executor, 
"shouldForwardToMaster");
+            Assert.assertFalse(forward);
+        } finally {
+            Deencapsulation.setField(env, "feType", originalFeType);
+            canRead.set(false);
+            Config.force_forward_all_queries = false;
+        }
+    }
+}


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

Reply via email to