@@ -165,6 +165,7 @@ func (c *consumer) ConsumePartition(topic string, partition int32, offset int64)
165
165
messages : make (chan * ConsumerMessage , c .conf .ChannelBufferSize ),
166
166
errors : make (chan * ConsumerError , c .conf .ChannelBufferSize ),
167
167
feeder : make (chan * FetchResponse , 1 ),
168
+ leaderEpoch : invalidLeaderEpoch ,
168
169
preferredReadReplica : invalidPreferredReplicaID ,
169
170
trigger : make (chan none , 1 ),
170
171
dying : make (chan none ),
@@ -175,9 +176,8 @@ func (c *consumer) ConsumePartition(topic string, partition int32, offset int64)
175
176
return nil , err
176
177
}
177
178
178
- var leader * Broker
179
- var err error
180
- if leader , err = c .client .Leader (child .topic , child .partition ); err != nil {
179
+ leader , epoch , err := c .client .LeaderAndEpoch (child .topic , child .partition )
180
+ if err != nil {
181
181
return nil , err
182
182
}
183
183
@@ -188,6 +188,7 @@ func (c *consumer) ConsumePartition(topic string, partition int32, offset int64)
188
188
go withRecover (child .dispatcher )
189
189
go withRecover (child .responseFeeder )
190
190
191
+ child .leaderEpoch = epoch
191
192
child .broker = c .refBrokerConsumer (leader )
192
193
child .broker .input <- child
193
194
@@ -400,6 +401,7 @@ type partitionConsumer struct {
400
401
errors chan * ConsumerError
401
402
feeder chan * FetchResponse
402
403
404
+ leaderEpoch int32
403
405
preferredReadReplica int32
404
406
405
407
trigger , dying chan none
@@ -463,11 +465,11 @@ func (child *partitionConsumer) dispatcher() {
463
465
close (child .feeder )
464
466
}
465
467
466
- func (child * partitionConsumer ) preferredBroker () (* Broker , error ) {
468
+ func (child * partitionConsumer ) preferredBroker () (* Broker , int32 , error ) {
467
469
if child .preferredReadReplica >= 0 {
468
470
broker , err := child .consumer .client .Broker (child .preferredReadReplica )
469
471
if err == nil {
470
- return broker , nil
472
+ return broker , child . leaderEpoch , nil
471
473
}
472
474
Logger .Printf (
473
475
"consumer/%s/%d failed to find active broker for preferred read replica %d - will fallback to leader" ,
@@ -480,21 +482,21 @@ func (child *partitionConsumer) preferredBroker() (*Broker, error) {
480
482
}
481
483
482
484
// if preferred replica cannot be found fallback to leader
483
- return child .consumer .client .Leader (child .topic , child .partition )
485
+ return child .consumer .client .LeaderAndEpoch (child .topic , child .partition )
484
486
}
485
487
486
488
func (child * partitionConsumer ) dispatch () error {
487
489
if err := child .consumer .client .RefreshMetadata (child .topic ); err != nil {
488
490
return err
489
491
}
490
492
491
- broker , err := child .preferredBroker ()
493
+ broker , epoch , err := child .preferredBroker ()
492
494
if err != nil {
493
495
return err
494
496
}
495
497
498
+ child .leaderEpoch = epoch
496
499
child .broker = child .consumer .refBrokerConsumer (broker )
497
-
498
500
child .broker .input <- child
499
501
500
502
return nil
@@ -987,7 +989,7 @@ func (bc *brokerConsumer) handleResponses() {
987
989
child .responseResult = nil
988
990
989
991
if result == nil {
990
- if preferredBroker , err := child .preferredBroker (); err == nil {
992
+ if preferredBroker , _ , err := child .preferredBroker (); err == nil {
991
993
if bc .broker .ID () != preferredBroker .ID () {
992
994
// not an error but needs redispatching to consume from preferred replica
993
995
Logger .Printf (
@@ -1014,7 +1016,12 @@ func (bc *brokerConsumer) handleResponses() {
1014
1016
Logger .Printf ("consumer/%s/%d shutting down because %s\n " , child .topic , child .partition , result )
1015
1017
close (child .trigger )
1016
1018
delete (bc .subscriptions , child )
1017
- } else if errors .Is (result , ErrUnknownTopicOrPartition ) || errors .Is (result , ErrNotLeaderForPartition ) || errors .Is (result , ErrLeaderNotAvailable ) || errors .Is (result , ErrReplicaNotAvailable ) {
1019
+ } else if errors .Is (result , ErrUnknownTopicOrPartition ) ||
1020
+ errors .Is (result , ErrNotLeaderForPartition ) ||
1021
+ errors .Is (result , ErrLeaderNotAvailable ) ||
1022
+ errors .Is (result , ErrReplicaNotAvailable ) ||
1023
+ errors .Is (result , ErrFencedLeaderEpoch ) ||
1024
+ errors .Is (result , ErrUnknownLeaderEpoch ) {
1018
1025
// not an error, but does need redispatching
1019
1026
Logger .Printf ("consumer/broker/%d abandoned subscription to %s/%d because %s\n " ,
1020
1027
bc .broker .ID (), child .topic , child .partition , result )
@@ -1092,7 +1099,7 @@ func (bc *brokerConsumer) fetchNewMessages() (*FetchResponse, error) {
1092
1099
1093
1100
for child := range bc .subscriptions {
1094
1101
if ! child .IsPaused () {
1095
- request .AddBlock (child .topic , child .partition , child .offset , child .fetchSize )
1102
+ request .AddBlock (child .topic , child .partition , child .offset , child .fetchSize , child . leaderEpoch )
1096
1103
}
1097
1104
}
1098
1105
0 commit comments