davsclaus commented on code in PR #25732:
URL: https://github.com/apache/camel/pull/25732#discussion_r3869536078


##########
components/camel-kafka/src/main/java/org/apache/camel/component/kafka/KafkaFetchRecords.java:
##########
@@ -570,7 +570,7 @@ private boolean isReady() {
             return false;
         }
 
-        boolean ready = true;
+        boolean ready = false;

Review Comment:
   This default flip affects the existing, working classic-`KafkaConsumer` 
reflection path too, not just the new `AsyncKafkaConsumer` branch below: any 
future reflection failure (Kafka client renames `delegate`/`client` internals, 
or a stricter JDK module system blocks the access) now flips a healthy classic 
consumer to "not ready" instead of previously staying "ready". That may well be 
the right call for a readiness probe (fail closed on uncertainty), but please 
call it out explicitly as its own decision in the PR description, and confirm 
the existing health-check IT suite still passes with this stricter default.



##########
components/camel-kafka/src/main/java/org/apache/camel/component/kafka/KafkaFetchRecords.java:
##########
@@ -585,12 +585,17 @@ private boolean isReady() {
                             "Health-Check calling 
org.apache.kafka.clients.consumer.internals.ConsumerNetworkClient.hasReadyNode");
                     ready = nc.hasReadyNodes(System.currentTimeMillis());
                 }
+            } else {
+                // fail-closed: unknown consumer type (e.g. AsyncKafkaConsumer 
with group.protocol=consumer) -> not ready
+                // alternative would be to reflectively check 
AsyncKafkaConsumer.applicationEventHandler
+                ready = false;

Review Comment:
   Rather than hardcoding `ready = false` here, `AsyncKafkaConsumer`'s actual 
connectivity is reachable via reflection, mirroring the classic-consumer path 
above:
   
   ```java
   } else if (consumer.getClass().getName().equals(
           "org.apache.kafka.clients.consumer.internals.AsyncKafkaConsumer")) {
       // group.protocol=consumer (KIP-848) uses AsyncKafkaConsumer. Its 
network client
       // lives on a background thread, reachable via:
       // applicationEventHandler -> networkThread -> networkClientDelegate -> 
client
       Object handler = ReflectionHelper.getField(
               consumer.getClass().getDeclaredField("applicationEventHandler"), 
consumer);
       if (handler != null) {
           Object networkThread = ReflectionHelper.getField(
                   handler.getClass().getDeclaredField("networkThread"), 
handler);
           if (networkThread != null) {
               // networkClientDelegate is set once, on the consumer's 
background thread,
               // inside initializeResources(). It is not volatile, so there is 
a brief
               // window right after consumer startup where this reads null -- 
treat that
               // as "not yet ready" rather than an error.
               Object delegate = ReflectionHelper.getField(
                       
networkThread.getClass().getDeclaredField("networkClientDelegate"), 
networkThread);
               if (delegate != null) {
                   Object client = ReflectionHelper.getField(
                           delegate.getClass().getDeclaredField("client"), 
delegate);
                   if (client instanceof org.apache.kafka.clients.KafkaClient 
kc) {
                       LOG.trace(
                               "Health-Check calling 
org.apache.kafka.clients.KafkaClient.hasReadyNodes on AsyncKafkaConsumer's 
NetworkClientDelegate");
                       ready = kc.hasReadyNodes(System.currentTimeMillis());
                   }
               }
           }
       }
   } else {
       // fail-closed: genuinely unknown consumer type -> not ready
       ready = false;
   }
   ```
   
   Verified reachable against `kafka-clients:4.3.1` (the version pinned in this 
repo's `parent/pom.xml`) via `javap`/sources. Using 
`getClass().getName().equals(...)` rather than `instanceof` against the 
internals class literal avoids a hard compile-time dependency on a class with 
no compatibility guarantee.



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

Reply via email to