AndrewJSchofield commented on code in PR #22270:
URL: https://github.com/apache/kafka/pull/22270#discussion_r3305075817


##########
clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerRebalanceListener.java:
##########
@@ -31,9 +31,23 @@
  * of the members changes. This can occur when processes die, new process 
instances are added or old instances come back to life after failure.
  * Partition re-assignments can also be triggered by changes affecting the 
subscribed topics (e.g. when the number of partitions is
  * administratively adjusted).
+ *
+ * <h3>Consumer-Aware Callbacks</h3>
+ *
+ * Each callback method has two variants: a one-argument form that receives 
only the affected partitions, and a
+ * two-argument form that additionally receives a {@link RebalanceConsumer} - 
a restricted view of the
+ * {@link Consumer} exposing only operations that are safe during a rebalance. 
The two-argument variants default
+ * to delegating to their one-argument counterparts, so existing 
implementations continue to work unchanged.
  * <p>
- * There are many uses for this functionality. One common use is saving 
offsets in a custom store. By saving offsets in
- * the {@link #onPartitionsRevoked(Collection)} call we can ensure that any 
time partition assignment changes
+ * When consumer access is needed during a rebalance (e.g. to commit offsets 
or seek to external positions),
+ * prefer overriding the two-argument variants and using the provided {@link 
RebalanceConsumer} instead of
+ * capturing the full {@code Consumer} reference externally. This avoids 
accidental use of operations like
+ * {@code poll()}, {@code close()}, or {@code subscribe()} that could corrupt 
consumer state mid-rebalance.
+ *
+ * <h3>Common Use Cases</h3>
+ *
+ * <p>There are many uses for this functionality. One common use is saving 
offsets in a custom store. By saving offsets in

Review Comment:
   nit: We tend not to use `<p>` just after the heading in the javadoc. Just 
for consistency. See `KafkaConsumer` for example.



##########
clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerRebalanceListener.java:
##########
@@ -48,27 +62,29 @@
  * whenever partition assignment changes.
  * <p>
  * Under normal conditions, if a partition is reassigned from one consumer to 
another, then the old consumer will
- * always invoke {@link #onPartitionsRevoked(Collection) onPartitionsRevoked} 
for that partition prior to the new consumer
- * invoking {@link #onPartitionsAssigned(Collection) onPartitionsAssigned} for 
the same partition. So if offsets or other state is saved in the
- * {@link #onPartitionsRevoked(Collection) onPartitionsRevoked} call by one 
consumer member, it will always be accessible by the time the
- * other consumer member taking over that partition and triggering its {@link 
#onPartitionsAssigned(Collection) onPartitionsAssigned} callback to load the 
state.
+ * always invoke {@link #onPartitionsRevoked(Collection, RebalanceConsumer) 
onPartitionsRevoked} for that partition
+ * prior to the new consumer invoking {@link #onPartitionsAssigned(Collection, 
RebalanceConsumer) onPartitionsAssigned}
+ * for the same partition. So if offsets or other state is saved durably in the
+ * {@link #onPartitionsRevoked(Collection, RebalanceConsumer) 
onPartitionsRevoked} callback by one consumer member,
+ * it will always be accessible by the time the other consumer member taking 
over that partition triggers its
+ * {@link #onPartitionsAssigned(Collection, RebalanceConsumer) 
onPartitionsAssigned} callback to load the state.
  * <p>
  * You can think of revocation as a graceful way to give up ownership of a 
partition. In some cases, the consumer may not have an opportunity to do so.
  * For example, if the session times out, then the partitions may be 
reassigned before we have a chance to revoke them gracefully.
- * For this case, we have a third callback {@link 
#onPartitionsLost(Collection)}. The difference between this function and
- * {@link #onPartitionsRevoked(Collection)} is that upon invocation of {@link 
#onPartitionsLost(Collection)}, the partitions
+ * For this case, we have a third callback {@link 
#onPartitionsLost(Collection, RebalanceConsumer)}. The difference between this 
function and
+ * {@link #onPartitionsRevoked(Collection, RebalanceConsumer)} is that upon 
invocation of {@link #onPartitionsLost(Collection, RebalanceConsumer)}, the 
partitions
  * may already be owned by some other members in the group and therefore users 
would not be able to commit its consumed offsets for example.
  * Users could implement these two functions differently (by default,
- * {@link #onPartitionsLost(Collection)} will be calling {@link 
#onPartitionsRevoked(Collection)} directly); for example, in the
- * {@link #onPartitionsLost(Collection)} we should not need to store the 
offsets since we know these partitions are no longer owned by the consumer
+ * {@link #onPartitionsLost(Collection, RebalanceConsumer)} will be calling 
{@link #onPartitionsRevoked(Collection, RebalanceConsumer)} directly); for 
example, in the
+ * {@link #onPartitionsLost(Collection, RebalanceConsumer)} we should not need 
to store the offsets since we know these partitions are no longer owned by the 
consumer
  * at that time.
  * <p>
- * During a rebalance event, the {@link #onPartitionsAssigned(Collection) 
onPartitionsAssigned} function will always be triggered exactly once when
- * the rebalance completes. That is, even if there is no newly assigned 
partitions for a consumer member, its {@link #onPartitionsAssigned(Collection) 
onPartitionsAssigned}
+ * During a rebalance event, the {@link #onPartitionsAssigned(Collection, 
RebalanceConsumer) onPartitionsAssigned} function will always be triggered 
exactly once when
+ * the rebalance completes. That is, even if there is no newly assigned 
partitions for a consumer member, its {@link #onPartitionsAssigned(Collection, 
RebalanceConsumer) onPartitionsAssigned}

Review Comment:
   nit: Grammar. There ARE no newly assigned partitions.



##########
clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerRebalanceListener.java:
##########
@@ -89,31 +105,31 @@
  * Here is pseudo-code for a callback implementation for saving offsets:
  * <pre>
  * {@code
- *   public class SaveOffsetsOnRebalance implements ConsumerRebalanceListener {
- *       private Consumer<?,?> consumer;
- *
- *       public SaveOffsetsOnRebalance(Consumer<?,?> consumer) {
- *           this.consumer = consumer;
- *       }
- *
- *       public void onPartitionsRevoked(Collection<TopicPartition> 
partitions) {
+ *   consumer.setConsumerRebalanceListener(new ConsumerRebalanceListener() {
+ *       @Override
+ *       public void onPartitionsRevoked(Collection<TopicPartition> 
partitions, RebalanceConsumer rebalanceConsumer) {
  *           // save the offsets in an external store using some custom code 
not described here
  *           for(TopicPartition partition: partitions)
- *              saveOffsetInExternalStore(consumer.position(partition));
+ *              
saveOffsetInExternalStore(rebalanceConsumer.position(partition));
  *       }
  *
+ *       @Override
  *       public void onPartitionsLost(Collection<TopicPartition> partitions) {

Review Comment:
   nit: In the example, I would override the two-argument variant.



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