FrankChen021 commented on code in PR #20151:
URL: https://github.com/apache/druid/pull/20151#discussion_r3981223355


##########
server/src/main/java/org/apache/druid/client/DirectDruidClient.java:
##########
@@ -444,7 +614,12 @@ private void setupResponseReadFailure(String msg, 
Throwable th)
                     @Override
                     public int read() throws IOException
                     {
-                      if (th != null) {
+                      if (th instanceof RuntimeException) {

Review Comment:
   [P2] Do not rethrow every runtime failure directly
   
   This branch now rethrows every RuntimeException captured by the response 
stream, not just QueryException. After a response has been handed to the 
caller, an ordinary mid-stream disconnect reaches this handler as Netty's 
ChannelException (and other handler failures can be plain RuntimeExceptions); 
failureException() returns it unchanged, while JsonParserIterator only 
normalizes IOException and QueryException. Those failures therefore escape as 
raw transport exceptions instead of the previous QueryInterruptedException with 
client-host context, changing downstream query error handling. Restrict direct 
rethrow to QueryException, or otherwise preserve the generic conversion for 
non-query runtime failures, and add a mid-stream disconnect regression test.



##########
server/src/main/java/org/apache/druid/client/JsonParserIterator.java:
##########
@@ -221,6 +229,39 @@ private void init()
     }
   }
 
+  /**
+   * Creates the parser for {@code is}, converting a {@link QueryException} 
that reaches here unwrapped (e.g. a
+   * later-chunk {@link QueryCapacityExceededException} DirectDruidClient 
rethrows as itself rather than as the
+   * cause of an {@link IOException}, since Jackson's stream bootstrapping can 
read ahead for encoding detection
+   * before any token is parsed) through {@link #convertException}, same as 
every other error path. Scoped to just
+   * this call, rather than caught around the whole {@link #init()} try block, 
so it never re-catches the
+   * QueryExceptions {@link #init()} throws explicitly after already calling 
{@link #convertException}.
+   */
+  private JsonParser createParser(InputStream is) throws IOException
+  {
+    try {
+      return objectMapper.getFactory().createParser(is);
+    }
+    catch (QueryException e) {
+      throw convertException(e);
+    }
+  }
+
+  /**
+   * Reads the next {@link JsonToken} from {@link #jp}, with the same 
unwrapped-{@link QueryException} handling as
+   * {@link #createParser}, for the same reason: a later-chunk failure can 
surface on any read from the underlying
+   * stream, not only the first.
+   */
+  private JsonToken readNextToken() throws IOException

Review Comment:
   [P2] Normalize structured-error read failures too
   
   The new helpers cover parser construction and nextToken(), but init() still 
calls jp.getCodec().readValue(jp, QueryException.class) directly in its 
START_OBJECT branch. If a chunked structured error begins with '{' and a later 
chunk triggers a timeout or scatter-gather limit, the direct QueryException 
from the stream escapes init() without convertException(), so it is not 
normalized to DirectDruidClient's target host. Wrap this readValue path as 
well, while avoiding a second conversion of exceptions already converted by 
init().



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