bitflicker64 commented on code in PR #3204:
URL: https://github.com/apache/hugegraph/pull/3204#discussion_r4004358083


##########
hugegraph-store/hg-store-client/src/main/java/org/apache/hugegraph/store/client/NodeTxExecutor.java:
##########
@@ -373,35 +391,75 @@ boolean ifAnyTrue(Supplier<Stream<HgPair<HgStoreNode, 
NodeTkv>>> nodeStreamSuppl
     }
 
     <T> Optional<T> retryingInvoke(Supplier<T> supplier) {
+        boolean[] deadlineRetried = {false};
         return IntStream.rangeClosed(0, NODE_MAX_RETRYING_TIMES).boxed()
                         .map(
                                 i -> {
+                                    if 
(Thread.currentThread().isInterrupted()) {
+                                        // The caller (e.g. a REST worker 
hitting
+                                        // restserver.request_timeout) gave 
up: stop
+                                        // retrying instead of holding its 
thread.
+                                        // InterruptedException as the root 
cause: the
+                                        // server's task cancel path 
recognises it
+                                        // (HugeException.isInterrupted()).
+                                        throw HgStoreClientException.of(
+                                                "Interrupted before retry " + 
i,
+                                                new InterruptedException());
+                                    }
                                     T buffer = null;
                                     try {
                                         buffer = supplier.get();
                                     } catch (Throwable t) {
-                                        if (i + 1 <= NODE_MAX_RETRYING_TIMES) {
-                                            try {
-                                                int sleepTime;
-                                                // The first three times try 
once every second
-                                                if (i < 3) {
-                                                    sleepTime = 1;
-                                                } else {
-                                                    // Subsequent incremental
-                                                    sleepTime = i - 1;
-                                                }
-                                                log.info("Waiting {} seconds " 
+
-                                                         "for the next try.",
-                                                         sleepTime);
-                                                Thread.sleep(sleepTime * 
1000L);
-                                            } catch (InterruptedException e) {
-                                                log.error("Failed to sleep", 
e);
+                                        Failure failure = classify(t);
+                                        if (failure != Failure.DEADLINE) {
+                                            // a different failure in between 
means the
+                                            // next deadline is not "in a row" 
again
+                                            deadlineRetried[0] = false;

Review Comment:
   ⚠️ Resetting the budget here lets one call block on up to six full 
deadlines, not two.
   
   Evidence:
   
   - The loop makes 11 attempts (`rangeClosed(0, NODE_MAX_RETRYING_TIMES)`). 
With D, X, D, X, ... D, where X is any fast retryable failure, every D gets 
retried: 6 × `grpc.timeout.seconds` (600 s on defaults) plus about 38 s of 
backoff.
   - That pattern is reachable. The DEADLINE sends NOT_WORK without the node 
(`NotifyingExecutor.java:249-254`), which reloads partition leaders. While raft 
is still electing, or PD still lists the stalled store, the next attempt can 
fail quickly with NOT_LEADER, a partition fault or UNAVAILABLE. That resets 
this flag, and the attempt after it waits on the stalled store again.
   - The description gives the bound as 2 × deadline + backoff. That holds only 
for back-to-back deadlines. The request-timeout interrupt still frees REST 
workers, but callers that are never interrupted (Gremlin jobs without 
`evaluationTimeout`, background tasks) can be held for about 10 minutes again.
   
   Could you bound deadlines per `retryingInvoke` call instead, e.g. count 
DEADLINE failures and stop at the second one even if something else failed in 
between? The javadoc on `Failure` and 
`testDeadlineBudgetResetsAfterAnotherFailure` would need updating to match.



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