github-actions[bot] commented on code in PR #68283:
URL: https://github.com/apache/doris/pull/68283#discussion_r4059188753


##########
fe/fe-core/src/main/java/org/apache/doris/qe/MasterOpExecutor.java:
##########
@@ -59,24 +66,52 @@ public MasterOpExecutor(ConnectContext ctx) {
 
     @Override
     public void execute() throws Exception {
-        super.execute();
-        waitOnReplaying();
+        synchronized (executionLock) {
+            if (cancelReason != null) {
+                throw new UserException("Forwarded statement was terminated 
before execution: "
+                        + cancelReason.getErrorMsg());
+            }
+            executionStarted = true;
+        }
+        try {
+            super.execute();
+            waitOnReplaying(result);
+        } finally {
+            synchronized (executionLock) {
+                executionFinished = true;
+            }
+        }
     }
 
     @Override
     public void cancel() throws Exception {
-        super.cancel();
-        waitOnReplaying();
+        cancel(Status.CANCELLED);
+    }
+
+    public void cancel(Status reason) throws Exception {
+        synchronized (executionLock) {
+            if (cancelReason == null) {
+                cancelReason = reason;
+            }
+            if (!executionStarted || executionFinished || cancelForwarded) {
+                return;
+            }
+            cancelForwarded = true;

Review Comment:
   [P1] Leave failed cancel delivery retryable. `cancelForwarded` is set before 
`forwardCancel()` succeeds, so a client-pool or transport failure leaves it 
true; every later KILL/timeout then returns at line 96 without sending anything 
while the statement RPC may still complete. Treat the flag as 
in-flight/delivered and restore a retryable state when the cancel send fails 
(duplicate cancel is safe), with a test where the first cancel send throws and 
the second succeeds.



##########
fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java:
##########
@@ -397,8 +399,45 @@ public class FrontendServiceImpl implements 
FrontendService.Iface {
     private ConcurrentHashMap<Long, AtomicInteger> 
multiTableFragmentInstanceIdIndexMap =
             new ConcurrentHashMap<>(64);
 
-    private final Map<TUniqueId, ConnectContext> proxyQueryIdToConnCtx =
-            new ConcurrentHashMap<>(64);
+    private final ProxyQueryRegistry proxyQueryRegistry = new 
ProxyQueryRegistry();
+
+    static final class ProxyQueryRegistry {
+        private final Object lock = new Object();
+        private final Map<TUniqueId, ConnectContext> contexts = new 
HashMap<>();
+        private final Cache<TUniqueId, Status> pendingCancels = 
CacheBuilder.newBuilder()
+                .maximumSize(1_000_000)
+                .expireAfterWrite(30, TimeUnit.MINUTES)
+                .build();
+
+        Runnable register(TUniqueId queryId, ConnectContext context) {
+            Status pendingCancel;
+            synchronized (lock) {
+                contexts.put(queryId, context);

Review Comment:
   [P1] Keep cancellation terminal across same-ID forward retries. 
`FEOpExecutor.forward()` can retry a query with the same request/query ID after 
a non-timeout transport failure. If attempt 1 is registered when cancellation 
arrives, `cancel()` stops only that context and stores no tombstone; after 
cleanup, the retry registers here with no terminal state and can execute/return 
rows. Overlapping attempts are also collapsed to one map entry. Retain 
cancellation for every registration in the query-ID retry lifetime (and track 
all live contexts, or fence the origin retry), with a 
cancel-C1-then-register-C2 test.



##########
fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java:
##########
@@ -1621,29 +1651,34 @@ public void executeAndSendResult(boolean 
isOutfileQuery, boolean isSendFields,
         // Where the result goes is the protocol's decision, made now, before 
the coordinator is
         // built: relayed by this frontend through the sender, or left on the 
backends for the
         // client to pull (context.isReturnResultFromLocal() is false then).
+        throwIfTerminated();

Review Comment:
   [P1] Recheck termination after coordinator publication and before OUTFILE 
cleanup. A TIMEOUT/KILL can pass this gate while the coordinator is being 
constructed; `setCoord()` then replays the terminal reason, but control still 
reaches `deleteExistingOutfileFilesInFe()` before `coordBase.exec()` rejects 
the cancelled coordinator. With `delete_existing_files`, that recursively 
removes the existing remote output and the cancelled query writes no 
replacement. Add the post-publication gate before deletion and a 
cancel-during-construction OUTFILE test.



##########
fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java:
##########
@@ -1248,10 +1287,8 @@ private TMasterOpResult 
handleForwardCancel(TMasterOpRequest params) throws TExc
         if (!params.isSetQueryId()) {
             throw new TException("a query id is needed to cancel a query");
         }
-        ConnectContext context = 
proxyQueryIdToConnCtx.get(params.getQueryId());
-        if (context != null) {
-            context.cancelQuery(new Status(TStatusCode.CANCELLED, "cancel 
query by forward request."));
-        }
+        proxyQueryRegistry.cancel(params.getQueryId(),

Review Comment:
   [P2] Preserve the first terminal reason across forwarded cancellation. The 
origin retains `TIMEOUT` and passes it to `MasterOpExecutor.cancel(reason)`, 
but the request carries only a boolean/query ID and this handler always 
rebuilds `CANCELLED`, so the master/BE, client message, and follower audit lose 
the timeout cause. Carry optional code/message fields with a rolling-version 
fallback, and recheck the retained reason after `masterOpExecutor.execute()` 
before hooks/result selection. Add an in-flight TIMEOUT propagation test.



-- 
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