m1a2st commented on code in PR #23348:
URL: https://github.com/apache/kafka/pull/23348#discussion_r3963788645


##########
clients/src/main/java/org/apache/kafka/clients/consumer/internals/AbstractHeartbeatRequestManager.java:
##########
@@ -245,27 +245,36 @@ public PollResult pollOnClose(long currentTimeMs) {
      * <p>Similarly, we may have to unblock the application thread to send a 
{@link AsyncPollEvent} to make sure
      * our poll timer will not expire while we are polling.
      *
-     * <p>When the member is {@link MemberState#UNSUBSCRIBED} (for example, 
with manual assignment),
-     * this returns {@code Long.MAX_VALUE} to indicate there is no next 
heartbeat to wait for,
-     * allowing the application thread to block for the full user-specified 
poll timeout rather than
-     * spinning in a busy loop.
+     * <p>When the member is {@link MemberState#UNSUBSCRIBED} or in the 
terminal {@link MemberState#FATAL} state, 
+     * this returns {@code Long.MAX_VALUE} to indicate there is no next 
heartbeat to wait for, allowing the application 
+     * thread to block for the full user-specified poll timeout rather than 
spinning in a busy loop.
      */
     @Override
     public long maximumTimeToWait(long currentTimeMs) {
         pollTimer.update(currentTimeMs);
-        if (membershipManager().state() == MemberState.UNSUBSCRIBED) {
+        MemberState state = membershipManager().state();
+        // No heartbeat can be sent in these states: UNSUBSCRIBED has nothing 
to heartbeat for,
+        // and FATAL is terminal. The fatal error has already been propagated 
to the
+        // application thread, so there is no need to wake it before its poll 
timeout expires.
+        if (state == MemberState.UNSUBSCRIBED || state == MemberState.FATAL) {
             return Long.MAX_VALUE;
         }
         if (pollTimer.isExpired()) {
             return 0L;
         }
-        // KAFKA-20253: mirror the guard in poll(). A heartbeat is only sent 
when the coordinator is known
-        // and the member is in a state that heartbeats. When the coordinator 
is unavailable (e.g. after a
-        // re-authentication failure) or the member should skip heartbeats 
(FATAL/FENCED/STALE/UNSUBSCRIBED),
-        // poll() returns EMPTY, so falling through to the timer-based 
branches below would return 0 (the
-        // heartbeat timer is left permanently expired) and busy-spin both the 
application and network threads.
+        // Mirror the guard in poll(). A heartbeat is only sent when the 
coordinator is known and the
+        // member is in a state that heartbeats. Otherwise, the timer-based 
branches below may return 0
+        // (the heartbeat timer remains permanently expired), causing both the 
application and network
+        // threads to busy-spin.

Review Comment:
   I have updated the comment



##########
clients/src/main/java/org/apache/kafka/clients/consumer/internals/AbstractHeartbeatRequestManager.java:
##########
@@ -245,27 +245,36 @@ public PollResult pollOnClose(long currentTimeMs) {
      * <p>Similarly, we may have to unblock the application thread to send a 
{@link AsyncPollEvent} to make sure
      * our poll timer will not expire while we are polling.
      *
-     * <p>When the member is {@link MemberState#UNSUBSCRIBED} (for example, 
with manual assignment),
-     * this returns {@code Long.MAX_VALUE} to indicate there is no next 
heartbeat to wait for,
-     * allowing the application thread to block for the full user-specified 
poll timeout rather than
-     * spinning in a busy loop.
+     * <p>When the member is {@link MemberState#UNSUBSCRIBED} or in the 
terminal {@link MemberState#FATAL} state, 
+     * this returns {@code Long.MAX_VALUE} to indicate there is no next 
heartbeat to wait for, allowing the application 
+     * thread to block for the full user-specified poll timeout rather than 
spinning in a busy loop.
      */
     @Override
     public long maximumTimeToWait(long currentTimeMs) {
         pollTimer.update(currentTimeMs);
-        if (membershipManager().state() == MemberState.UNSUBSCRIBED) {
+        MemberState state = membershipManager().state();
+        // No heartbeat can be sent in these states: UNSUBSCRIBED has nothing 
to heartbeat for,
+        // and FATAL is terminal. The fatal error has already been propagated 
to the
+        // application thread, so there is no need to wake it before its poll 
timeout expires.
+        if (state == MemberState.UNSUBSCRIBED || state == MemberState.FATAL) {
             return Long.MAX_VALUE;
         }
         if (pollTimer.isExpired()) {
             return 0L;
         }
-        // KAFKA-20253: mirror the guard in poll(). A heartbeat is only sent 
when the coordinator is known
-        // and the member is in a state that heartbeats. When the coordinator 
is unavailable (e.g. after a
-        // re-authentication failure) or the member should skip heartbeats 
(FATAL/FENCED/STALE/UNSUBSCRIBED),
-        // poll() returns EMPTY, so falling through to the timer-based 
branches below would return 0 (the
-        // heartbeat timer is left permanently expired) and busy-spin both the 
application and network threads.
+        // Mirror the guard in poll(). A heartbeat is only sent when the 
coordinator is known and the
+        // member is in a state that heartbeats. Otherwise, the timer-based 
branches below may return 0
+        // (the heartbeat timer remains permanently expired), causing both the 
application and network
+        // threads to busy-spin.

Review Comment:
   I have updated the comment.



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